You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by cl...@apache.org on 2011/02/20 03:39:21 UTC

svn commit: r1072478 [7/8] - in /thrift/trunk: ./ compiler/cpp/ compiler/cpp/src/generate/ lib/ lib/go/ lib/go/thrift/ test/ tutorial/go/ tutorial/go/src/

Added: thrift/trunk/lib/go/thrift/tsimple_json_protocol.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tsimple_json_protocol.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tsimple_json_protocol.go (added)
+++ thrift/trunk/lib/go/thrift/tsimple_json_protocol.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,1281 @@
+/*
+ * 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 (
+  "bufio"
+  "bytes"
+  "container/vector"
+  "encoding/base64"
+  "fmt"
+  "io"
+  "json"
+  "math"
+  "os"
+  "strconv"
+  "strings"
+)
+
+type _ParseContext int
+
+const (
+  _CONTEXT_IN_TOPLEVEL          _ParseContext = 1
+  _CONTEXT_IN_LIST_FIRST        _ParseContext = 2
+  _CONTEXT_IN_LIST              _ParseContext = 3
+  _CONTEXT_IN_OBJECT_FIRST      _ParseContext = 4
+  _CONTEXT_IN_OBJECT_NEXT_KEY   _ParseContext = 5
+  _CONTEXT_IN_OBJECT_NEXT_VALUE _ParseContext = 6
+)
+
+func (p _ParseContext) String() string {
+  switch p {
+  case _CONTEXT_IN_TOPLEVEL:
+    return "TOPLEVEL"
+  case _CONTEXT_IN_LIST_FIRST:
+    return "LIST-FIRST"
+  case _CONTEXT_IN_LIST:
+    return "LIST"
+  case _CONTEXT_IN_OBJECT_FIRST:
+    return "OBJECT-FIRST"
+  case _CONTEXT_IN_OBJECT_NEXT_KEY:
+    return "OBJECT-NEXT-KEY"
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    return "OBJECT-NEXT-VALUE"
+  }
+  return "UNKNOWN-PARSE-CONTEXT"
+}
+
+/**
+ * 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 TSimpleJSONProtocol struct {
+  //TProtocolBase;
+  trans TTransport
+
+  /**
+   * Stack of nested contexts that we may be in.
+   */
+  parseContextStack vector.IntVector
+  /**
+   * Stack of nested contexts that we may be in.
+   */
+  dumpContext vector.IntVector
+
+  /**
+   * Current context that we are in
+   */
+  writer TTransport
+  reader *bufio.Reader
+}
+
+/**
+ * Constructor
+ */
+func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol {
+  v := &TSimpleJSONProtocol{trans: t,
+    writer: t,
+    reader: bufio.NewReader(t),
+  }
+  v.parseContextStack.Push(int(_CONTEXT_IN_TOPLEVEL))
+  v.dumpContext.Push(int(_CONTEXT_IN_TOPLEVEL))
+  return v
+}
+
+/**
+ * Factory
+ */
+type TSimpleJSONProtocolFactory struct{}
+
+func (p *TSimpleJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+  return NewTSimpleJSONProtocol(trans)
+}
+
+func NewTSimpleJSONProtocolFactory() *TSimpleJSONProtocolFactory {
+  return &TSimpleJSONProtocolFactory{}
+}
+
+var (
+  JSON_COMMA                   []byte
+  JSON_COLON                   []byte
+  JSON_LBRACE                  []byte
+  JSON_RBRACE                  []byte
+  JSON_LBRACKET                []byte
+  JSON_RBRACKET                []byte
+  JSON_QUOTE                   byte
+  JSON_QUOTE_BYTES             []byte
+  JSON_NULL                    []byte
+  JSON_TRUE                    []byte
+  JSON_FALSE                   []byte
+  JSON_INFINITY                string
+  JSON_NEGATIVE_INFINITY       string
+  JSON_NAN                     string
+  JSON_INFINITY_BYTES          []byte
+  JSON_NEGATIVE_INFINITY_BYTES []byte
+  JSON_NAN_BYTES               []byte
+  json_nonbase_map_elem_bytes  []byte
+)
+
+func init() {
+  JSON_COMMA = []byte{','}
+  JSON_COLON = []byte{':'}
+  JSON_LBRACE = []byte{'{'}
+  JSON_RBRACE = []byte{'}'}
+  JSON_LBRACKET = []byte{'['}
+  JSON_RBRACKET = []byte{']'}
+  JSON_QUOTE = '"'
+  JSON_QUOTE_BYTES = []byte{'"'}
+  JSON_NULL = []byte{'n', 'u', 'l', 'l'}
+  JSON_TRUE = []byte{'t', 'r', 'u', 'e'}
+  JSON_FALSE = []byte{'f', 'a', 'l', 's', 'e'}
+  JSON_INFINITY = "Infinity"
+  JSON_NEGATIVE_INFINITY = "-Infinity"
+  JSON_NAN = "NaN"
+  JSON_INFINITY_BYTES = []byte{'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'}
+  JSON_NEGATIVE_INFINITY_BYTES = []byte{'-', 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'}
+  JSON_NAN_BYTES = []byte{'N', 'a', 'N'}
+  json_nonbase_map_elem_bytes = []byte{']', ',', '['}
+}
+
+func JsonQuote(s string) string {
+  b, _ := json.Marshal(s)
+  s1 := string(b)
+  return s1
+}
+
+func JsonUnquote(s string) (string, bool) {
+  s1 := new(string)
+  err := json.Unmarshal([]byte(s), s1)
+  return *s1, err == nil
+}
+
+
+func (p *TSimpleJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException {
+  if e := p.OutputListBegin(); 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 *TSimpleJSONProtocol) WriteMessageEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteStructBegin(name string) TProtocolException {
+  if e := p.OutputObjectBegin(); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteStructEnd() TProtocolException {
+  return p.OutputObjectEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+  if e := p.WriteString(name); e != nil {
+    return e
+  }
+  return nil
+  /*
+    	if e := p.OutputListBegin(); e != nil {
+        return e
+      }
+      if e := p.WriteByte(byte(typeId)); e != nil {
+        return e
+      }
+      return p.WriteI16(id)
+  */
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldEnd() TProtocolException {
+  //return p.OutputListEnd()
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldStop() TProtocolException { return nil }
+
+func (p *TSimpleJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(keyType)); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(valueType)); e != nil {
+    return e
+  }
+  return p.WriteI32(int32(size))
+}
+
+func (p *TSimpleJSONProtocol) WriteMapEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+  return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TSimpleJSONProtocol) WriteListEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+  return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TSimpleJSONProtocol) WriteSetEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteBool(b bool) TProtocolException {
+  return p.OutputBool(b)
+}
+
+func (p *TSimpleJSONProtocol) WriteByte(b byte) TProtocolException {
+  return p.WriteI32(int32(b))
+}
+
+func (p *TSimpleJSONProtocol) WriteI16(v int16) TProtocolException {
+  return p.WriteI32(int32(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteI32(v int32) TProtocolException {
+  return p.OutputI64(int64(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteI64(v int64) TProtocolException {
+  return p.OutputI64(int64(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteDouble(v float64) TProtocolException {
+  return p.OutputF64(v)
+}
+
+func (p *TSimpleJSONProtocol) WriteString(v string) TProtocolException {
+  return p.OutputString(v)
+}
+
+func (p *TSimpleJSONProtocol) WriteBinary(v []byte) TProtocolException {
+  // 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
+  }
+  if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  writer := base64.NewEncoder(base64.StdEncoding, p.writer)
+  if _, e := writer.Write(v); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  if e := writer.Close(); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  return p.OutputPostValue()
+}
+
+/**
+ * Reading methods.
+ */
+
+func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) {
+  if isNull, err := p.ParseListBegin(); isNull || err != nil {
+    return name, typeId, seqId, err
+  }
+  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 *TSimpleJSONProtocol) ReadMessageEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadStructBegin() (name string, err TProtocolException) {
+  _, err = p.ParseObjectStart()
+  return "", err
+}
+
+func (p *TSimpleJSONProtocol) ReadStructEnd() TProtocolException {
+  return p.ParseObjectEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return "", STOP, 0, err
+  }
+  if p.reader.Buffered() < 1 {
+    return "", STOP, 0, nil
+  }
+  b, _ := p.reader.Peek(1)
+  if len(b) > 0 {
+    switch b[0] {
+    case JSON_RBRACE[0]:
+      return "", STOP, 0, nil
+    case JSON_QUOTE:
+      p.reader.ReadByte()
+      name, err := p.ParseStringBody()
+      if err != nil {
+        return name, STOP, 0, err
+      }
+      return name, GENERIC, -1, p.ParsePostValue()
+      /*
+         if err = p.ParsePostValue(); err != nil {
+           return name, STOP, 0, err
+         }
+         if isNull, err := p.ParseListBegin(); isNull || err != nil {
+           return name, STOP, 0, err
+         }
+         bType, err := p.ReadByte()
+         thetype := TType(bType)
+         if err != nil {
+           return name, thetype, 0, err
+         }
+         id, err := p.ReadI16()
+         return name, thetype, id, err
+      */
+    }
+    return "", STOP, 0, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"}\" or '\"', but found: '", string(b), "'"))
+  }
+  return "", STOP, 0, NewTProtocolExceptionFromOsError(os.EOF)
+}
+
+func (p *TSimpleJSONProtocol) ReadFieldEnd() TProtocolException {
+  return nil
+  //return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e TProtocolException) {
+  if isNull, e := p.ParseListBegin(); isNull || e != nil {
+    return VOID, VOID, 0, e
+  }
+
+  // read keyType
+  bKeyType, e := p.ReadByte()
+  keyType = TType(bKeyType)
+  if e != nil {
+    return keyType, valueType, size, e
+  }
+
+  // read valueType
+  bValueType, e := p.ReadByte()
+  valueType = TType(bValueType)
+  if e != nil {
+    return keyType, valueType, size, e
+  }
+
+  // read size
+  iSize, err := p.ReadI64()
+  size = int(iSize)
+  return keyType, valueType, size, err
+}
+
+func (p *TSimpleJSONProtocol) ReadMapEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadListBegin() (elemType TType, size int, e TProtocolException) {
+  return p.ParseElemListBegin()
+}
+
+func (p *TSimpleJSONProtocol) ReadListEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadSetBegin() (elemType TType, size int, e TProtocolException) {
+  return p.ParseElemListBegin()
+}
+
+func (p *TSimpleJSONProtocol) ReadSetEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadBool() (bool, TProtocolException) {
+  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 {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"true\" but found: "+string(b))
+      }
+      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 {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"false\" but found: "+string(b))
+      }
+      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 {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"null\" but found: "+string(b))
+      }
+    default:
+      return value, NewTProtocolException(INVALID_DATA, "Expected \"true\", \"false\", or \"null\" but found: "+string(b))
+    }
+  }
+  return value, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ReadByte() (byte, TProtocolException) {
+  v, err := p.ReadI64()
+  return byte(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI16() (int16, TProtocolException) {
+  v, err := p.ReadI64()
+  return int16(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI32() (int32, TProtocolException) {
+  v, err := p.ReadI64()
+  return int32(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI64() (int64, TProtocolException) {
+  v, _, err := p.ParseI64()
+  return v, err
+}
+
+func (p *TSimpleJSONProtocol) ReadDouble() (float64, TProtocolException) {
+  v, _, err := p.ParseF64()
+  return v, err
+}
+
+func (p *TSimpleJSONProtocol) ReadString() (string, TProtocolException) {
+  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, NewTProtocolExceptionFromOsError(err)
+    }
+  } else {
+    return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b)))
+  }
+  return v, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, TProtocolException) {
+  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, NewTProtocolExceptionFromOsError(err)
+    }
+  } else {
+    return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b)))
+  }
+  return v, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) Flush() (err TProtocolException) {
+  return NewTProtocolExceptionFromOsError(p.writer.Flush())
+}
+
+func (p *TSimpleJSONProtocol) Skip(fieldType TType) (err TProtocolException) {
+  return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TSimpleJSONProtocol) Transport() TTransport {
+  return p.trans
+}
+
+
+func (p *TSimpleJSONProtocol) OutputPreValue() TProtocolException {
+  cxt := _ParseContext(p.dumpContext.Last())
+  switch cxt {
+  case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    if _, e := p.writer.Write(JSON_COMMA); e != nil {
+      return NewTProtocolExceptionFromOsError(e)
+    }
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    if _, e := p.writer.Write(JSON_COLON); e != nil {
+      return NewTProtocolExceptionFromOsError(e)
+    }
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputPostValue() TProtocolException {
+  cxt := _ParseContext(p.dumpContext.Last())
+  switch cxt {
+  case _CONTEXT_IN_LIST_FIRST:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_LIST))
+    break
+  case _CONTEXT_IN_OBJECT_FIRST:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_KEY:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_KEY))
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputBool(value bool) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  var v string
+  if value {
+    v = string(JSON_TRUE)
+  } else {
+    v = string(JSON_FALSE)
+  }
+  switch _ParseContext(p.dumpContext.Last()) {
+  case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    v = JsonQuote(v)
+  default:
+  }
+  if e := p.OutputStringData(v); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputNull() TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if _, e := p.writer.Write(JSON_NULL); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputF64(value float64) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  var v string
+  if math.IsNaN(value) {
+    v = string(JSON_QUOTE) + JSON_NAN + string(JSON_QUOTE)
+  } else if math.IsInf(value, 1) {
+    v = string(JSON_QUOTE) + JSON_INFINITY + string(JSON_QUOTE)
+  } else if math.IsInf(value, -1) {
+    v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE)
+  } else {
+    v = strconv.Ftoa64(value, 'g', -1)
+    switch _ParseContext(p.dumpContext.Last()) {
+    case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+      v = string(JSON_QUOTE) + v + string(JSON_QUOTE)
+    default:
+    }
+  }
+  if e := p.OutputStringData(v); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputI64(value int64) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  v := strconv.Itoa64(value)
+  switch _ParseContext(p.dumpContext.Last()) {
+  case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    v = JsonQuote(v)
+  default:
+  }
+  if e := p.OutputStringData(v); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputString(s string) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if e := p.OutputStringData(JsonQuote(s)); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputStringData(s string) TProtocolException {
+  _, e := io.Copyn(p.writer, strings.NewReader(s), int64(len(s)))
+  return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TSimpleJSONProtocol) OutputObjectBegin() TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if _, e := p.writer.Write(JSON_LBRACE); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_FIRST))
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputObjectEnd() TProtocolException {
+  if _, e := p.writer.Write(JSON_RBRACE); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Pop()
+  if e := p.OutputPostValue(); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputListBegin() TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if _, e := p.writer.Write(JSON_LBRACKET); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Push(int(_CONTEXT_IN_LIST_FIRST))
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputListEnd() TProtocolException {
+  if _, e := p.writer.Write(JSON_RBRACKET); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Pop()
+  if e := p.OutputPostValue(); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(elemType)); e != nil {
+    return e
+  }
+  if e := p.WriteI64(int64(size)); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) ParsePreValue() TProtocolException {
+  if e := p.readNonSignificantWhitespace(); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  cxt := _ParseContext(p.parseContextStack.Last())
+  if p.reader.Buffered() < 1 {
+    return nil
+  }
+  b, _ := p.reader.Peek(1)
+  switch cxt {
+  case _CONTEXT_IN_LIST:
+    if len(b) > 0 {
+      switch b[0] {
+      case JSON_RBRACKET[0]:
+        return nil
+      case JSON_COMMA[0]:
+        p.reader.ReadByte()
+        if e := p.readNonSignificantWhitespace(); e != nil {
+          return NewTProtocolExceptionFromOsError(e)
+        }
+        return nil
+      default:
+        return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"]\" or \",\" in list context, but found \"", string(b), "\""))
+      }
+    }
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_KEY:
+    if len(b) > 0 {
+      switch b[0] {
+      case JSON_RBRACE[0]:
+        return nil
+      case JSON_COMMA[0]:
+        p.reader.ReadByte()
+        if e := p.readNonSignificantWhitespace(); e != nil {
+          return NewTProtocolExceptionFromOsError(e)
+        }
+        return nil
+      default:
+        return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"}\" or \",\" in object context, but found \"", string(b), "\""))
+      }
+    }
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    if len(b) > 0 {
+      switch b[0] {
+      case JSON_COLON[0]:
+        p.reader.ReadByte()
+        if e := p.readNonSignificantWhitespace(); e != nil {
+          return NewTProtocolExceptionFromOsError(e)
+        }
+        return nil
+      default:
+        return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \":\" in object context, but found \"", string(b), "\""))
+      }
+    }
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) ParsePostValue() TProtocolException {
+  if e := p.readNonSignificantWhitespace(); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  cxt := _ParseContext(p.parseContextStack.Last())
+  switch cxt {
+  case _CONTEXT_IN_LIST_FIRST:
+    p.parseContextStack.Pop()
+    p.parseContextStack.Push(int(_CONTEXT_IN_LIST))
+    break
+  case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    p.parseContextStack.Pop()
+    p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    p.parseContextStack.Pop()
+    p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_NEXT_KEY))
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) readNonSignificantWhitespace() os.Error {
+  for p.reader.Buffered() > 0 {
+    b, _ := p.reader.Peek(1)
+    if len(b) < 1 {
+      return nil
+    }
+    switch b[0] {
+    case ' ', '\r', '\n', '\t':
+      p.reader.ReadByte()
+      continue
+    default:
+      break
+    }
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) ParseStringBody() (string, TProtocolException) {
+  line, err := p.reader.ReadString(JSON_QUOTE)
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  l := len(line)
+  // count number of escapes to see if we need to keep going
+  i := 1
+  for ; i < l; i++ {
+    if line[l-i-1] != '\\' {
+      break
+    }
+  }
+  if i&0x01 == 1 {
+    v, ok := JsonUnquote(string(JSON_QUOTE) + line)
+    if !ok {
+      return "", NewTProtocolExceptionFromOsError(err)
+    }
+    return v, nil
+  }
+  s, err := p.ParseQuotedStringBody()
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  str := string(JSON_QUOTE) + line + s
+  v, ok := JsonUnquote(str)
+  if !ok {
+    return "", NewTProtocolException(INVALID_DATA, "Unable to parse as JSON string "+str)
+  }
+  return v, nil
+}
+
+func (p *TSimpleJSONProtocol) ParseQuotedStringBody() (string, TProtocolException) {
+  line, err := p.reader.ReadString(JSON_QUOTE)
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  l := len(line)
+  // count number of escapes to see if we need to keep going
+  i := 1
+  for ; i < l; i++ {
+    if line[l-i-1] != '\\' {
+      break
+    }
+  }
+  if i&0x01 == 1 {
+    return line, nil
+  }
+  s, err := p.ParseQuotedStringBody()
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  v := line + s
+  return v, nil
+}
+
+func (p *TSimpleJSONProtocol) ParseBase64EncodedBody() ([]byte, TProtocolException) {
+  line, err := p.reader.ReadBytes(JSON_QUOTE)
+  if err != nil {
+    return line, NewTProtocolExceptionFromOsError(err)
+  }
+  line2 := line[0 : len(line)-1]
+  l := len(line2)
+  output := make([]byte, base64.StdEncoding.DecodedLen(l))
+  n, err := base64.StdEncoding.Decode(output, line2)
+  return output[0:n], NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return 0, false, err
+  }
+  var value int64
+  var isnull bool
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
+    p.reader.Read(b[0:len(JSON_NULL)])
+    isnull = true
+  } else {
+    num, err := p.readNumeric()
+    isnull = (num == nil)
+    if !isnull {
+      value = num.Int64()
+    }
+    if err != nil {
+      return value, isnull, err
+    }
+  }
+  return value, isnull, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return 0, false, err
+  }
+  var value float64
+  var isnull bool
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
+    p.reader.Read(b[0:len(JSON_NULL)])
+    isnull = true
+  } else {
+    num, err := p.readNumeric()
+    isnull = (num == nil)
+    if !isnull {
+      value = num.Float64()
+    }
+    if err != nil {
+      return value, isnull, err
+    }
+  }
+  return value, isnull, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return false, err
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) > 0 && b[0] == JSON_LBRACE[0] {
+    p.reader.ReadByte()
+    p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_FIRST))
+    return false, nil
+  } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+    return true, nil
+  }
+  return false, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected '{' or null, but found '", string(b), "'"))
+}
+
+func (p *TSimpleJSONProtocol) ParseObjectEnd() TProtocolException {
+  if isNull, err := p.readIfNull(); isNull || err != nil {
+    return err
+  }
+  cxt := _ParseContext(p.parseContextStack.Last())
+  if cxt != _CONTEXT_IN_OBJECT_FIRST && cxt != _CONTEXT_IN_OBJECT_NEXT_KEY {
+    return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected to be in the Object Context, but not in Object Context"))
+  }
+  line, err := p.reader.ReadString(JSON_RBRACE[0])
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  for _, char := range line {
+    switch char {
+    default:
+      return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expecting end of object \"}\", but found: \"", line, "\""))
+    case ' ', '\n', '\r', '\t', '}':
+      break
+    }
+  }
+  p.parseContextStack.Pop()
+  return p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseListBegin() (bool, TProtocolException) {
+  if e := p.ParsePreValue(); e != nil {
+    return false, e
+  }
+  b, e := p.reader.Peek(len(JSON_NULL))
+  if e == nil && len(b) >= 1 && b[0] == JSON_LBRACKET[0] {
+    p.parseContextStack.Push(int(_CONTEXT_IN_LIST_FIRST))
+    p.reader.ReadByte()
+    return false, nil
+  } else if e == nil && len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
+    return true, nil
+  }
+  return false, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Expected 'null' or '{', received '%q'", b))
+}
+
+func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e TProtocolException) {
+  if isNull, e := p.ParseListBegin(); isNull || e != nil {
+    return VOID, 0, e
+  }
+  bElemType, err := p.ReadByte()
+  elemType = TType(bElemType)
+  if err != nil {
+    return elemType, size, err
+  }
+  nSize, err2 := p.ReadI64()
+  size = int(nSize)
+  return elemType, size, err2
+}
+
+func (p *TSimpleJSONProtocol) ParseListEnd() TProtocolException {
+  if isNull, err := p.readIfNull(); isNull || err != nil {
+    return err
+  }
+  if _ParseContext(p.parseContextStack.Last()) != _CONTEXT_IN_LIST {
+    return NewTProtocolException(INVALID_DATA, "Expected to be in the List Context, but not in List Context")
+  }
+  line, err := p.reader.ReadString(JSON_RBRACKET[0])
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  for _, char := range line {
+    switch char {
+    default:
+      return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expecting end of list \"]\", but found: \"", line, "\""))
+    case ' ', '\n', '\r', '\t', int(JSON_RBRACKET[0]):
+      break
+    }
+  }
+  p.parseContextStack.Pop()
+  return p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) readSingleValue() (interface{}, TType, TProtocolException) {
+  e := p.readNonSignificantWhitespace()
+  if e != nil {
+    return nil, VOID, NewTProtocolExceptionFromOsError(e)
+  }
+  b, e := p.reader.Peek(10)
+  if len(b) > 0 {
+    c := b[0]
+    switch c {
+    case JSON_NULL[0]:
+      buf := make([]byte, len(JSON_NULL))
+      _, e := p.reader.Read(buf)
+      if e != nil {
+        return nil, VOID, NewTProtocolExceptionFromOsError(e)
+      }
+      if string(JSON_NULL) != string(buf) {
+        e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_NULL)+"' but found '"+string(buf)+"' while parsing JSON.")
+        return nil, VOID, e
+      }
+      return nil, VOID, nil
+    case JSON_QUOTE:
+      p.reader.ReadByte()
+      v, e := p.ParseStringBody()
+      if e != nil {
+        return v, UTF8, NewTProtocolExceptionFromOsError(e)
+      }
+      if v == JSON_INFINITY {
+        return INFINITY, DOUBLE, nil
+      } else if v == JSON_NEGATIVE_INFINITY {
+        return NEGATIVE_INFINITY, DOUBLE, nil
+      } else if v == JSON_NAN {
+        return NAN, DOUBLE, nil
+      }
+      return v, UTF8, nil
+    case JSON_TRUE[0]:
+      buf := make([]byte, len(JSON_TRUE))
+      _, e := p.reader.Read(buf)
+      if e != nil {
+        return true, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      if string(JSON_TRUE) != string(buf) {
+        e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_TRUE)+"' but found '"+string(buf)+"' while parsing JSON.")
+        return true, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      return true, BOOL, nil
+    case JSON_FALSE[0]:
+      buf := make([]byte, len(JSON_FALSE))
+      _, e := p.reader.Read(buf)
+      if e != nil {
+        return false, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      if string(JSON_FALSE) != string(buf) {
+        e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_FALSE)+"' but found '"+string(buf)+"' while parsing JSON.")
+        return false, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      return false, BOOL, nil
+    case JSON_LBRACKET[0]:
+      _, e := p.reader.ReadByte()
+      return make([]interface{}, 0), LIST, NewTProtocolExceptionFromOsError(e)
+    case JSON_LBRACE[0]:
+      _, e := p.reader.ReadByte()
+      return make(map[string]interface{}), STRUCT, NewTProtocolExceptionFromOsError(e)
+    case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-', JSON_INFINITY[0], JSON_NAN[0]:
+      // assume numeric
+      v, e := p.readNumeric()
+      return v, DOUBLE, e
+    default:
+      return nil, VOID, NewTProtocolException(INVALID_DATA, "Expected element in list but found '"+string(c)+"' while parsing JSON.")
+    }
+  }
+  return nil, VOID, NewTProtocolException(INVALID_DATA, "Cannot read a single element while parsing JSON.")
+
+}
+
+
+func (p *TSimpleJSONProtocol) readIfNull() (bool, TProtocolException) {
+  cont := true
+  for p.reader.Buffered() > 0 && cont {
+    b, _ := p.reader.Peek(1)
+    if len(b) < 1 {
+      return false, nil
+    }
+    switch b[0] {
+    default:
+      return false, nil
+    case JSON_NULL[0]:
+      cont = false
+      break
+    case ' ', '\n', '\r', '\t':
+      p.reader.ReadByte()
+      break
+    }
+  }
+  if p.reader.Buffered() == 0 {
+    return false, nil
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if string(b) == string(JSON_NULL) {
+    p.reader.Read(b[0:len(JSON_NULL)])
+    return true, nil
+  }
+  return false, nil
+}
+
+func (p *TSimpleJSONProtocol) readQuoteIfNext() {
+  if p.reader.Buffered() < 1 {
+    return
+  }
+  b, _ := p.reader.Peek(1)
+  if len(b) > 0 && b[0] == JSON_QUOTE {
+    p.reader.ReadByte()
+  }
+}
+
+func (p *TSimpleJSONProtocol) readNumeric() (Numeric, TProtocolException) {
+  isNull, err := p.readIfNull()
+  if isNull || err != nil {
+    return NUMERIC_NULL, err
+  }
+  hasDecimalPoint := false
+  nextCanBeSign := true
+  hasE := false
+  MAX_LEN := 40
+  buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN))
+  continueFor := true
+  inQuotes := false
+  for continueFor {
+    c, err := p.reader.ReadByte()
+    if err != nil {
+      if err == os.EOF {
+        break
+      }
+      return NUMERIC_NULL, NewTProtocolExceptionFromOsError(err)
+    }
+    switch c {
+    case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+      buf.WriteByte(c)
+      nextCanBeSign = false
+    case '.':
+      if hasDecimalPoint {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with multiple decimal points '%s.'", buf.String()))
+      }
+      if hasE {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with decimal points in the exponent '%s.'", buf.String()))
+      }
+      buf.WriteByte(c)
+      hasDecimalPoint, nextCanBeSign = true, false
+    case 'e', 'E':
+      if hasE {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c))
+      }
+      buf.WriteByte(c)
+      hasE, nextCanBeSign = true, true
+    case '-', '+':
+      if !nextCanBeSign {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprint("Negative sign within number"))
+      }
+      buf.WriteByte(c)
+      nextCanBeSign = false
+    case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]:
+      p.reader.UnreadByte()
+      continueFor = false
+    case JSON_NAN[0]:
+      if buf.Len() == 0 {
+        buffer := make([]byte, len(JSON_NAN))
+        buffer[0] = c
+        _, e := p.reader.Read(buffer[1:])
+        if e != nil {
+          return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e)
+        }
+        if JSON_NAN != string(buffer) {
+          e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_NAN+"' but found '"+string(buffer)+"' while parsing JSON.")
+          return NUMERIC_NULL, e
+        }
+        if inQuotes {
+          p.readQuoteIfNext()
+        }
+        return NAN, nil
+      } else {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c'", c))
+      }
+    case JSON_INFINITY[0]:
+      if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') {
+        buffer := make([]byte, len(JSON_INFINITY))
+        buffer[0] = c
+        _, e := p.reader.Read(buffer[1:])
+        if e != nil {
+          return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e)
+        }
+        if JSON_INFINITY != string(buffer) {
+          e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_INFINITY+"' but found '"+string(buffer)+"' while parsing JSON.")
+          return NUMERIC_NULL, e
+        }
+        if inQuotes {
+          p.readQuoteIfNext()
+        }
+        return INFINITY, nil
+      } else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] {
+        buffer := make([]byte, len(JSON_NEGATIVE_INFINITY))
+        buffer[0] = JSON_NEGATIVE_INFINITY[0]
+        buffer[1] = c
+        _, e := p.reader.Read(buffer[2:])
+        if e != nil {
+          return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e)
+        }
+        if JSON_NEGATIVE_INFINITY != string(buffer) {
+          e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_NEGATIVE_INFINITY+"' but found '"+string(buffer)+"' while parsing JSON.")
+          return NUMERIC_NULL, e
+        }
+        if inQuotes {
+          p.readQuoteIfNext()
+        }
+        return NEGATIVE_INFINITY, nil
+      } else {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String()))
+      }
+    case JSON_QUOTE:
+      if !inQuotes {
+        inQuotes = true
+      } else {
+        break
+      }
+    default:
+      return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c'", c))
+    }
+  }
+  if buf.Len() == 0 {
+    return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprint("Unable to parse number from empty string ''"))
+  }
+  return NewNumericFromJSONString(buf.String(), false), nil
+}

