You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by je...@apache.org on 2013/06/18 22:29:11 UTC

[07/10] THRIFT-2012 Modernizing Go

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/iostream_transport_test.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/iostream_transport_test.go b/lib/go/thrift/iostream_transport_test.go
new file mode 100644
index 0000000..15ea2d4
--- /dev/null
+++ b/lib/go/thrift/iostream_transport_test.go
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestStreamTransport(t *testing.T) {
+	trans := NewStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 1024)))
+	TransportTest(t, trans, trans)
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/json_protocol.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go
new file mode 100644
index 0000000..5e8453a
--- /dev/null
+++ b/lib/go/thrift/json_protocol.go
@@ -0,0 +1,556 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"encoding/base64"
+	"fmt"
+)
+
+const (
+	THRIFT_JSON_PROTOCOL_VERSION = 1
+)
+
+// for references to _ParseContext see tsimplejson_protocol.go
+
+// JSON protocol implementation for thrift.
+//
+// This protocol produces/consumes a simple output format
+// suitable for parsing by scripting languages.  It should not be
+// confused with the full-featured TJSONProtocol.
+//
+type TJSONProtocol struct {
+	*TSimpleJSONProtocol
+}
+
+// Constructor
+func NewTJSONProtocol(t TTransport) *TJSONProtocol {
+	v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)}
+	v.parseContextStack = append(v.parseContextStack, int(_CONTEXT_IN_TOPLEVEL))
+	v.dumpContext = append(v.dumpContext, int(_CONTEXT_IN_TOPLEVEL))
+	return v
+}
+
+// Factory
+type TJSONProtocolFactory struct{}
+
+func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+	return NewTJSONProtocol(trans)
+}
+
+func NewTJSONProtocolFactory() *TJSONProtocolFactory {
+	return &TJSONProtocolFactory{}
+}
+
+func (p *TJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error {
+	if e := p.OutputListBegin(); e != nil {
+		return e
+	}
+	if e := p.WriteI32(THRIFT_JSON_PROTOCOL_VERSION); e != nil {
+		return e
+	}
+	if e := p.WriteString(name); e != nil {
+		return e
+	}
+	if e := p.WriteByte(byte(typeId)); e != nil {
+		return e
+	}
+	if e := p.WriteI32(seqId); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TJSONProtocol) WriteMessageEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteStructBegin(name string) error {
+	if e := p.OutputObjectBegin(); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TJSONProtocol) WriteStructEnd() error {
+	return p.OutputObjectEnd()
+}
+
+func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
+	if e := p.WriteI16(id); e != nil {
+		return e
+	}
+	if e := p.OutputObjectBegin(); e != nil {
+		return e
+	}
+	if e := p.WriteString(p.TypeIdToString(typeId)); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TJSONProtocol) WriteFieldEnd() error {
+	return p.OutputObjectEnd()
+}
+
+func (p *TJSONProtocol) WriteFieldStop() error { return nil }
+
+func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
+	if e := p.OutputListBegin(); e != nil {
+		return e
+	}
+	if e := p.WriteString(p.TypeIdToString(keyType)); e != nil {
+		return e
+	}
+	if e := p.WriteString(p.TypeIdToString(valueType)); e != nil {
+		return e
+	}
+	return p.WriteI64(int64(size))
+}
+
+func (p *TJSONProtocol) WriteMapEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) error {
+	return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TJSONProtocol) WriteListEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) error {
+	return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TJSONProtocol) WriteSetEnd() error {
+	return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteBool(b bool) error {
+	return p.OutputBool(b)
+}
+
+func (p *TJSONProtocol) WriteByte(b byte) error {
+	return p.WriteI32(int32(b))
+}
+
+func (p *TJSONProtocol) WriteI16(v int16) error {
+	return p.WriteI32(int32(v))
+}
+
+func (p *TJSONProtocol) WriteI32(v int32) error {
+	return p.OutputI64(int64(v))
+}
+
+func (p *TJSONProtocol) WriteI64(v int64) error {
+	return p.OutputI64(int64(v))
+}
+
+func (p *TJSONProtocol) WriteDouble(v float64) error {
+	return p.OutputF64(v)
+}
+
+func (p *TJSONProtocol) WriteString(v string) error {
+	return p.OutputString(v)
+}
+
+func (p *TJSONProtocol) WriteBinary(v []byte) error {
+	// JSON library only takes in a string,
+	// not an arbitrary byte array, to ensure bytes are transmitted
+	// efficiently we must convert this into a valid JSON string
+	// therefore we use base64 encoding to avoid excessive escaping/quoting
+	if e := p.OutputPreValue(); e != nil {
+		return e
+	}
+	p.writer.Write(JSON_QUOTE_BYTES)
+	writer := base64.NewEncoder(base64.StdEncoding, p.writer)
+	if _, e := writer.Write(v); e != nil {
+		return NewTProtocolException(e)
+	}
+	writer.Close()
+	p.writer.Write(JSON_QUOTE_BYTES)
+	return p.OutputPostValue()
+}
+
+// Reading methods.
+
+func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
+	if isNull, err := p.ParseListBegin(); isNull || err != nil {
+		return name, typeId, seqId, err
+	}
+	version, err := p.ReadI32()
+	if err != nil {
+		return name, typeId, seqId, err
+	}
+	if version != THRIFT_JSON_PROTOCOL_VERSION {
+		e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION)
+		return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e)
+
+	}
+	if name, err = p.ReadString(); err != nil {
+		return name, typeId, seqId, err
+	}
+	bTypeId, err := p.ReadByte()
+	typeId = TMessageType(bTypeId)
+	if err != nil {
+		return name, typeId, seqId, err
+	}
+	if seqId, err = p.ReadI32(); err != nil {
+		return name, typeId, seqId, err
+	}
+	return name, typeId, seqId, nil
+}
+
+func (p *TJSONProtocol) ReadMessageEnd() error {
+	err := p.ParseListEnd()
+	return err
+}
+
+func (p *TJSONProtocol) ReadStructBegin() (name string, err error) {
+	_, err = p.ParseObjectStart()
+	return "", err
+}
+
+func (p *TJSONProtocol) ReadStructEnd() error {
+	return p.ParseObjectEnd()
+}
+
+func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, error) {
+	if p.reader.Buffered() < 1 {
+		return "", STOP, -1, nil
+	}
+	b, _ := p.reader.Peek(1)
+	if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
+		return "", STOP, -1, nil
+	}
+	fieldId, err := p.ReadI16()
+	if err != nil {
+		return "", STOP, fieldId, err
+	}
+	if _, err = p.ParseObjectStart(); err != nil {
+		return "", STOP, fieldId, err
+	}
+	sType, err := p.ReadString()
+	fType := p.StringToTypeId(sType)
+	return "", fType, fieldId, err
+}
+
+func (p *TJSONProtocol) ReadFieldEnd() error {
+	return p.ParseObjectEnd()
+}
+
+func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e error) {
+	if isNull, e := p.ParseListBegin(); isNull || e != nil {
+		return VOID, VOID, 0, e
+	}
+
+	// read keyType
+	sKeyType, e := p.ReadString()
+	keyType = p.StringToTypeId(sKeyType)
+	if e != nil {
+		return keyType, valueType, size, e
+	}
+
+	// read valueType
+	sValueType, e := p.ReadString()
+	valueType = p.StringToTypeId(sValueType)
+	if e != nil {
+		return keyType, valueType, size, e
+	}
+
+	// read size
+	iSize, err := p.ReadI64()
+	size = int(iSize)
+	return keyType, valueType, size, err
+}
+
+func (p *TJSONProtocol) ReadMapEnd() error {
+	return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e error) {
+	return p.ParseElemListBegin()
+}
+
+func (p *TJSONProtocol) ReadListEnd() error {
+	return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e error) {
+	return p.ParseElemListBegin()
+}
+
+func (p *TJSONProtocol) ReadSetEnd() error {
+	return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadBool() (bool, error) {
+	var value bool
+	if err := p.ParsePreValue(); err != nil {
+		return value, err
+	}
+	b, _ := p.reader.Peek(len(JSON_FALSE))
+	if len(b) > 0 {
+		switch b[0] {
+		case JSON_TRUE[0]:
+			if string(b[0:len(JSON_TRUE)]) == string(JSON_TRUE) {
+				p.reader.Read(b[0:len(JSON_TRUE)])
+				value = true
+			} else {
+				e := fmt.Errorf("Expected \"true\" but found: %s", string(b))
+				return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			break
+		case JSON_FALSE[0]:
+			if string(b[0:len(JSON_FALSE)]) == string(JSON_FALSE) {
+				p.reader.Read(b[0:len(JSON_FALSE)])
+				value = false
+			} else {
+				e := fmt.Errorf("Expected \"false\" but found: %s", string(b))
+				return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+			break
+		case JSON_NULL[0]:
+			if string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+				p.reader.Read(b[0:len(JSON_NULL)])
+				value = false
+			} else {
+				e := fmt.Errorf("Expected \"null\" but found: %s", string(b))
+				return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+			}
+		default:
+			e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(b))
+			return value, NewTProtocolExceptionWithType(INVALID_DATA, e)
+		}
+	}
+	return value, p.ParsePostValue()
+}
+
+func (p *TJSONProtocol) ReadByte() (byte, error) {
+	v, err := p.ReadI64()
+	return byte(v), err
+}
+
+func (p *TJSONProtocol) ReadI16() (int16, error) {
+	v, err := p.ReadI64()
+	return int16(v), err
+}
+
+func (p *TJSONProtocol) ReadI32() (int32, error) {
+	v, err := p.ReadI64()
+	return int32(v), err
+}
+
+func (p *TJSONProtocol) ReadI64() (int64, error) {
+	v, _, err := p.ParseI64()
+	return v, err
+}
+
+func (p *TJSONProtocol) ReadDouble() (float64, error) {
+	v, _, err := p.ParseF64()
+	return v, err
+}
+
+func (p *TJSONProtocol) ReadString() (string, error) {
+	var v string
+	if err := p.ParsePreValue(); err != nil {
+		return v, err
+	}
+	b, _ := p.reader.Peek(len(JSON_NULL))
+	if len(b) > 0 && b[0] == JSON_QUOTE {
+		p.reader.ReadByte()
+		value, err := p.ParseStringBody()
+		v = value
+		if err != nil {
+			return v, err
+		}
+	} else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+		_, err := p.reader.Read(b[0:len(JSON_NULL)])
+		if err != nil {
+			return v, NewTProtocolException(err)
+		}
+	} else {
+		e := fmt.Errorf("Expected a JSON string, found %s", string(b))
+		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	return v, p.ParsePostValue()
+}
+
+func (p *TJSONProtocol) ReadBinary() ([]byte, error) {
+	var v []byte
+	if err := p.ParsePreValue(); err != nil {
+		return nil, err
+	}
+	b, _ := p.reader.Peek(len(JSON_NULL))
+	if len(b) > 0 && b[0] == JSON_QUOTE {
+		p.reader.ReadByte()
+		value, err := p.ParseBase64EncodedBody()
+		v = value
+		if err != nil {
+			return v, err
+		}
+	} else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+		_, err := p.reader.Read(b[0:len(JSON_NULL)])
+		if err != nil {
+			return v, NewTProtocolException(err)
+		}
+	} else {
+		e := fmt.Errorf("Expected a JSON string, found %s", string(b))
+		return v, NewTProtocolExceptionWithType(INVALID_DATA, e)
+	}
+	return v, p.ParsePostValue()
+}
+
+func (p *TJSONProtocol) Flush() (err error) {
+	return NewTProtocolException(p.writer.Flush())
+}
+
+func (p *TJSONProtocol) Skip(fieldType TType) (err error) {
+	return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TJSONProtocol) Transport() TTransport {
+	return p.trans
+}
+
+func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error {
+	if e := p.OutputListBegin(); e != nil {
+		return e
+	}
+	if e := p.WriteString(p.TypeIdToString(elemType)); e != nil {
+		return e
+	}
+	if e := p.WriteI64(int64(size)); e != nil {
+		return e
+	}
+	return nil
+}
+
+
+func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) {
+	if isNull, e := p.ParseListBegin(); isNull || e != nil {
+		return VOID, 0, e
+	}
+	sElemType, err := p.ReadString()
+	elemType = p.StringToTypeId(sElemType)
+	if err != nil {
+		return elemType, size, err
+	}
+	nSize, err2 := p.ReadI64()
+	size = int(nSize)
+	return elemType, size, err2
+}
+
+func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e error) {
+	if isNull, e := p.ParseListBegin(); isNull || e != nil {
+		return VOID, 0, e
+	}
+	sElemType, err := p.ReadString()
+	elemType = p.StringToTypeId(sElemType)
+	if err != nil {
+		return elemType, size, err
+	}
+	nSize, err2 := p.ReadI64()
+	size = int(nSize)
+	return elemType, size, err2
+}
+
+func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) error {
+	if e := p.OutputListBegin(); e != nil {
+		return e
+	}
+	if e := p.OutputString(p.TypeIdToString(elemType)); e != nil {
+		return e
+	}
+	if e := p.OutputI64(int64(size)); e != nil {
+		return e
+	}
+	return nil
+}
+
+func (p *TJSONProtocol) TypeIdToString(fieldType TType) string {
+	switch byte(fieldType) {
+	case STOP:
+		return "stp"
+	case VOID:
+		return "v"
+	case BOOL:
+		return "tf"
+	case BYTE:
+		return "i8"
+	case DOUBLE:
+		return "dbl"
+	case I16:
+		return "i16"
+	case I32:
+		return "i32"
+	case I64:
+		return "i64"
+	case STRING:
+		return "str"
+	case STRUCT:
+		return "rec"
+	case MAP:
+		return "map"
+	case SET:
+		return "set"
+	case LIST:
+		return "lst"
+	case UTF16:
+		return "str"
+	}
+	return ""
+}
+
+func (p *TJSONProtocol) StringToTypeId(fieldType string) TType {
+	switch fieldType {
+	case "stp":
+		return TType(STOP)
+	case "v":
+		return TType(VOID)
+	case "tf":
+		return TType(BOOL)
+	case "i8":
+		return TType(BYTE)
+	case "dbl":
+		return TType(DOUBLE)
+	case "16":
+		return TType(I16)
+	case "i32":
+		return TType(I32)
+	case "i64":
+		return TType(I64)
+	case "str":
+		return TType(STRING)
+	case "rec":
+		return TType(STRUCT)
+	case "map":
+		return TType(MAP)
+	case "set":
+		return TType(SET)
+	case "lst":
+		return TType(LIST)
+	case "u16":
+		return TType(UTF16)
+	}
+	return TType(STOP)
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/json_protocol_test.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/json_protocol_test.go b/lib/go/thrift/json_protocol_test.go
new file mode 100644
index 0000000..cb626cc
--- /dev/null
+++ b/lib/go/thrift/json_protocol_test.go
@@ -0,0 +1,639 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"math"
+	"strconv"
+	"testing"
+)
+
+func TestWriteJSONProtocolBool(t *testing.T) {
+	thetype := "boolean"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	for _, value := range BOOL_VALUES {
+		if e := p.WriteBool(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if e := p.Flush(); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+		}
+		s := trans.String()
+		if s != fmt.Sprint(value) {
+			t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+		}
+		v := false
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolBool(t *testing.T) {
+	thetype := "boolean"
+	for _, value := range BOOL_VALUES {
+		trans := NewTMemoryBuffer()
+		p := NewTJSONProtocol(trans)
+		if value {
+			trans.Write(JSON_TRUE)
+		} else {
+			trans.Write(JSON_FALSE)
+		}
+		trans.Flush()
+		s := trans.String()
+		v, e := p.ReadBool()
+		if e != nil {
+			t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if v != value {
+			t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+		}
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+		trans.Close()
+	}
+}
+
+func TestWriteJSONProtocolByte(t *testing.T) {
+	thetype := "byte"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	for _, value := range BYTE_VALUES {
+		if e := p.WriteByte(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if e := p.Flush(); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+		}
+		s := trans.String()
+		if s != fmt.Sprint(value) {
+			t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+		}
+		v := byte(0)
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolByte(t *testing.T) {
+	thetype := "byte"
+	for _, value := range BYTE_VALUES {
+		trans := NewTMemoryBuffer()
+		p := NewTJSONProtocol(trans)
+		trans.WriteString(strconv.Itoa(int(value)))
+		trans.Flush()
+		s := trans.String()
+		v, e := p.ReadByte()
+		if e != nil {
+			t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if v != value {
+			t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+		}
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+		trans.Close()
+	}
+}
+
+func TestWriteJSONProtocolI16(t *testing.T) {
+	thetype := "int16"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	for _, value := range INT16_VALUES {
+		if e := p.WriteI16(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if e := p.Flush(); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+		}
+		s := trans.String()
+		if s != fmt.Sprint(value) {
+			t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+		}
+		v := int16(0)
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolI16(t *testing.T) {
+	thetype := "int16"
+	for _, value := range INT16_VALUES {
+		trans := NewTMemoryBuffer()
+		p := NewTJSONProtocol(trans)
+		trans.WriteString(strconv.Itoa(int(value)))
+		trans.Flush()
+		s := trans.String()
+		v, e := p.ReadI16()
+		if e != nil {
+			t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if v != value {
+			t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+		}
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+		trans.Close()
+	}
+}
+
+func TestWriteJSONProtocolI32(t *testing.T) {
+	thetype := "int32"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	for _, value := range INT32_VALUES {
+		if e := p.WriteI32(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if e := p.Flush(); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+		}
+		s := trans.String()
+		if s != fmt.Sprint(value) {
+			t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+		}
+		v := int32(0)
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolI32(t *testing.T) {
+	thetype := "int32"
+	for _, value := range INT32_VALUES {
+		trans := NewTMemoryBuffer()
+		p := NewTJSONProtocol(trans)
+		trans.WriteString(strconv.Itoa(int(value)))
+		trans.Flush()
+		s := trans.String()
+		v, e := p.ReadI32()
+		if e != nil {
+			t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if v != value {
+			t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+		}
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+		trans.Close()
+	}
+}
+
+func TestWriteJSONProtocolI64(t *testing.T) {
+	thetype := "int64"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	for _, value := range INT64_VALUES {
+		if e := p.WriteI64(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if e := p.Flush(); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+		}
+		s := trans.String()
+		if s != fmt.Sprint(value) {
+			t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+		}
+		v := int64(0)
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolI64(t *testing.T) {
+	thetype := "int64"
+	for _, value := range INT64_VALUES {
+		trans := NewTMemoryBuffer()
+		p := NewTJSONProtocol(trans)
+		trans.WriteString(strconv.FormatInt(value, 10))
+		trans.Flush()
+		s := trans.String()
+		v, e := p.ReadI64()
+		if e != nil {
+			t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if v != value {
+			t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+		}
+		if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+		}
+		trans.Reset()
+		trans.Close()
+	}
+}
+
+func TestWriteJSONProtocolDouble(t *testing.T) {
+	thetype := "double"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	for _, value := range DOUBLE_VALUES {
+		if e := p.WriteDouble(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if e := p.Flush(); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+		}
+		s := trans.String()
+		if math.IsInf(value, 1) {
+			if s != jsonQuote(JSON_INFINITY) {
+				t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_INFINITY))
+			}
+		} else if math.IsInf(value, -1) {
+			if s != jsonQuote(JSON_NEGATIVE_INFINITY) {
+				t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NEGATIVE_INFINITY))
+			}
+		} else if math.IsNaN(value) {
+			if s != jsonQuote(JSON_NAN) {
+				t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NAN))
+			}
+		} else {
+			if s != fmt.Sprint(value) {
+				t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+			}
+			v := float64(0)
+			if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+				t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+			}
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolDouble(t *testing.T) {
+	thetype := "double"
+	for _, value := range DOUBLE_VALUES {
+		trans := NewTMemoryBuffer()
+		p := NewTJSONProtocol(trans)
+		n := NewNumericFromDouble(value)
+		trans.WriteString(n.String())
+		trans.Flush()
+		s := trans.String()
+		v, e := p.ReadDouble()
+		if e != nil {
+			t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if math.IsInf(value, 1) {
+			if !math.IsInf(v, 1) {
+				t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+			}
+		} else if math.IsInf(value, -1) {
+			if !math.IsInf(v, -1) {
+				t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+			}
+		} else if math.IsNaN(value) {
+			if !math.IsNaN(v) {
+				t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+			}
+		} else {
+			if v != value {
+				t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+			}
+			if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+				t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+			}
+		}
+		trans.Reset()
+		trans.Close()
+	}
+}
+
+func TestWriteJSONProtocolString(t *testing.T) {
+	thetype := "string"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	for _, value := range STRING_VALUES {
+		if e := p.WriteString(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if e := p.Flush(); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+		}
+		s := trans.String()
+		if s[0] != '"' || s[len(s)-1] != '"' {
+			t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\""))
+		}
+		v := new(string)
+		if err := json.Unmarshal([]byte(s), v); err != nil || *v != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v)
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolString(t *testing.T) {
+	thetype := "string"
+	for _, value := range STRING_VALUES {
+		trans := NewTMemoryBuffer()
+		p := NewTJSONProtocol(trans)
+		trans.WriteString(jsonQuote(value))
+		trans.Flush()
+		s := trans.String()
+		v, e := p.ReadString()
+		if e != nil {
+			t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+		}
+		if v != value {
+			t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+		}
+		v1 := new(string)
+		if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value {
+			t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1)
+		}
+		trans.Reset()
+		trans.Close()
+	}
+}
+
+func TestWriteJSONProtocolBinary(t *testing.T) {
+	thetype := "binary"
+	value := protocol_bdata
+	b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata)))
+	base64.StdEncoding.Encode(b64value, value)
+	b64String := string(b64value)
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	if e := p.WriteBinary(value); e != nil {
+		t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+	}
+	if e := p.Flush(); e != nil {
+		t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error())
+	}
+	s := trans.String()
+	expectedString := fmt.Sprint("\"", b64String, "\"")
+	if s != expectedString {
+		t.Fatalf("Bad value for %s %v\n  wrote:  \"%v\"\nexpected: \"%v\"", thetype, value, s, expectedString)
+	}
+	v1, err := p.ReadBinary()
+	if err != nil {
+		t.Fatalf("Unable to read binary: %s", err.Error())
+	}
+	if len(v1) != len(value) {
+		t.Fatalf("Invalid value for binary\nexpected: \"%v\"\n   read: \"%v\"", value, v1)
+	}
+	for k, v := range value {
+		if v1[k] != v {
+			t.Fatalf("Invalid value for binary at %v\nexpected: \"%v\"\n   read: \"%v\"", k, v, v1[k])
+		}
+	}
+	trans.Close()
+}
+
+func TestReadJSONProtocolBinary(t *testing.T) {
+	thetype := "binary"
+	value := protocol_bdata
+	b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata)))
+	base64.StdEncoding.Encode(b64value, value)
+	b64String := string(b64value)
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	trans.WriteString(jsonQuote(b64String))
+	trans.Flush()
+	s := trans.String()
+	v, e := p.ReadBinary()
+	if e != nil {
+		t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error())
+	}
+	if len(v) != len(value) {
+		t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v))
+	}
+	for i := 0; i < len(v); i++ {
+		if v[i] != value[i] {
+			t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i])
+		}
+	}
+	v1 := new(string)
+	if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String {
+		t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1)
+	}
+	trans.Reset()
+	trans.Close()
+}
+
+func TestWriteJSONProtocolList(t *testing.T) {
+	thetype := "list"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	p.WriteListBegin(TType(DOUBLE), len(DOUBLE_VALUES))
+	for _, value := range DOUBLE_VALUES {
+		if e := p.WriteDouble(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+	}
+	p.WriteListEnd()
+	if e := p.Flush(); e != nil {
+		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
+	}
+	str := trans.String()
+	str1 := new([]interface{})
+	err := json.Unmarshal([]byte(str), str1)
+	if err != nil {
+		t.Fatalf("Unable to decode %s, wrote: %s", thetype, str)
+	}
+	l := *str1
+	if len(l) < 2 {
+		t.Fatalf("List must be at least of length two to include metadata")
+	}
+	if l[0] != "dbl" {
+		t.Fatal("Invalid type for list, expected: ", STRING, ", but was: ", l[0])
+	}
+	if int(l[1].(float64)) != len(DOUBLE_VALUES) {
+		t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1])
+	}
+	for k, value := range DOUBLE_VALUES {
+		s := l[k+2]
+		if math.IsInf(value, 1) {
+			if s.(string) != JSON_INFINITY {
+				t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str)
+			}
+		} else if math.IsInf(value, 0) {
+			if s.(string) != JSON_NEGATIVE_INFINITY {
+				t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str)
+			}
+		} else if math.IsNaN(value) {
+			if s.(string) != JSON_NAN {
+				t.Fatalf("Bad value for %s at index %v  %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str)
+			}
+		} else {
+			if s.(float64) != value {
+				t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s)
+			}
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestWriteJSONProtocolSet(t *testing.T) {
+	thetype := "set"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	p.WriteSetBegin(TType(DOUBLE), len(DOUBLE_VALUES))
+	for _, value := range DOUBLE_VALUES {
+		if e := p.WriteDouble(value); e != nil {
+			t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error())
+		}
+	}
+	p.WriteSetEnd()
+	if e := p.Flush(); e != nil {
+		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
+	}
+	str := trans.String()
+	str1 := new([]interface{})
+	err := json.Unmarshal([]byte(str), str1)
+	if err != nil {
+		t.Fatalf("Unable to decode %s, wrote: %s", thetype, str)
+	}
+	l := *str1
+	if len(l) < 2 {
+		t.Fatalf("Set must be at least of length two to include metadata")
+	}
+	if l[0] != "dbl" {
+		t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0])
+	}
+	if int(l[1].(float64)) != len(DOUBLE_VALUES) {
+		t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1])
+	}
+	for k, value := range DOUBLE_VALUES {
+		s := l[k+2]
+		if math.IsInf(value, 1) {
+			if s.(string) != JSON_INFINITY {
+				t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str)
+			}
+		} else if math.IsInf(value, 0) {
+			if s.(string) != JSON_NEGATIVE_INFINITY {
+				t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str)
+			}
+		} else if math.IsNaN(value) {
+			if s.(string) != JSON_NAN {
+				t.Fatalf("Bad value for %s at index %v  %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str)
+			}
+		} else {
+			if s.(float64) != value {
+				t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s)
+			}
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}
+
+func TestWriteJSONProtocolMap(t *testing.T) {
+	thetype := "map"
+	trans := NewTMemoryBuffer()
+	p := NewTJSONProtocol(trans)
+	p.WriteMapBegin(TType(I32), TType(DOUBLE), len(DOUBLE_VALUES))
+	for k, value := range DOUBLE_VALUES {
+		if e := p.WriteI32(int32(k)); e != nil {
+			t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.Error())
+		}
+		if e := p.WriteDouble(value); e != nil {
+			t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.Error())
+		}
+	}
+	p.WriteMapEnd()
+	if e := p.Flush(); e != nil {
+		t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error())
+	}
+	str := trans.String()
+	if str[0] != '[' || str[len(str)-1] != ']' {
+		t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES)
+	}
+	expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin()
+	if err != nil {
+		t.Fatalf("Error while reading map begin: %s", err.Error())
+	}
+	if expectedKeyType != I32 {
+		t.Fatal("Expected map key type ", I32, ", but was ", expectedKeyType)
+	}
+	if expectedValueType != DOUBLE {
+		t.Fatal("Expected map value type ", DOUBLE, ", but was ", expectedValueType)
+	}
+	if expectedSize != len(DOUBLE_VALUES) {
+		t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", expectedSize)
+	}
+	for k, value := range DOUBLE_VALUES {
+		ik, err := p.ReadI32()
+		if err != nil {
+			t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, ik, string(k), err.Error())
+		}
+		if int(ik) != k {
+			t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v", thetype, k, ik, k)
+		}
+		dv, err := p.ReadDouble()
+		if err != nil {
+			t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, dv, value, err.Error())
+		}
+		s := strconv.FormatFloat(dv, 'g', 10, 64)
+		if math.IsInf(value, 1) {
+			if !math.IsInf(dv, 1) {
+				t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_INFINITY))
+			}
+		} else if math.IsInf(value, 0) {
+			if !math.IsInf(dv, 0) {
+				t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY))
+			}
+		} else if math.IsNaN(value) {
+			if !math.IsNaN(dv) {
+				t.Fatalf("Bad value for %s at index %v  %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NAN))
+			}
+		} else {
+			expected := strconv.FormatFloat(value, 'g', 10, 64)
+			if s != expected {
+				t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected)
+			}
+			v := float64(0)
+			if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+				t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+			}
+		}
+		trans.Reset()
+	}
+	trans.Close()
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/memory_buffer.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/memory_buffer.go b/lib/go/thrift/memory_buffer.go
new file mode 100644
index 0000000..c48e089
--- /dev/null
+++ b/lib/go/thrift/memory_buffer.go
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"bytes"
+)
+
+// Memory buffer-based implementation of the TTransport interface.
+type TMemoryBuffer struct {
+	*bytes.Buffer
+	size int
+}
+
+type TMemoryBufferTransportFactory struct {
+	size int
+}
+
+func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport {
+	if trans != nil {
+		t, ok := trans.(*TMemoryBuffer)
+		if ok && t.size > 0 {
+			return NewTMemoryBufferLen(t.size)
+		}
+	}
+	return NewTMemoryBufferLen(p.size)
+}
+
+func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory {
+	return &TMemoryBufferTransportFactory{size: size}
+}
+
+func NewTMemoryBuffer() *TMemoryBuffer {
+	return &TMemoryBuffer{Buffer: &bytes.Buffer{}, size: 0}
+}
+
+func NewTMemoryBufferLen(size int) *TMemoryBuffer {
+	buf := make([]byte, 0, size)
+	return &TMemoryBuffer{Buffer: bytes.NewBuffer(buf), size: size}
+}
+
+func (p *TMemoryBuffer) IsOpen() bool {
+	return true
+}
+
+func (p *TMemoryBuffer) Open() error {
+	return nil
+}
+
+func (p *TMemoryBuffer) Peek() bool {
+	return p.IsOpen()
+}
+
+func (p *TMemoryBuffer) Close() error {
+	p.Buffer.Reset()
+	return nil
+}
+
+// Flushing a memory buffer is a no-op
+func (p *TMemoryBuffer) Flush() error {
+	return nil
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/memory_buffer_test.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/memory_buffer_test.go b/lib/go/thrift/memory_buffer_test.go
new file mode 100644
index 0000000..af2e8bf
--- /dev/null
+++ b/lib/go/thrift/memory_buffer_test.go
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"testing"
+)
+
+func TestMemoryBuffer(t *testing.T) {
+	trans := NewTMemoryBufferLen(1024)
+	TransportTest(t, trans, trans)
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/messagetype.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/messagetype.go b/lib/go/thrift/messagetype.go
new file mode 100644
index 0000000..25ab2e9
--- /dev/null
+++ b/lib/go/thrift/messagetype.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// Message type constants in the Thrift protocol.
+type TMessageType int32
+
+const (
+	INVALID_TMESSAGE_TYPE TMessageType = 0
+	CALL                  TMessageType = 1
+	REPLY                 TMessageType = 2
+	EXCEPTION             TMessageType = 3
+	ONEWAY                TMessageType = 4
+)

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/numeric.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/numeric.go b/lib/go/thrift/numeric.go
new file mode 100644
index 0000000..aa8daa9
--- /dev/null
+++ b/lib/go/thrift/numeric.go
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"math"
+	"strconv"
+)
+
+type Numeric interface {
+	Int64() int64
+	Int32() int32
+	Int16() int16
+	Byte() byte
+	Int() int
+	Float64() float64
+	Float32() float32
+	String() string
+	isNull() bool
+}
+
+type numeric struct {
+	iValue int64
+	dValue float64
+	sValue string
+	isNil  bool
+}
+
+var (
+	INFINITY          Numeric
+	NEGATIVE_INFINITY Numeric
+	NAN               Numeric
+	ZERO              Numeric
+	NUMERIC_NULL      Numeric
+)
+
+func NewNumericFromDouble(dValue float64) Numeric {
+	if math.IsInf(dValue, 1) {
+		return INFINITY
+	}
+	if math.IsInf(dValue, -1) {
+		return NEGATIVE_INFINITY
+	}
+	if math.IsNaN(dValue) {
+		return NAN
+	}
+	iValue := int64(dValue)
+	sValue := strconv.FormatFloat(dValue, 'g', 10, 64)
+	isNil := false
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromI64(iValue int64) Numeric {
+	dValue := float64(iValue)
+	sValue := string(iValue)
+	isNil := false
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromI32(iValue int32) Numeric {
+	dValue := float64(iValue)
+	sValue := string(iValue)
+	isNil := false
+	return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromString(sValue string) Numeric {
+	if sValue == INFINITY.String() {
+		return INFINITY
+	}
+	if sValue == NEGATIVE_INFINITY.String() {
+		return NEGATIVE_INFINITY
+	}
+	if sValue == NAN.String() {
+		return NAN
+	}
+	iValue, _ := strconv.ParseInt(sValue, 10, 64)
+	dValue, _ := strconv.ParseFloat(sValue, 64)
+	isNil := len(sValue) == 0
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromJSONString(sValue string, isNull bool) Numeric {
+	if isNull {
+		return NewNullNumeric()
+	}
+	if sValue == JSON_INFINITY {
+		return INFINITY
+	}
+	if sValue == JSON_NEGATIVE_INFINITY {
+		return NEGATIVE_INFINITY
+	}
+	if sValue == JSON_NAN {
+		return NAN
+	}
+	iValue, _ := strconv.ParseInt(sValue, 10, 64)
+	dValue, _ := strconv.ParseFloat(sValue, 64)
+	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull}
+}
+
+func NewNullNumeric() Numeric {
+	return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true}
+}
+
+func (p *numeric) Int64() int64 {
+	return p.iValue
+}
+
+func (p *numeric) Int32() int32 {
+	return int32(p.iValue)
+}
+
+func (p *numeric) Int16() int16 {
+	return int16(p.iValue)
+}
+
+func (p *numeric) Byte() byte {
+	return byte(p.iValue)
+}
+
+func (p *numeric) Int() int {
+	return int(p.iValue)
+}
+
+func (p *numeric) Float64() float64 {
+	return p.dValue
+}
+
+func (p *numeric) Float32() float32 {
+	return float32(p.dValue)
+}
+
+func (p *numeric) String() string {
+	return p.sValue
+}
+
+func (p *numeric) isNull() bool {
+	return p.isNil
+}
+
+func init() {
+	INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false}
+	NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false}
+	NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false}
+	ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false}
+	NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true}
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/processor.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/processor.go b/lib/go/thrift/processor.go
new file mode 100644
index 0000000..ca0d3fa
--- /dev/null
+++ b/lib/go/thrift/processor.go
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// A processor is a generic object which operates upon an input stream and
+// writes to some output stream.
+type TProcessor interface {
+	Process(in, out TProtocol) (bool, TException)
+}
+
+type TProcessorFunction interface {
+	Process(seqId int32, in, out TProtocol) (bool, TException)
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/processor_factory.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/processor_factory.go b/lib/go/thrift/processor_factory.go
new file mode 100644
index 0000000..9d645df
--- /dev/null
+++ b/lib/go/thrift/processor_factory.go
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// The default processor factory just returns a singleton
+// instance.
+type TProcessorFactory interface {
+	GetProcessor(trans TTransport) TProcessor
+}
+
+type tProcessorFactory struct {
+	processor TProcessor
+}
+
+func NewTProcessorFactory(p TProcessor) TProcessorFactory {
+	return &tProcessorFactory{processor: p}
+}
+
+func (p *tProcessorFactory) GetProcessor(trans TTransport) TProcessor {
+	return p.processor
+}
+
+/**
+ * The default processor factory just returns a singleton
+ * instance.
+ */
+type TProcessorFunctionFactory interface {
+	GetProcessorFunction(trans TTransport) TProcessorFunction
+}
+
+type tProcessorFunctionFactory struct {
+	processor TProcessorFunction
+}
+
+func NewTProcessorFunctionFactory(p TProcessorFunction) TProcessorFunctionFactory {
+	return &tProcessorFunctionFactory{processor: p}
+}
+
+func (p *tProcessorFunctionFactory) GetProcessorFunction(trans TTransport) TProcessorFunction {
+	return p.processor
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/protocol.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/protocol.go b/lib/go/thrift/protocol.go
new file mode 100644
index 0000000..87ceaad
--- /dev/null
+++ b/lib/go/thrift/protocol.go
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+const (
+	VERSION_MASK = 0xffff0000
+	VERSION_1    = 0x80010000
+)
+
+type TProtocol interface {
+	WriteMessageBegin(name string, typeId TMessageType, seqid int32) error
+	WriteMessageEnd() error
+	WriteStructBegin(name string) error
+	WriteStructEnd() error
+	WriteFieldBegin(name string, typeId TType, id int16) error
+	WriteFieldEnd() error
+	WriteFieldStop() error
+	WriteMapBegin(keyType TType, valueType TType, size int) error
+	WriteMapEnd() error
+	WriteListBegin(elemType TType, size int) error
+	WriteListEnd() error
+	WriteSetBegin(elemType TType, size int) error
+	WriteSetEnd() error
+	WriteBool(value bool) error
+	WriteByte(value byte) error
+	WriteI16(value int16) error
+	WriteI32(value int32) error
+	WriteI64(value int64) error
+	WriteDouble(value float64) error
+	WriteString(value string) error
+	WriteBinary(value []byte) error
+
+	ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error)
+	ReadMessageEnd() error
+	ReadStructBegin() (name string, err error)
+	ReadStructEnd() error
+	ReadFieldBegin() (name string, typeId TType, id int16, err error)
+	ReadFieldEnd() error
+	ReadMapBegin() (keyType TType, valueType TType, size int, err error)
+	ReadMapEnd() error
+	ReadListBegin() (elemType TType, size int, err error)
+	ReadListEnd() error
+	ReadSetBegin() (elemType TType, size int, err error)
+	ReadSetEnd() error
+	ReadBool() (value bool, err error)
+	ReadByte() (value byte, err error)
+	ReadI16() (value int16, err error)
+	ReadI32() (value int32, err error)
+	ReadI64() (value int64, err error)
+	ReadDouble() (value float64, err error)
+	ReadString() (value string, err error)
+	ReadBinary() (value []byte, err error)
+
+	Skip(fieldType TType) (err error)
+	Flush() (err error)
+
+	Transport() TTransport
+}
+
+// The maximum recursive depth the skip() function will traverse
+var MaxSkipDepth = 1<<31 - 1
+
+// Skips over the next data element from the provided input TProtocol object.
+func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) {
+	return Skip(prot, typeId, MaxSkipDepth)
+}
+
+// Skips over the next data element from the provided input TProtocol object.
+func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) {
+	switch fieldType {
+	case STOP:
+		return
+	case BOOL:
+		_, err = self.ReadBool()
+		return
+	case BYTE:
+		_, err = self.ReadByte()
+		return
+	case I16:
+		_, err = self.ReadI16()
+		return
+	case I32:
+		_, err = self.ReadI32()
+		return
+	case I64:
+		_, err = self.ReadI64()
+		return
+	case DOUBLE:
+		_, err = self.ReadDouble()
+		return
+	case STRING:
+		_, err = self.ReadString()
+		return
+	case STRUCT:
+		if _, err = self.ReadStructBegin(); err != nil {
+			return err
+		}
+		for {
+			_, typeId, _, _ := self.ReadFieldBegin()
+			if typeId == STOP {
+				break
+			}
+			Skip(self, typeId, maxDepth-1)
+			self.ReadFieldEnd()
+		}
+		return self.ReadStructEnd()
+	case MAP:
+		keyType, valueType, size, err := self.ReadMapBegin()
+		if err != nil {
+			return err
+		}
+		for i := 0; i < size; i++ {
+			Skip(self, keyType, maxDepth-1)
+			self.Skip(valueType)
+		}
+		return self.ReadMapEnd()
+	case SET:
+		elemType, size, err := self.ReadSetBegin()
+		if err != nil {
+			return err
+		}
+		for i := 0; i < size; i++ {
+			Skip(self, elemType, maxDepth-1)
+		}
+		return self.ReadSetEnd()
+	case LIST:
+		elemType, size, err := self.ReadListBegin()
+		if err != nil {
+			return err
+		}
+		for i := 0; i < size; i++ {
+			Skip(self, elemType, maxDepth-1)
+		}
+		return self.ReadListEnd()
+	}
+	return nil
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/protocol_exception.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/protocol_exception.go b/lib/go/thrift/protocol_exception.go
new file mode 100644
index 0000000..f1a164a
--- /dev/null
+++ b/lib/go/thrift/protocol_exception.go
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"encoding/base64"
+)
+
+// Thrift Protocol exception
+type TProtocolException interface {
+	TException
+	TypeId() int
+}
+
+const (
+	UNKNOWN_PROTOCOL_EXCEPTION = 0
+	INVALID_DATA               = 1
+	NEGATIVE_SIZE              = 2
+	SIZE_LIMIT                 = 3
+	BAD_VERSION                = 4
+	NOT_IMPLEMENTED            = 5
+)
+
+type tProtocolException struct {
+	typeId  int
+	message string
+}
+
+func (p *tProtocolException) TypeId() int {
+	return p.typeId
+}
+
+func (p *tProtocolException) String() string {
+	return p.message
+}
+
+func (p *tProtocolException) Error() string {
+	return p.message
+}
+
+func NewTProtocolException(err error) TProtocolException {
+	if err == nil {
+		return nil
+	}
+	if e,ok := err.(TProtocolException); ok {
+		return e
+	}
+	if _, ok := err.(base64.CorruptInputError); ok {
+		return &tProtocolException{INVALID_DATA, err.Error()}
+	}
+	return &tProtocolException{UNKNOWN_PROTOCOL_EXCEPTION, err.Error()}
+}
+
+func NewTProtocolExceptionWithType(errType int, err error) TProtocolException {
+	if err == nil {
+		return nil
+	}
+	return &tProtocolException{errType, err.Error()}
+}
+

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/protocol_factory.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/protocol_factory.go b/lib/go/thrift/protocol_factory.go
new file mode 100644
index 0000000..c40f796
--- /dev/null
+++ b/lib/go/thrift/protocol_factory.go
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// Factory interface for constructing protocol instances.
+type TProtocolFactory interface {
+	GetProtocol(trans TTransport) TProtocol
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/protocol_test.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/protocol_test.go b/lib/go/thrift/protocol_test.go
new file mode 100644
index 0000000..632098c
--- /dev/null
+++ b/lib/go/thrift/protocol_test.go
@@ -0,0 +1,458 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"bytes"
+	"io/ioutil"
+	"math"
+	"net"
+	"net/http"
+	"testing"
+)
+
+const PROTOCOL_BINARY_DATA_SIZE = 155
+
+var (
+	data           string // test data for writing
+	protocol_bdata []byte // test data for writing; same as data
+	BOOL_VALUES    []bool
+	BYTE_VALUES    []byte
+	INT16_VALUES   []int16
+	INT32_VALUES   []int32
+	INT64_VALUES   []int64
+	DOUBLE_VALUES  []float64
+	STRING_VALUES  []string
+)
+
+func init() {
+	protocol_bdata = make([]byte, PROTOCOL_BINARY_DATA_SIZE)
+	for i := 0; i < PROTOCOL_BINARY_DATA_SIZE; i++ {
+		protocol_bdata[i] = byte((i + 'a') % 255)
+	}
+	data = string(protocol_bdata)
+	BOOL_VALUES = []bool{false, true, false, false, true}
+	BYTE_VALUES = []byte{117, 0, 1, 32, 127, 128, 255}
+	INT16_VALUES = []int16{459, 0, 1, -1, -128, 127, 32767, -32768}
+	INT32_VALUES = []int32{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535}
+	INT64_VALUES = []int64{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535, 34359738481, -35184372088719, -9223372036854775808, 9223372036854775807}
+	DOUBLE_VALUES = []float64{459.3, 0.0, -1.0, 1.0, 0.5, 0.3333, 3.14159, 1.537e-38, 1.673e25, 6.02214179e23, -6.02214179e23, INFINITY.Float64(), NEGATIVE_INFINITY.Float64(), NAN.Float64()}
+	STRING_VALUES = []string{"", "a", "st[uf]f", "st,u:ff with spaces", "stuff\twith\nescape\\characters'...\"lots{of}fun</xml>"}
+}
+
+type HTTPEchoServer struct{}
+
+func (p *HTTPEchoServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	buf, err := ioutil.ReadAll(req.Body)
+	if err != nil {
+		w.WriteHeader(http.StatusBadRequest)
+		w.Write(buf)
+	} else {
+		w.WriteHeader(http.StatusOK)
+		w.Write(buf)
+	}
+}
+
+func HttpClientSetupForTest(t *testing.T) (net.Listener, net.Addr) {
+	addr, err := FindAvailableTCPServerPort(40000)
+	if err != nil {
+		t.Fatalf("Unable to find available tcp port addr: %s", err)
+		return nil, addr
+	}
+	l, err := net.Listen(addr.Network(), addr.String())
+	if err != nil {
+		t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err)
+		return l, addr
+	}
+	go http.Serve(l, &HTTPEchoServer{})
+	return l, addr
+}
+
+func ReadWriteProtocolTest(t *testing.T, protocolFactory TProtocolFactory) {
+	buf := bytes.NewBuffer(make([]byte, 0, 1024))
+	l, addr := HttpClientSetupForTest(t)
+	defer l.Close()
+	transports := []TTransportFactory{
+		NewTMemoryBufferTransportFactory(1024),
+		NewStreamTransportFactory(buf, buf, true),
+		NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)),
+		NewTHttpPostClientTransportFactory("http://" + addr.String()),
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteBool(t, p, trans)
+		trans.Close()
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteByte(t, p, trans)
+		trans.Close()
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteI16(t, p, trans)
+		trans.Close()
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteI32(t, p, trans)
+		trans.Close()
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteI64(t, p, trans)
+		trans.Close()
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteDouble(t, p, trans)
+		trans.Close()
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteString(t, p, trans)
+		trans.Close()
+	}
+	for _, tf := range transports {
+		trans := tf.GetTransport(nil)
+		p := protocolFactory.GetProtocol(trans)
+		ReadWriteBinary(t, p, trans)
+		trans.Close()
+	}
+
+	for _, tf := range transports {
+	  trans := tf.GetTransport(nil)
+	  p := protocolFactory.GetProtocol(trans);
+	  ReadWriteI64(t, p, trans);
+	  ReadWriteDouble(t, p, trans);
+	  ReadWriteBinary(t, p, trans);
+	  ReadWriteByte(t, p, trans);
+	  trans.Close()
+	}
+
+}
+
+func ReadWriteBool(t *testing.T, p TProtocol, trans TTransport) {
+	thetype := TType(BOOL)
+	thelen := len(BOOL_VALUES)
+	err := p.WriteListBegin(thetype, thelen)
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteBool", p, trans, err, thetype)
+	}
+	for k, v := range BOOL_VALUES {
+		err = p.WriteBool(v)
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error writing bool in list at index %d: %q", "ReadWriteBool", p, trans, err, k, v)
+		}
+	}
+	p.WriteListEnd()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES)
+	}
+	p.Flush()
+	thetype2, thelen2, err := p.ReadListBegin()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES)
+	}
+	_, ok := p.(*TSimpleJSONProtocol)
+	if !ok {
+		if thetype != thetype2 {
+			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteBool", p, trans, thetype, thetype2)
+		}
+		if thelen != thelen2 {
+			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteBool", p, trans, thelen, thelen2)
+		}
+	}
+	for k, v := range BOOL_VALUES {
+		value, err := p.ReadBool()
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error reading bool at index %d: %q", "ReadWriteBool", p, trans, err, k, v)
+		}
+		if v != value {
+			t.Errorf("%s: index %d %q %q %q != %q", "ReadWriteBool", k, p, trans, v, value)
+		}
+	}
+	err = p.ReadListEnd()
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteBool", p, trans, err)
+	}
+}
+
+func ReadWriteByte(t *testing.T, p TProtocol, trans TTransport) {
+	thetype := TType(BYTE)
+	thelen := len(BYTE_VALUES)
+	err := p.WriteListBegin(thetype, thelen)
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteByte", p, trans, err, thetype)
+	}
+	for k, v := range BYTE_VALUES {
+		err = p.WriteByte(v)
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error writing byte in list at index %d: %q", "ReadWriteByte", p, trans, err, k, v)
+		}
+	}
+	err = p.WriteListEnd()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
+	}
+	err = p.Flush()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error flushing list of bytes: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
+	}
+	thetype2, thelen2, err := p.ReadListBegin()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
+	}
+	_, ok := p.(*TSimpleJSONProtocol)
+	if !ok {
+		if thetype != thetype2 {
+			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteByte", p, trans, thetype, thetype2)
+		}
+		if thelen != thelen2 {
+			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteByte", p, trans, thelen, thelen2)
+		}
+	}
+	for k, v := range BYTE_VALUES {
+		value, err := p.ReadByte()
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error reading byte at index %d: %q", "ReadWriteByte", p, trans, err, k, v)
+		}
+		if v != value {
+			t.Errorf("%s: %T %T %d != %d", "ReadWriteByte", p, trans, v, value)
+		}
+	}
+	err = p.ReadListEnd()
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteByte", p, trans, err)
+	}
+}
+
+func ReadWriteI16(t *testing.T, p TProtocol, trans TTransport) {
+	thetype := TType(I16)
+	thelen := len(INT16_VALUES)
+	p.WriteListBegin(thetype, thelen)
+	for _, v := range INT16_VALUES {
+		p.WriteI16(v)
+	}
+	p.WriteListEnd()
+	p.Flush()
+	thetype2, thelen2, err := p.ReadListBegin()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI16", p, trans, err, INT16_VALUES)
+	}
+	_, ok := p.(*TSimpleJSONProtocol)
+	if !ok {
+		if thetype != thetype2 {
+			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI16", p, trans, thetype, thetype2)
+		}
+		if thelen != thelen2 {
+			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI16", p, trans, thelen, thelen2)
+		}
+	}
+	for k, v := range INT16_VALUES {
+		value, err := p.ReadI16()
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error reading int16 at index %d: %q", "ReadWriteI16", p, trans, err, k, v)
+		}
+		if v != value {
+			t.Errorf("%s: %T %T %d != %d", "ReadWriteI16", p, trans, v, value)
+		}
+	}
+	err = p.ReadListEnd()
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI16", p, trans, err)
+	}
+}
+
+func ReadWriteI32(t *testing.T, p TProtocol, trans TTransport) {
+	thetype := TType(I32)
+	thelen := len(INT32_VALUES)
+	p.WriteListBegin(thetype, thelen)
+	for _, v := range INT32_VALUES {
+		p.WriteI32(v)
+	}
+	p.WriteListEnd()
+	p.Flush()
+	thetype2, thelen2, err := p.ReadListBegin()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI32", p, trans, err, INT32_VALUES)
+	}
+	_, ok := p.(*TSimpleJSONProtocol)
+	if !ok {
+		if thetype != thetype2 {
+			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI32", p, trans, thetype, thetype2)
+		}
+		if thelen != thelen2 {
+			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI32", p, trans, thelen, thelen2)
+		}
+	}
+	for k, v := range INT32_VALUES {
+		value, err := p.ReadI32()
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error reading int32 at index %d: %q", "ReadWriteI32", p, trans, err, k, v)
+		}
+		if v != value {
+			t.Errorf("%s: %T %T %d != %d", "ReadWriteI32", p, trans, v, value)
+		}
+	}
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI32", p, trans, err)
+	}
+}
+
+func ReadWriteI64(t *testing.T, p TProtocol, trans TTransport) {
+	thetype := TType(I64)
+	thelen := len(INT64_VALUES)
+	p.WriteListBegin(thetype, thelen)
+	for _, v := range INT64_VALUES {
+		p.WriteI64(v)
+	}
+	p.WriteListEnd()
+	p.Flush()
+	thetype2, thelen2, err := p.ReadListBegin()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI64", p, trans, err, INT64_VALUES)
+	}
+	_, ok := p.(*TSimpleJSONProtocol)
+	if !ok {
+		if thetype != thetype2 {
+			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI64", p, trans, thetype, thetype2)
+		}
+		if thelen != thelen2 {
+			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI64", p, trans, thelen, thelen2)
+		}
+	}
+	for k, v := range INT64_VALUES {
+		value, err := p.ReadI64()
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error reading int64 at index %d: %q", "ReadWriteI64", p, trans, err, k, v)
+		}
+		if v != value {
+			t.Errorf("%s: %T %T %q != %q", "ReadWriteI64", p, trans, v, value)
+		}
+	}
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI64", p, trans, err)
+	}
+}
+
+func ReadWriteDouble(t *testing.T, p TProtocol, trans TTransport) {
+	thetype := TType(DOUBLE)
+	thelen := len(DOUBLE_VALUES)
+	p.WriteListBegin(thetype, thelen)
+	for _, v := range DOUBLE_VALUES {
+		p.WriteDouble(v)
+	}
+	p.WriteListEnd()
+	p.Flush()
+	wrotebuffer := ""
+	if memtrans, ok := trans.(*TMemoryBuffer); ok {
+		wrotebuffer = memtrans.String()
+	}
+	thetype2, thelen2, err := p.ReadListBegin()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error reading list: %q, wrote: %v", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES, wrotebuffer)
+	}
+	if thetype != thetype2 {
+		t.Errorf("%s: %T %T type %s != type %s", "ReadWriteDouble", p, trans, thetype, thetype2)
+	}
+	if thelen != thelen2 {
+		t.Errorf("%s: %T %T len %s != len %s", "ReadWriteDouble", p, trans, thelen, thelen2)
+	}
+	for k, v := range DOUBLE_VALUES {
+		value, err := p.ReadDouble()
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error reading double at index %d: %q", "ReadWriteDouble", p, trans, err, k, v)
+		}
+		if math.IsNaN(v) {
+			if !math.IsNaN(value) {
+				t.Errorf("%s: %T %T math.IsNaN(%q) != math.IsNaN(%q)", "ReadWriteDouble", p, trans, v, value)
+			}
+		} else if v != value {
+			t.Errorf("%s: %T %T %v != %q", "ReadWriteDouble", p, trans, v, value)
+		}
+	}
+	err = p.ReadListEnd()
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteDouble", p, trans, err)
+	}
+}
+
+func ReadWriteString(t *testing.T, p TProtocol, trans TTransport) {
+	thetype := TType(STRING)
+	thelen := len(STRING_VALUES)
+	p.WriteListBegin(thetype, thelen)
+	for _, v := range STRING_VALUES {
+		p.WriteString(v)
+	}
+	p.WriteListEnd()
+	p.Flush()
+	thetype2, thelen2, err := p.ReadListBegin()
+	if err != nil {
+		t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteString", p, trans, err, STRING_VALUES)
+	}
+	_, ok := p.(*TSimpleJSONProtocol)
+	if !ok {
+		if thetype != thetype2 {
+			t.Errorf("%s: %T %T type %s != type %s", "ReadWriteString", p, trans, thetype, thetype2)
+		}
+		if thelen != thelen2 {
+			t.Errorf("%s: %T %T len %s != len %s", "ReadWriteString", p, trans, thelen, thelen2)
+		}
+	}
+	for k, v := range STRING_VALUES {
+		value, err := p.ReadString()
+		if err != nil {
+			t.Errorf("%s: %T %T %q Error reading string at index %d: %q", "ReadWriteString", p, trans, err, k, v)
+		}
+		if v != value {
+			t.Errorf("%s: %T %T %d != %d", "ReadWriteString", p, trans, v, value)
+		}
+	}
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteString", p, trans, err)
+	}
+}
+
+func ReadWriteBinary(t *testing.T, p TProtocol, trans TTransport) {
+	v := protocol_bdata
+	p.WriteBinary(v)
+	p.Flush()
+	value, err := p.ReadBinary()
+	if err != nil {
+		t.Errorf("%s: %T %T Unable to read binary: %s", "ReadWriteBinary", p, trans, err.Error())
+	}
+	if len(v) != len(value) {
+		t.Errorf("%s: %T %T len(v) != len(value)... %d != %d", "ReadWriteBinary", p, trans, len(v), len(value))
+	} else {
+		for i := 0; i < len(v); i++ {
+			if v[i] != value[i] {
+				t.Errorf("%s: %T %T %s != %s", "ReadWriteBinary", p, trans, v, value)
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/server.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/server.go b/lib/go/thrift/server.go
new file mode 100644
index 0000000..f813fa3
--- /dev/null
+++ b/lib/go/thrift/server.go
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+type TServer interface {
+	ProcessorFactory() TProcessorFactory
+	ServerTransport() TServerTransport
+	InputTransportFactory() TTransportFactory
+	OutputTransportFactory() TTransportFactory
+	InputProtocolFactory() TProtocolFactory
+	OutputProtocolFactory() TProtocolFactory
+
+	// Starts the server
+	Serve() error
+	// Stops the server. This is optional on a per-implementation basis. Not
+	// all servers are required to be cleanly stoppable.
+	Stop() error
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/server_socket.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/server_socket.go b/lib/go/thrift/server_socket.go
new file mode 100644
index 0000000..1a01095
--- /dev/null
+++ b/lib/go/thrift/server_socket.go
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"net"
+	"time"
+)
+
+type TServerSocket struct {
+	listener      net.Listener
+	addr          net.Addr
+	clientTimeout time.Duration
+	interrupted   bool
+}
+
+func NewTServerSocket(listenAddr string) (*TServerSocket, error) {
+	return NewTServerSocketTimeout(listenAddr, 0)
+}
+
+func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) {
+	addr, err := net.ResolveTCPAddr("tcp", listenAddr)
+	if err != nil {
+		return nil, err
+	}
+	return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil
+}
+
+func (p *TServerSocket) Listen() error {
+	if p.IsListening() {
+		return nil
+	}
+	l, err := net.Listen(p.addr.Network(), p.addr.String())
+	if err != nil {
+		return err
+	}
+	p.listener = l
+	return nil
+}
+
+func (p *TServerSocket) Accept() (TTransport, error) {
+	if p.interrupted {
+		return nil, errTransportInterrupted
+	}
+	if p.listener == nil {
+		return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
+	}
+	conn, err := p.listener.Accept()
+	if err != nil {
+		return nil, NewTTransportExceptionFromError(err)
+	}
+	return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil
+}
+
+// Checks whether the socket is listening.
+func (p *TServerSocket) IsListening() bool {
+	return p.listener != nil
+}
+
+// Connects the socket, creating a new socket object if necessary.
+func (p *TServerSocket) Open() error {
+	if p.IsListening() {
+		return NewTTransportException(ALREADY_OPEN, "Server socket already open")
+	}
+	if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil {
+		return err
+	} else {
+		p.listener = l
+	}
+	return nil
+}
+
+func (p *TServerSocket) Addr() net.Addr {
+	return p.addr
+}
+
+func (p *TServerSocket) Close() error {
+	defer func() {
+		p.listener = nil
+	}()
+	if p.IsListening() {
+		return p.listener.Close()
+	}
+	return nil
+}
+
+func (p *TServerSocket) Interrupt() error {
+	p.interrupted = true
+	return nil
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/server_test.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/server_test.go b/lib/go/thrift/server_test.go
new file mode 100644
index 0000000..ffaf457
--- /dev/null
+++ b/lib/go/thrift/server_test.go
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+	"testing"
+)
+
+func TestNothing(t *testing.T) {
+
+}

http://git-wip-us.apache.org/repos/asf/thrift/blob/0e87c46c/lib/go/thrift/server_transport.go
----------------------------------------------------------------------
diff --git a/lib/go/thrift/server_transport.go b/lib/go/thrift/server_transport.go
new file mode 100644
index 0000000..51c40b6
--- /dev/null
+++ b/lib/go/thrift/server_transport.go
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+// Server transport. Object which provides client transports.
+type TServerTransport interface {
+	Listen() error
+	Accept() (TTransport, error)
+	Close() error
+
+	// Optional method implementation. This signals to the server transport
+	// that it should break out of any accept() or listen() that it is currently
+	// blocked on. This method, if implemented, MUST be thread safe, as it may
+	// be called from a different thread context than the other TServerTransport
+	// methods.
+	Interrupt() error
+}