Added: thrift/trunk/lib/go/thrift/tsimple_json_protocol_test.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tsimple_json_protocol_test.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tsimple_json_protocol_test.go (added)
+++ thrift/trunk/lib/go/thrift/tsimple_json_protocol_test.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,662 @@
+/*
+ * 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_test
+
+import (
+  . "thrift"
+  "encoding/base64"
+  "fmt"
+  "json"
+  "math"
+  "strconv"
+  "strings"
+  "testing"
+)
+
+func TestWriteSimpleJSONProtocolBool(t *testing.T) {
+  thetype := "boolean"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    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 TestReadSimpleJSONProtocolBool(t *testing.T) {
+  thetype := "boolean"
+  for _, value := range BOOL_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(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.String())
+    }
+    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 TestWriteSimpleJSONProtocolByte(t *testing.T) {
+  thetype := "byte"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    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 TestReadSimpleJSONProtocolByte(t *testing.T) {
+  thetype := "byte"
+  for _, value := range BYTE_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(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.String())
+    }
+    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 TestWriteSimpleJSONProtocolI16(t *testing.T) {
+  thetype := "int16"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    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 TestReadSimpleJSONProtocolI16(t *testing.T) {
+  thetype := "int16"
+  for _, value := range INT16_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(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.String())
+    }
+    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 TestWriteSimpleJSONProtocolI32(t *testing.T) {
+  thetype := "int32"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    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 TestReadSimpleJSONProtocolI32(t *testing.T) {
+  thetype := "int32"
+  for _, value := range INT32_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(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.String())
+    }
+    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 TestWriteSimpleJSONProtocolI64(t *testing.T) {
+  thetype := "int64"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    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 TestReadSimpleJSONProtocolI64(t *testing.T) {
+  thetype := "int64"
+  for _, value := range INT64_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa64(value))
+    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.String())
+    }
+    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 TestWriteSimpleJSONProtocolDouble(t *testing.T) {
+  thetype := "double"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    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 TestReadSimpleJSONProtocolDouble(t *testing.T) {
+  thetype := "double"
+  for _, value := range DOUBLE_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(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.String())
+    }
+    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 TestWriteSimpleJSONProtocolString(t *testing.T) {
+  thetype := "string"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    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 TestReadSimpleJSONProtocolString(t *testing.T) {
+  thetype := "string"
+  for _, value := range STRING_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(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.String())
+    }
+    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 TestWriteSimpleJSONProtocolBinary(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 := NewTSimpleJSONProtocol(trans)
+  if e := p.WriteBinary(value); e != nil {
+    t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+  }
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+  }
+  s := trans.String()
+  if s != fmt.Sprint("\"", b64String, "\"") {
+    t.Fatalf("Bad value for %s %v\n  wrote: %v\nexpected: %v", thetype, value, s, "\""+b64String+"\"")
+  }
+  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.Close()
+}
+
+func TestReadSimpleJSONProtocolBinary(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 := NewTSimpleJSONProtocol(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.String())
+  }
+  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 TestWriteSimpleJSONProtocolList(t *testing.T) {
+  thetype := "list"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+  }
+  p.WriteListEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  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 int(l[0].(float64)) != DOUBLE {
+    t.Fatal("Invalid type for list, expected: ", DOUBLE, ", 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 TestWriteSimpleJSONProtocolSet(t *testing.T) {
+  thetype := "set"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+  }
+  p.WriteSetEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  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 int(l[0].(float64)) != DOUBLE {
+    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 TestWriteSimpleJSONProtocolMap(t *testing.T) {
+  thetype := "map"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(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.String())
+    }
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.String())
+    }
+  }
+  p.WriteMapEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  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)
+  }
+  l := strings.Split(str[1:len(str)-1], ",", -1)
+  if len(l) < 3 {
+    t.Fatal("Expected list of at least length 3 for map for metadata, but was of length ", len(l))
+  }
+  expectedKeyType, _ := strconv.Atoi(l[0])
+  expectedValueType, _ := strconv.Atoi(l[1])
+  expectedSize, _ := strconv.Atoi(l[2])
+  if expectedKeyType != I32 {
+    t.Fatal("Expected map key type ", I32, ", but was ", l[0])
+  }
+  if expectedValueType != DOUBLE {
+    t.Fatal("Expected map value type ", DOUBLE, ", but was ", l[1])
+  }
+  if expectedSize != len(DOUBLE_VALUES) {
+    t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", l[2])
+  }
+  for k, value := range DOUBLE_VALUES {
+    strk := l[k*2+3]
+    strv := l[k*2+4]
+    ik, err := strconv.Atoi(strk)
+    if err != nil {
+      t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, strk, string(k), err.String())
+    }
+    if ik != k {
+      t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v", thetype, k, strk, k)
+    }
+    s := strv
+    if math.IsInf(value, 1) {
+      if s != JsonQuote(JSON_INFINITY) {
+        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 s != JsonQuote(JSON_NEGATIVE_INFINITY) {
+        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 s != JsonQuote(JSON_NAN) {
+        t.Fatalf("Bad value for %s at index %v  %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NAN))
+      }
+    } else {
+      expected := strconv.Ftoa64(value, 'g', 10)
+      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()
+}
+
+
+func TestReadWriteSimpleJSONStruct(t *testing.T) {
+  thetype := "struct"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  orig := NewWork()
+  orig.Num1 = 25
+  orig.Num2 = 102
+  orig.Op = ADD
+  orig.Comment = "Add: 25 + 102"
+  if e := orig.Write(p); e != nil {
+    t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String())
+  }
+  t.Log("Memory buffer contents: ", trans.String())
+  read := NewWork()
+  e := read.Read(p)
+  t.Logf("Read %s value: %#v", thetype, read)
+  if e != nil {
+    t.Fatalf("Unable to read %s due to error: %s", thetype, e.String())
+  }
+  if !orig.Equals(read) {
+    t.Fatalf("Original Write != Read: %#v != %#v ", orig, read)
+  }
+}
+
+func TestReadWriteSimpleJSONProtocol(t *testing.T) {
+  ReadWriteProtocolTest(t, NewTSimpleJSONProtocolFactory())
+}

Added: thrift/trunk/lib/go/thrift/tsimple_server.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tsimple_server.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tsimple_server.go (added)
+++ thrift/trunk/lib/go/thrift/tsimple_server.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,166 @@
+/*
+ * 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 (
+  "os"
+)
+
+
+/**
+ * Simple singlethreaded server for testing.
+ *
+ */
+type TSimpleServer struct {
+  stopped bool
+
+  processorFactory       TProcessorFactory
+  serverTransport        TServerTransport
+  inputTransportFactory  TTransportFactory
+  outputTransportFactory TTransportFactory
+  inputProtocolFactory   TProtocolFactory
+  outputProtocolFactory  TProtocolFactory
+}
+
+func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer {
+  return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport)
+}
+
+func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer {
+  return NewTSimpleServerFactory4(NewTProcessorFactory(processor),
+    serverTransport,
+    transportFactory,
+    protocolFactory,
+  )
+}
+
+func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer {
+  return NewTSimpleServerFactory6(NewTProcessorFactory(processor),
+    serverTransport,
+    inputTransportFactory,
+    outputTransportFactory,
+    inputProtocolFactory,
+    outputProtocolFactory,
+  )
+}
+
+func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer {
+  return NewTSimpleServerFactory6(processorFactory,
+    serverTransport,
+    NewTTransportFactory(),
+    NewTTransportFactory(),
+    NewTBinaryProtocolFactoryDefault(),
+    NewTBinaryProtocolFactoryDefault(),
+  )
+}
+
+func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer {
+  return NewTSimpleServerFactory6(processorFactory,
+    serverTransport,
+    transportFactory,
+    transportFactory,
+    protocolFactory,
+    protocolFactory,
+  )
+}
+
+func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer {
+  return &TSimpleServer{processorFactory: processorFactory,
+    serverTransport:        serverTransport,
+    inputTransportFactory:  inputTransportFactory,
+    outputTransportFactory: outputTransportFactory,
+    inputProtocolFactory:   inputProtocolFactory,
+    outputProtocolFactory:  outputProtocolFactory,
+  }
+}
+
+func (p *TSimpleServer) ProcessorFactory() TProcessorFactory {
+  return p.processorFactory
+}
+
+func (p *TSimpleServer) ServerTransport() TServerTransport {
+  return p.serverTransport
+}
+
+func (p *TSimpleServer) InputTransportFactory() TTransportFactory {
+  return p.inputTransportFactory
+}
+
+func (p *TSimpleServer) OutputTransportFactory() TTransportFactory {
+  return p.outputTransportFactory
+}
+
+func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory {
+  return p.inputProtocolFactory
+}
+
+func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory {
+  return p.outputProtocolFactory
+}
+
+func (p *TSimpleServer) Serve() os.Error {
+  p.stopped = false
+  err := p.serverTransport.Listen()
+  if err != nil {
+    return err
+  }
+  for !p.stopped {
+    client, err := p.serverTransport.Accept()
+    if err != nil {
+      return err
+    }
+    if client != nil {
+      p.processRequest(client)
+    }
+  }
+  return nil
+}
+
+func (p *TSimpleServer) Stop() os.Error {
+  p.stopped = true
+  p.serverTransport.Interrupt()
+  return nil
+}
+
+func (p *TSimpleServer) processRequest(client TTransport) {
+  processor := p.processorFactory.GetProcessor(client)
+  inputTransport := p.inputTransportFactory.GetTransport(client)
+  outputTransport := p.outputTransportFactory.GetTransport(client)
+  inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport)
+  outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport)
+  if inputTransport != nil {
+    defer inputTransport.Close()
+  }
+  if outputTransport != nil {
+    defer outputTransport.Close()
+  }
+  for {
+    ok, e := processor.Process(inputProtocol, outputProtocol)
+    if e != nil {
+      if !p.stopped {
+        // TODO(pomack) log error
+        break
+      }
+    }
+    if !ok {
+      break
+    }
+  }
+}

Added: thrift/trunk/lib/go/thrift/tsocket.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tsocket.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tsocket.go (added)
+++ thrift/trunk/lib/go/thrift/tsocket.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,203 @@
+/*
+ * 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"
+  "os"
+  "bytes"
+)
+
+/**
+ * Socket implementation of the TTransport interface. To be commented soon!
+ *
+ */
+type TSocket struct {
+  writeBuffer *bytes.Buffer
+  /**
+   * Wrapped Socket object
+   */
+  conn net.Conn
+  /**
+   * Remote Addr
+   */
+  addr net.Addr
+  /**
+   * Socket timeout in nanoseconds
+   */
+  nsecTimeout int64
+}
+
+/**
+ * Constructor that takes an already created socket.
+ *
+ * @param socket Already created socket object
+ * @throws TTransportException if there is an error setting up the streams
+ */
+func NewTSocketConn(connection net.Conn) (*TSocket, TTransportException) {
+  address := connection.RemoteAddr()
+  if address == nil {
+    address = connection.LocalAddr()
+  }
+  p := &TSocket{conn: connection, addr: address, nsecTimeout: 0, writeBuffer: bytes.NewBuffer(make([]byte, 0, 4096))}
+  return p, nil
+}
+
+/**
+ * Creates a new unconnected socket that will connect to the given host
+ * on the given port.
+ *
+ * @param host Remote host
+ * @param port Remote port
+ */
+func NewTSocketAddr(address net.Addr) *TSocket {
+  return NewTSocket(address, 0)
+}
+
+/**
+ * Creates a new unconnected socket that will connect to the given host
+ * on the given port.
+ *
+ * @param host    Remote host
+ * @param port    Remote port
+ * @param nsecTimeout Socket timeout
+ */
+func NewTSocket(address net.Addr, nsecTimeout int64) *TSocket {
+  sock := &TSocket{addr: address, nsecTimeout: nsecTimeout, writeBuffer: bytes.NewBuffer(make([]byte, 0, 4096))}
+  return sock
+}
+
+/**
+ * Sets the socket timeout
+ *
+ * @param timeout Nanoseconds timeout
+ */
+func (p *TSocket) SetTimeout(nsecTimeout int64) os.Error {
+  p.nsecTimeout = nsecTimeout
+  if p.IsOpen() {
+    if err := p.conn.SetTimeout(nsecTimeout); err != nil {
+      LOGGER.Print("Could not set socket timeout.", err)
+      return err
+    }
+  }
+  return nil
+}
+
+/**
+ * Returns a reference to the underlying socket.
+ */
+func (p *TSocket) Conn() net.Conn {
+  return p.conn
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TSocket) IsOpen() bool {
+  if p.conn == nil {
+    return false
+  }
+  return true
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TSocket) Open() os.Error {
+  if p.IsOpen() {
+    return NewTTransportException(ALREADY_OPEN, "Socket already connected.")
+  }
+  if p.addr == nil {
+    return NewTTransportException(NOT_OPEN, "Cannot open nil address.")
+  }
+  if len(p.addr.Network()) == 0 {
+    return NewTTransportException(NOT_OPEN, "Cannot open bad network name.")
+  }
+  if len(p.addr.String()) == 0 {
+    return NewTTransportException(NOT_OPEN, "Cannot open bad address.")
+  }
+  var err os.Error
+  if p.conn, err = net.Dial(p.addr.Network(), "", p.addr.String()); err != nil {
+    LOGGER.Print("Could not open socket", err.String())
+    return NewTTransportException(NOT_OPEN, err.String())
+  }
+  if p.conn != nil {
+    p.conn.SetTimeout(p.nsecTimeout)
+  }
+  return nil
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TSocket) Close() os.Error {
+  // Close the socket
+  if p.conn != nil {
+    err := p.conn.Close()
+    if err != nil {
+      LOGGER.Print("Could not close socket. ", err.String())
+      return err
+    }
+    p.conn = nil
+  }
+  return nil
+}
+
+
+func (p *TSocket) Read(buf []byte) (int, os.Error) {
+  if !p.IsOpen() {
+    return 0, NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  n, err := p.conn.Read(buf)
+  return n, NewTTransportExceptionFromOsError(err)
+}
+
+
+func (p *TSocket) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+func (p *TSocket) Write(buf []byte) (int, os.Error) {
+  if !p.IsOpen() {
+    return 0, NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  p.writeBuffer.Write(buf)
+  return len(buf), nil
+}
+
+func (p *TSocket) Peek() bool {
+  return p.IsOpen()
+}
+
+func (p *TSocket) Flush() os.Error {
+  if !p.IsOpen() {
+    return NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  _, err := p.writeBuffer.WriteTo(p.conn)
+  return NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TSocket) Interrupt() os.Error {
+  if !p.IsOpen() {
+    return nil
+  }
+  // TODO(pomack) fix Interrupt as this is probably wrong
+  return p.conn.Close()
+}

Added: thrift/trunk/lib/go/thrift/tstruct.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tstruct.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tstruct.go (added)
+++ thrift/trunk/lib/go/thrift/tstruct.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,93 @@
+/*
+ * 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
+
+/**
+ * Helper class that encapsulates struct metadata.
+ *
+ */
+type TStruct interface {
+  TFieldContainer
+  TStructName() string
+  ThriftName() string
+  TStructFields() TFieldContainer
+  String() string
+  AttributeFromFieldId(fieldId int) interface{}
+  AttributeFromFieldName(fieldName string) interface{}
+}
+
+type tStruct struct {
+  TFieldContainer
+  name string
+}
+
+func NewTStructEmpty(name string) TStruct {
+  return &tStruct{
+    name:            name,
+    TFieldContainer: NewTFieldContainer(make([]TField, 0, 0)),
+  }
+}
+
+func NewTStruct(name string, fields []TField) TStruct {
+  return &tStruct{
+    name:            name,
+    TFieldContainer: NewTFieldContainer(fields),
+  }
+}
+
+func (p *tStruct) TStructName() string {
+  return p.name
+}
+
+func (p *tStruct) ThriftName() string {
+  return p.name
+}
+
+func (p *tStruct) TStructFields() TFieldContainer {
+  return p.TFieldContainer
+}
+
+func (p *tStruct) String() string {
+  return p.name
+}
+
+func (p *tStruct) Equals(other interface{}) bool {
+  cmp, ok := p.CompareTo(other)
+  return ok && cmp == 0
+}
+
+func (p *tStruct) CompareTo(other interface{}) (int, bool) {
+  return TType(STRUCT).Compare(p, other)
+}
+
+func (p *tStruct) AttributeFromFieldId(fieldId int) interface{} {
+  return nil
+}
+
+func (p *tStruct) AttributeFromFieldName(fieldName string) interface{} {
+  return p.AttributeFromFieldId(p.FieldIdFromFieldName(fieldName))
+}
+
+
+var ANONYMOUS_STRUCT TStruct
+
+func init() {
+  ANONYMOUS_STRUCT = NewTStructEmpty("")
+}

Added: thrift/trunk/lib/go/thrift/ttransport.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/ttransport.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/ttransport.go (added)
+++ thrift/trunk/lib/go/thrift/ttransport.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,181 @@
+/*
+ * 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 (
+  "os"
+  "log"
+)
+
+type Flusher interface {
+  Flush() (err os.Error)
+}
+
+/**
+ * Generic class that encapsulates the I/O layer. This is basically a thin
+ * wrapper around the combined functionality of Java input/output streams.
+ *
+ */
+type TTransport interface {
+  /**
+   * Queries whether the transport is open.
+   *
+   * @return True if the transport is open.
+   */
+  IsOpen() bool
+
+  /**
+   * Opens the transport for reading/writing.
+   *
+   * @returns TTransportException if the transport could not be opened
+   */
+  Open() (err os.Error)
+
+  /**
+   * Closes the transport.
+   */
+  Close() (err os.Error)
+
+  /**
+   * Reads up to len bytes into buffer buf, starting att offset off.
+   *
+   * @param buf Array to read into
+   * @param off Index to start reading at
+   * @param len Maximum number of bytes to read
+   * @return The number of bytes actually read
+   * @return TTransportException if there was an error reading data
+   */
+  Read(buf []byte) (n int, err os.Error)
+
+  /**
+   * Guarantees that all of len bytes are actually read off the transport.
+   *
+   * @param buf Array to read into
+   * @param off Index to start reading at
+   * @param len Maximum number of bytes to read
+   * @return The number of bytes actually read, which must be equal to len
+   * @return TTransportException if there was an error reading data
+   */
+  ReadAll(buf []byte) (n int, err os.Error)
+
+  /**
+   * Writes the buffer to the output
+   *
+   * @param buf The output data buffer
+   * @return Number of bytes written
+   * @return TTransportException if an error occurs writing data
+   */
+  Write(buf []byte) (n int, err os.Error)
+
+  /**
+   * Flush any pending data out of a transport buffer.
+   *
+   * @return TTransportException if there was an error writing out data.
+   */
+  Flush() (err os.Error)
+
+  /**
+   * Is there more data to be read?
+   *
+   * @return True if the remote side is still alive and feeding us
+   */
+  Peek() bool
+}
+/*
+type TTransportBase struct {
+}
+
+func (p* TTransportBase) IsOpen() bool {
+  return false;
+};
+
+func (p* TTransportBase) Peek() bool {
+  return p.IsOpen();
+}
+
+func (p* TTransportBase) Open() os.Error {
+  return NewTTransportException(UNKNOWN, "Subclasses must implement TTransportBase.Open()");
+}
+
+func (p* TTransportBase) Close() os.Error {
+  return NewTTransportException(UNKNOWN, "Subclasses must implement TTransportBase.Close()");
+}
+
+func (p* TTransportBase) Read(buf []byte) (int, os.Error) {
+  return 0, NewTTransportExceptionDefaultString("Subclasses must implement TTransportBase.Read()");
+}
+
+func (p* TTransportBase) ReadAll(buf []byte) (n int, err os.Error){
+  ret := 0;
+  size := len(buf);
+  for (n < size) {
+    ret, err = p.Read(buf[n:]);
+    if ret <= 0 {
+      if err != nil {
+        err = NewTTransportExceptionDefaultString("Cannot read. Remote side has closed. Tried to read " + string(size) + " bytes, but only got " + string(n) + " bytes.");
+      }
+      return ret, err;
+    }
+    n += ret;
+  }
+  return n, err;
+}
+
+func (p* TTransportBase) Write(buf []byte) (int, os.Error) {
+  return 0, NewTTransportExceptionDefaultString("Subclasses must implement TTransportBase.Write()");
+}
+
+func (p* TTransportBase) Flush() os.Error {
+  return nil;
+}
+*/
+/**
+ * Guarantees that all of len bytes are actually read off the transport.
+ *
+ * @param buf Array to read into
+ * @param off Index to start reading at
+ * @param len Maximum number of bytes to read
+ * @return The number of bytes actually read, which must be equal to len
+ * @return TTransportException if there was an error reading data
+ */
+func ReadAllTransport(p TTransport, buf []byte) (n int, err os.Error) {
+  ret := 0
+  size := len(buf)
+  for n < size {
+    ret, err = p.Read(buf[n:])
+    if ret <= 0 {
+      if err != nil {
+        err = NewTTransportExceptionDefaultString("Cannot read. Remote side has closed. Tried to read " + string(size) + " bytes, but only got " + string(n) + " bytes.")
+      }
+      return ret, err
+    }
+    n += ret
+  }
+  return n, err
+}
+
+
+var (
+  LOGGER *log.Logger
+)
+
+func init() {
+  LOGGER = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
+}

Added: thrift/trunk/lib/go/thrift/ttransport_exception.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/ttransport_exception.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/ttransport_exception.go (added)
+++ thrift/trunk/lib/go/thrift/ttransport_exception.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,84 @@
+/*
+ * 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 (
+  "os"
+)
+
+/**
+ * Transport exceptions.
+ *
+ */
+type TTransportException interface {
+  TException
+  TypeId() int
+}
+
+const (
+  UNKNOWN_TRANSPORT_EXCEPTION = 0
+  NOT_OPEN                    = 1
+  ALREADY_OPEN                = 2
+  TIMED_OUT                   = 3
+  END_OF_FILE                 = 4
+)
+
+type tTransportException struct {
+  typeId  int
+  message string
+}
+
+func (p *tTransportException) TypeId() int {
+  return p.typeId
+}
+
+func (p *tTransportException) String() string {
+  return p.message
+}
+
+func NewTTransportExceptionDefault() TTransportException {
+  return NewTTransportExceptionDefaultType(UNKNOWN_TRANSPORT_EXCEPTION)
+}
+
+func NewTTransportExceptionDefaultType(t int) TTransportException {
+  return NewTTransportException(t, "")
+}
+
+func NewTTransportExceptionDefaultString(m string) TTransportException {
+  return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, m)
+}
+
+func NewTTransportException(t int, m string) TTransportException {
+  return &tTransportException{typeId: t, message: m}
+}
+
+func NewTTransportExceptionFromOsError(e os.Error) TTransportException {
+  if e == nil {
+    return nil
+  }
+  t, ok := e.(TTransportException)
+  if ok {
+    return t
+  }
+  if e == os.EOF {
+    return NewTTransportException(END_OF_FILE, e.String())
+  }
+  return NewTTransportExceptionDefaultString(e.String())
+}

Added: thrift/trunk/lib/go/thrift/ttransport_factory.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/ttransport_factory.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/ttransport_factory.go (added)
+++ thrift/trunk/lib/go/thrift/ttransport_factory.go Sun Feb 20 02:39:19 2011
@@ -0,0 +1,47 @@
+/*
+ * 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 class used to create wrapped instance of Transports.
+ * This is used primarily in servers, which get Transports from
+ * a ServerTransport and then may want to mutate them (i.e. create
+ * a BufferedTransport from the underlying base transport)
+ *
+ */
+type TTransportFactory interface {
+  GetTransport(trans TTransport) TTransport
+}
+
+type tTransportFactory struct{}
+
+/**
+ * Return a wrapped instance of the base Transport.
+ *
+ * @param trans The base transport
+ * @return Wrapped Transport
+ */
+func (p *tTransportFactory) GetTransport(trans TTransport) TTransport {
+  return trans
+}
+
+func NewTTransportFactory() TTransportFactory {
+  return &tTransportFactory{}
+}