THRIFT-625: Add support for 'Go'; provided by Aalok Shah.
git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1072478 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9dbc1c1..8538afa 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -66,4 +66,5 @@
ocaml \
js \
as3 \
- st
+ st \
+ go
diff --git a/lib/go/Make.deps b/lib/go/Make.deps
new file mode 100644
index 0000000..c233e7e
--- /dev/null
+++ b/lib/go/Make.deps
@@ -0,0 +1,134 @@
+thrift/.install: bufio.install bytes.install container/list.install container/vector.install encoding/base64.install encoding/binary.install fmt.install http.install io.install json.install log.install math.install net.install os.install reflect.install sort.install strconv.install strings.install
+archive/tar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/tar.a
+archive/zip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/zip.a
+asn1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/asn1.a
+big.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/big.a
+bufio.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bufio.a
+bytes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bytes.a
+cmath.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/cmath.a
+compress/flate.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/flate.a
+compress/gzip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/gzip.a
+compress/zlib.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/zlib.a
+container/heap.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/heap.a
+container/list.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/list.a
+container/ring.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/ring.a
+container/vector.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/vector.a
+crypto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto.a
+crypto/aes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/aes.a
+crypto/block.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/block.a
+crypto/blowfish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/blowfish.a
+crypto/cast5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cast5.a
+crypto/cipher.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cipher.a
+crypto/dsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/dsa.a
+crypto/elliptic.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/elliptic.a
+crypto/hmac.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/hmac.a
+crypto/md4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md4.a
+crypto/md5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md5.a
+crypto/ocsp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ocsp.a
+crypto/rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rand.a
+crypto/rc4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rc4.a
+crypto/ripemd160.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ripemd160.a
+crypto/rsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rsa.a
+crypto/sha1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha1.a
+crypto/sha256.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha256.a
+crypto/sha512.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha512.a
+crypto/subtle.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/subtle.a
+crypto/tls.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/tls.a
+crypto/twofish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/twofish.a
+crypto/x509.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/x509.a
+crypto/xtea.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/xtea.a
+debug/dwarf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/dwarf.a
+debug/macho.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/macho.a
+debug/elf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/elf.a
+debug/gosym.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/gosym.a
+debug/pe.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/pe.a
+debug/proc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/proc.a
+ebnf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/ebnf.a
+encoding/ascii85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/ascii85.a
+encoding/base32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base32.a
+encoding/base64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base64.a
+encoding/binary.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/binary.a
+encoding/git85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/git85.a
+encoding/hex.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/hex.a
+encoding/line.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/line.a
+encoding/pem.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/pem.a
+exec.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exec.a
+exp/datafmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/datafmt.a
+exp/draw.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw.a
+exp/draw/x11.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw/x11.a
+exp/eval.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/eval.a
+expvar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/expvar.a
+flag.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/flag.a
+fmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/fmt.a
+go/ast.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/ast.a
+go/doc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/doc.a
+go/parser.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/parser.a
+go/printer.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/printer.a
+go/scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/scanner.a
+go/token.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/token.a
+go/typechecker.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/typechecker.a
+gob.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/gob.a
+hash.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash.a
+hash/adler32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/adler32.a
+hash/crc32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc32.a
+hash/crc64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc64.a
+html.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/html.a
+http.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http.a
+http/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/pprof.a
+image.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image.a
+image/jpeg.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/jpeg.a
+image/png.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/png.a
+index/suffixarray.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/index/suffixarray.a
+io.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io.a
+io/ioutil.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io/ioutil.a
+json.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/json.a
+log.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/log.a
+math.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/math.a
+mime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime.a
+mime/multipart.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime/multipart.a
+net.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net.a
+net/dict.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/dict.a
+net/textproto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/textproto.a
+netchan.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/netchan.a
+os.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os.a
+os/signal.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os/signal.a
+patch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/patch.a
+path.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/path.a
+rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rand.a
+reflect.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/reflect.a
+regexp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/regexp.a
+rpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc.a
+rpc/jsonrpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc/jsonrpc.a
+runtime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime.a
+runtime/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/cgo.a
+runtime/debug.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/debug.a
+runtime/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/pprof.a
+scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/scanner.a
+smtp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/smtp.a
+sort.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sort.a
+strconv.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strconv.a
+strings.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strings.a
+sync.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sync.a
+syscall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syscall.a
+syslog.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syslog.a
+tabwriter.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/tabwriter.a
+template.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/template.a
+testing.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing.a
+testing/iotest.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/iotest.a
+testing/quick.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/quick.a
+testing/script.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/script.a
+time.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/time.a
+try.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/try.a
+unicode.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/unicode.a
+utf16.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf16.a
+utf8.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf8.a
+websocket.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/websocket.a
+xml.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/xml.a
+../cmd/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/cgo.a
+../cmd/ebnflint.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/ebnflint.a
+../cmd/godoc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/godoc.a
+../cmd/gofmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/gofmt.a
+../cmd/goinstall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goinstall.a
+../cmd/govet.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/govet.a
+../cmd/goyacc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goyacc.a
+../cmd/hgpatch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/hgpatch.a
diff --git a/lib/go/Makefile b/lib/go/Makefile
new file mode 100644
index 0000000..8e81d8d
--- /dev/null
+++ b/lib/go/Makefile
@@ -0,0 +1,64 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# After editing the DIRS= list or adding imports to any Go files
+# in any of those directories, run:
+#
+# ./deps.bash
+#
+# to rebuild the dependency information in Make.deps.
+
+
+include $(GOROOT)/src/Make.inc
+
+all: Make.deps install
+
+DIRS=\
+ thrift/\
+
+TEST=\
+ $(filter-out $(NOTEST),$(DIRS))
+
+
+clean.dirs: $(addsuffix .clean, $(DIRS))
+install.dirs: $(addsuffix .install, $(DIRS))
+nuke.dirs: $(addsuffix .nuke, $(DIRS))
+test.dirs: $(addsuffix .test, $(DIRS))
+check.dirs: $(addsuffix .check, $(DIRS))
+
+%.clean:
+ +cd $* && gomake clean
+
+%.install:
+ +cd $* && gomake install
+
+%.nuke:
+ +cd $* && gomake nuke
+
+%.test:
+ +cd $* && gomake test
+
+%.check:
+ +cd $* && gomake check
+
+clean: clean.dirs
+
+install: install.dirs
+
+test: test.dirs
+
+check: check.dirs
+
+#nuke: nuke.dirs
+# rm -rf "$(GOROOT)"/pkg/thrift.*
+
+echo-dirs:
+ @echo $(DIRS)
+
+Make.deps:
+ ./deps.bash
+
+deps:
+ ./deps.bash
+
diff --git a/lib/go/deps.bash b/lib/go/deps.bash
new file mode 100644
index 0000000..dabd404
--- /dev/null
+++ b/lib/go/deps.bash
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+OUT="Make.deps"
+TMP="Make.deps.tmp"
+
+if [ -f $OUT ] && ! [ -w $OUT ]; then
+ echo "$0: $OUT is read-only; aborting." 1>&2
+ exit 1
+fi
+
+# Get list of directories from Makefile
+dirs=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' Makefile)
+dirs2=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' $GOROOT/src/pkg/Makefile)
+dirpat=$(echo $dirs $dirs2 | sed 's/ /|/g; s/.*/^(&)$/')
+
+for dir in $dirs; do (
+ cd $dir || exit 1
+
+ sources=$(sed -n 's/\.go\\/.go/p' Makefile)
+ sources=$(ls $sources 2> /dev/null) # remove .s, .c, etc.
+
+ deps=$(
+ sed -n '/^import.*"/p; /^import[ \t]*(/,/^)/p' $sources /dev/null |
+ cut -d '"' -f2 |
+ egrep "$dirpat" |
+ grep -v "^$dir\$" |
+ sed 's/$/.install/' |
+ sort -u
+ )
+
+ echo $dir.install: $deps
+) done > $TMP
+
+for dir in $dirs2; do (
+ echo $dir.install: \${GOROOT}/pkg/\${GOOS}_\${GOARCH}/${dir}.a
+) done >> $TMP
+
+mv $TMP $OUT
diff --git a/lib/go/thrift/Makefile b/lib/go/thrift/Makefile
new file mode 100644
index 0000000..59f7862
--- /dev/null
+++ b/lib/go/thrift/Makefile
@@ -0,0 +1,58 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include $(GOROOT)/src/Make.inc
+
+TARG=thrift
+GOFILES=\
+ tapplication_exception.go\
+ tbase.go\
+ tbinary_protocol.go\
+ tcompact_protocol.go\
+ tcompare.go\
+ tcontainer.go\
+ texception.go\
+ tfield.go\
+ tframed_transport.go\
+ thttp_client.go\
+ tiostream_transport.go\
+ tlist.go\
+ tjson_protocol.go\
+ tmap.go\
+ tmemory_buffer.go\
+ tmessage.go\
+ tmessagetype.go\
+ tnonblocking_server.go\
+ tnonblocking_server_socket.go\
+ tnonblocking_socket.go\
+ tnonblocking_transport.go\
+ tnumeric.go\
+ tprocessor.go\
+ tprocessor_factory.go\
+ tprotocol.go\
+ tprotocol_exception.go\
+ tprotocol_factory.go\
+ tserver.go\
+ tserver_socket.go\
+ tserver_transport.go\
+ tset.go\
+ tsimple_server.go\
+ tsimple_json_protocol.go\
+ tsocket.go\
+ tstruct.go\
+ ttransport.go\
+ ttransport_exception.go\
+ ttransport_factory.go\
+ ttype.go
+
+DIRS=\
+
+include $(GOROOT)/src/Make.pkg
+
+check:
+ gomake test
+
+-include ../Make.deps
+
+
diff --git a/lib/go/thrift/_testmain.go b/lib/go/thrift/_testmain.go
new file mode 100644
index 0000000..3b0abfb
--- /dev/null
+++ b/lib/go/thrift/_testmain.go
@@ -0,0 +1,68 @@
+package main
+
+import "./_xtest_"
+import "testing"
+import __regexp__ "regexp"
+
+var tests = []testing.InternalTest{
+ {"thrift_test.TestTApplicationException", thrift_test.TestTApplicationException},
+ {"thrift_test.TestReadWriteBinaryProtocol", thrift_test.TestReadWriteBinaryProtocol},
+ {"thrift_test.TestReadWriteCompactProtocol", thrift_test.TestReadWriteCompactProtocol},
+ {"thrift_test.TestTException", thrift_test.TestTException},
+ {"thrift_test.TestFramedTransport", thrift_test.TestFramedTransport},
+ {"thrift_test.TestHttpClient", thrift_test.TestHttpClient},
+ {"thrift_test.TestIOStreamTransport", thrift_test.TestIOStreamTransport},
+ {"thrift_test.TestWriteJSONProtocolBool", thrift_test.TestWriteJSONProtocolBool},
+ {"thrift_test.TestReadJSONProtocolBool", thrift_test.TestReadJSONProtocolBool},
+ {"thrift_test.TestWriteJSONProtocolByte", thrift_test.TestWriteJSONProtocolByte},
+ {"thrift_test.TestReadJSONProtocolByte", thrift_test.TestReadJSONProtocolByte},
+ {"thrift_test.TestWriteJSONProtocolI16", thrift_test.TestWriteJSONProtocolI16},
+ {"thrift_test.TestReadJSONProtocolI16", thrift_test.TestReadJSONProtocolI16},
+ {"thrift_test.TestWriteJSONProtocolI32", thrift_test.TestWriteJSONProtocolI32},
+ {"thrift_test.TestReadJSONProtocolI32", thrift_test.TestReadJSONProtocolI32},
+ {"thrift_test.TestWriteJSONProtocolI64", thrift_test.TestWriteJSONProtocolI64},
+ {"thrift_test.TestReadJSONProtocolI64", thrift_test.TestReadJSONProtocolI64},
+ {"thrift_test.TestWriteJSONProtocolDouble", thrift_test.TestWriteJSONProtocolDouble},
+ {"thrift_test.TestReadJSONProtocolDouble", thrift_test.TestReadJSONProtocolDouble},
+ {"thrift_test.TestWriteJSONProtocolString", thrift_test.TestWriteJSONProtocolString},
+ {"thrift_test.TestReadJSONProtocolString", thrift_test.TestReadJSONProtocolString},
+ {"thrift_test.TestWriteJSONProtocolBinary", thrift_test.TestWriteJSONProtocolBinary},
+ {"thrift_test.TestReadJSONProtocolBinary", thrift_test.TestReadJSONProtocolBinary},
+ {"thrift_test.TestWriteJSONProtocolList", thrift_test.TestWriteJSONProtocolList},
+ {"thrift_test.TestWriteJSONProtocolSet", thrift_test.TestWriteJSONProtocolSet},
+ {"thrift_test.TestWriteJSONProtocolMap", thrift_test.TestWriteJSONProtocolMap},
+ {"thrift_test.TestReadWriteJSONStruct", thrift_test.TestReadWriteJSONStruct},
+ {"thrift_test.TestReadWriteJSONProtocol", thrift_test.TestReadWriteJSONProtocol},
+ {"thrift_test.TestMemoryBuffer", thrift_test.TestMemoryBuffer},
+ {"thrift_test.TestNonblockingTransportServerToClient", thrift_test.TestNonblockingTransportServerToClient},
+ {"thrift_test.TestNonblockingTransportClientToServer", thrift_test.TestNonblockingTransportClientToServer},
+ {"thrift_test.TestNothing", thrift_test.TestNothing},
+ {"thrift_test.TestWriteSimpleJSONProtocolBool", thrift_test.TestWriteSimpleJSONProtocolBool},
+ {"thrift_test.TestReadSimpleJSONProtocolBool", thrift_test.TestReadSimpleJSONProtocolBool},
+ {"thrift_test.TestWriteSimpleJSONProtocolByte", thrift_test.TestWriteSimpleJSONProtocolByte},
+ {"thrift_test.TestReadSimpleJSONProtocolByte", thrift_test.TestReadSimpleJSONProtocolByte},
+ {"thrift_test.TestWriteSimpleJSONProtocolI16", thrift_test.TestWriteSimpleJSONProtocolI16},
+ {"thrift_test.TestReadSimpleJSONProtocolI16", thrift_test.TestReadSimpleJSONProtocolI16},
+ {"thrift_test.TestWriteSimpleJSONProtocolI32", thrift_test.TestWriteSimpleJSONProtocolI32},
+ {"thrift_test.TestReadSimpleJSONProtocolI32", thrift_test.TestReadSimpleJSONProtocolI32},
+ {"thrift_test.TestWriteSimpleJSONProtocolI64", thrift_test.TestWriteSimpleJSONProtocolI64},
+ {"thrift_test.TestReadSimpleJSONProtocolI64", thrift_test.TestReadSimpleJSONProtocolI64},
+ {"thrift_test.TestWriteSimpleJSONProtocolDouble", thrift_test.TestWriteSimpleJSONProtocolDouble},
+ {"thrift_test.TestReadSimpleJSONProtocolDouble", thrift_test.TestReadSimpleJSONProtocolDouble},
+ {"thrift_test.TestWriteSimpleJSONProtocolString", thrift_test.TestWriteSimpleJSONProtocolString},
+ {"thrift_test.TestReadSimpleJSONProtocolString", thrift_test.TestReadSimpleJSONProtocolString},
+ {"thrift_test.TestWriteSimpleJSONProtocolBinary", thrift_test.TestWriteSimpleJSONProtocolBinary},
+ {"thrift_test.TestReadSimpleJSONProtocolBinary", thrift_test.TestReadSimpleJSONProtocolBinary},
+ {"thrift_test.TestWriteSimpleJSONProtocolList", thrift_test.TestWriteSimpleJSONProtocolList},
+ {"thrift_test.TestWriteSimpleJSONProtocolSet", thrift_test.TestWriteSimpleJSONProtocolSet},
+ {"thrift_test.TestWriteSimpleJSONProtocolMap", thrift_test.TestWriteSimpleJSONProtocolMap},
+ {"thrift_test.TestReadWriteSimpleJSONStruct", thrift_test.TestReadWriteSimpleJSONStruct},
+ {"thrift_test.TestReadWriteSimpleJSONProtocol", thrift_test.TestReadWriteSimpleJSONProtocol},
+}
+var benchmarks = []testing.InternalBenchmark{ //
+}
+
+func main() {
+ testing.Main(__regexp__.MatchString, tests)
+ testing.RunBenchmarks(__regexp__.MatchString, benchmarks)
+}
diff --git a/lib/go/thrift/tapplication_exception.go b/lib/go/thrift/tapplication_exception.go
new file mode 100644
index 0000000..fc8bf2e
--- /dev/null
+++ b/lib/go/thrift/tapplication_exception.go
@@ -0,0 +1,169 @@
+/*
+ * 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"
+)
+
+const (
+ UNKNOWN_APPLICATION_EXCEPTION = 0
+ UNKNOWN_METHOD = 1
+ INVALID_MESSAGE_TYPE_EXCEPTION = 2
+ WRONG_METHOD_NAME = 3
+ BAD_SEQUENCE_ID = 4
+ MISSING_RESULT = 5
+ INTERNAL_ERROR = 6
+ PROTOCOL_ERROR = 7
+)
+
+
+/**
+ * Application level exception
+ *
+ */
+type TApplicationException interface {
+ TException
+ TypeId() int32
+ Read(iprot TProtocol) (TApplicationException, os.Error)
+ Write(oprot TProtocol) os.Error
+}
+
+type tApplicationException struct {
+ TException
+ type_ int32
+}
+
+func NewTApplicationExceptionDefault() TApplicationException {
+ return NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "UNKNOWN")
+}
+
+func NewTApplicationExceptionType(type_ int32) TApplicationException {
+ return NewTApplicationException(type_, "UNKNOWN")
+}
+
+func NewTApplicationException(type_ int32, message string) TApplicationException {
+ return &tApplicationException{TException: NewTException(message), type_: type_}
+}
+
+func NewTApplicationExceptionMessage(message string) TApplicationException {
+ return NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, message)
+}
+
+func (p *tApplicationException) TypeId() int32 {
+ return p.type_
+}
+
+func (p *tApplicationException) Read(iprot TProtocol) (error TApplicationException, err os.Error) {
+ _, err = iprot.ReadStructBegin()
+ if err != nil {
+ return
+ }
+
+ message := ""
+ type_ := int32(UNKNOWN_APPLICATION_EXCEPTION)
+
+ for {
+ _, ttype, id, err := iprot.ReadFieldBegin()
+ if err != nil {
+ return
+ }
+ if ttype == STOP {
+ break
+ }
+ switch id {
+ case 1:
+ if ttype == STRING {
+ message, err = iprot.ReadString()
+ if err != nil {
+ return
+ }
+ } else {
+ err = SkipDefaultDepth(iprot, ttype)
+ if err != nil {
+ return
+ }
+ }
+ break
+ case 2:
+ if ttype == I32 {
+ type_, err = iprot.ReadI32()
+ if err != nil {
+ return
+ }
+ } else {
+ err = SkipDefaultDepth(iprot, ttype)
+ if err != nil {
+ return
+ }
+ }
+ break
+ default:
+ err = SkipDefaultDepth(iprot, ttype)
+ if err != nil {
+ return
+ }
+ break
+ }
+ err = iprot.ReadFieldEnd()
+ if err != nil {
+ return
+ }
+ }
+ err = iprot.ReadStructEnd()
+ error = NewTApplicationException(type_, message)
+ return
+}
+
+func (p *tApplicationException) Write(oprot TProtocol) (err os.Error) {
+ err = oprot.WriteStructBegin("TApplicationException")
+ if len(p.String()) > 0 {
+ err = oprot.WriteFieldBegin("message", STRING, 1)
+ if err != nil {
+ return
+ }
+ err = oprot.WriteString(p.String())
+ if err != nil {
+ return
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return
+ }
+ }
+ err = oprot.WriteFieldBegin("type", I32, 2)
+ if err != nil {
+ return
+ }
+ err = oprot.WriteI32(p.type_)
+ if err != nil {
+ return
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return
+ }
+ err = oprot.WriteFieldStop()
+ if err != nil {
+ return
+ }
+ err = oprot.WriteStructEnd()
+ return
+}
diff --git a/lib/go/thrift/tapplication_exception_test.go b/lib/go/thrift/tapplication_exception_test.go
new file mode 100644
index 0000000..d9572f4
--- /dev/null
+++ b/lib/go/thrift/tapplication_exception_test.go
@@ -0,0 +1,42 @@
+/*
+ * 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"
+ "testing"
+)
+
+func TestTApplicationException(t *testing.T) {
+ exc := NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "")
+ if exc.String() != "" {
+ t.Fatalf("Expected empty string for exception but found '%s'", exc.String())
+ }
+ if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION {
+ t.Fatalf("Expected type UNKNOWN for exception but found '%s'", exc.TypeId())
+ }
+ exc = NewTApplicationException(WRONG_METHOD_NAME, "junk_method")
+ if exc.String() != "junk_method" {
+ t.Fatalf("Expected 'junk_method' for exception but found '%s'", exc.String())
+ }
+ if exc.TypeId() != WRONG_METHOD_NAME {
+ t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%s'", exc.TypeId())
+ }
+}
diff --git a/lib/go/thrift/tbase.go b/lib/go/thrift/tbase.go
new file mode 100644
index 0000000..adc52d0
--- /dev/null
+++ b/lib/go/thrift/tbase.go
@@ -0,0 +1,66 @@
+/*
+ * 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
+
+/**
+ * Generic base interface for generated Thrift objects.
+ *
+ */
+type TBase interface {
+
+ /**
+ * Reads the TObject from the given input protocol
+ *
+ * @param iprot Input protocol
+ */
+ Read(iprot TProtocol) (err TException)
+
+ /**
+ * Writes the objects out to the protocol
+ *
+ * @param oprot Output protocol
+ */
+ Write(oprot TProtocol) (err TException)
+
+ /**
+ * Check if a field is currently set or unset.
+ *
+ * @param field
+ */
+ IsSet(field TField) bool
+
+ /**
+ * Get a field's value by field variable. Primitive types will be wrapped in
+ * the appropriate "boxed" types.
+ *
+ * @param field
+ */
+ FieldValue(field TField) interface{}
+
+ /**
+ * Set a field's value by field variable. Primitive types must be "boxed" in
+ * the appropriate object wrapper type.
+ *
+ * @param field
+ */
+ SetFieldValue(field TField, value interface{})
+
+ DeepCopy() TBase
+}
diff --git a/lib/go/thrift/tbinary_protocol.go b/lib/go/thrift/tbinary_protocol.go
new file mode 100644
index 0000000..1c88da6
--- /dev/null
+++ b/lib/go/thrift/tbinary_protocol.go
@@ -0,0 +1,493 @@
+/*
+ * 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/binary"
+ "math"
+ "strings"
+ "io"
+)
+
+type TBinaryProtocol struct {
+ //TProtocolBase;
+ trans TTransport
+ _StrictRead bool
+ _StrictWrite bool
+ _ReadLength int
+ _CheckReadLength bool
+}
+
+type TBinaryProtocolFactory struct {
+ _StrictRead bool
+ _StrictWrite bool
+}
+
+func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol {
+ return NewTBinaryProtocol(t, false, true)
+}
+
+func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol {
+ //return &TBinaryProtocol{TProtocolBase:TProtocolBase{trans:t}, _StrictRead:strictRead, _StrictWrite:strictWrite, _ReadLength:0, _CheckReadLength:false};
+ return &TBinaryProtocol{trans: t, _StrictRead: strictRead, _StrictWrite: strictWrite, _ReadLength: 0, _CheckReadLength: false}
+}
+
+func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory {
+ return NewTBinaryProtocolFactory(false, true)
+}
+
+func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory {
+ return &TBinaryProtocolFactory{_StrictRead: strictRead, _StrictWrite: strictWrite}
+}
+
+func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol {
+ return NewTBinaryProtocol(t, p._StrictRead, p._StrictWrite)
+}
+
+/**
+ * Writing Methods
+ */
+
+func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException {
+ if p._StrictWrite {
+ version := uint32(VERSION_1) | uint32(typeId)
+ e := p.WriteI32(int32(version))
+ if e != nil {
+ return e
+ }
+ e = p.WriteString(name)
+ if e != nil {
+ return e
+ }
+ e = p.WriteI32(seqId)
+ return e
+ } else {
+ e := p.WriteString(name)
+ if e != nil {
+ return e
+ }
+ e = p.WriteByte(byte(typeId))
+ if e != nil {
+ return e
+ }
+ e = p.WriteI32(seqId)
+ return e
+ }
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteMessageEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteStructBegin(name string) TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteStructEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+ e := p.WriteByte(byte(typeId))
+ if e != nil {
+ return e
+ }
+ e = p.WriteI16(id)
+ return e
+}
+
+func (p *TBinaryProtocol) WriteFieldEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteFieldStop() TProtocolException {
+ e := p.WriteByte(STOP)
+ return e
+}
+
+func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+ e := p.WriteByte(byte(keyType))
+ if e != nil {
+ return e
+ }
+ e = p.WriteByte(byte(valueType))
+ if e != nil {
+ return e
+ }
+ e = p.WriteI32(int32(size))
+ return e
+}
+
+func (p *TBinaryProtocol) WriteMapEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+ e := p.WriteByte(byte(elemType))
+ if e != nil {
+ return e
+ }
+ e = p.WriteI32(int32(size))
+ return e
+}
+
+func (p *TBinaryProtocol) WriteListEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+ e := p.WriteByte(byte(elemType))
+ if e != nil {
+ return e
+ }
+ e = p.WriteI32(int32(size))
+ return e
+}
+
+func (p *TBinaryProtocol) WriteSetEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) WriteBool(value bool) TProtocolException {
+ if value {
+ return p.WriteByte(1)
+ }
+ return p.WriteByte(0)
+}
+
+func (p *TBinaryProtocol) WriteByte(value byte) TProtocolException {
+ v := []byte{value}
+ _, e := p.trans.Write(v)
+ return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TBinaryProtocol) WriteI16(value int16) TProtocolException {
+ h := byte(0xff & (value >> 8))
+ l := byte(0xff & value)
+ v := []byte{h, l}
+ _, e := p.trans.Write(v)
+ return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TBinaryProtocol) WriteI32(value int32) TProtocolException {
+ a := byte(0xff & (value >> 24))
+ b := byte(0xff & (value >> 16))
+ c := byte(0xff & (value >> 8))
+ d := byte(0xff & value)
+ v := []byte{a, b, c, d}
+ _, e := p.trans.Write(v)
+ return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TBinaryProtocol) WriteI64(value int64) TProtocolException {
+ a := byte(0xff & (value >> 56))
+ b := byte(0xff & (value >> 48))
+ c := byte(0xff & (value >> 40))
+ d := byte(0xff & (value >> 32))
+ e := byte(0xff & (value >> 24))
+ f := byte(0xff & (value >> 16))
+ g := byte(0xff & (value >> 8))
+ h := byte(0xff & value)
+ v := []byte{a, b, c, d, e, f, g, h}
+ _, err := p.trans.Write(v)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) WriteDouble(value float64) TProtocolException {
+ return p.WriteI64(int64(math.Float64bits(value)))
+}
+
+func (p *TBinaryProtocol) WriteString(value string) TProtocolException {
+ return p.WriteBinaryFromReader(strings.NewReader(value), len(value))
+}
+
+func (p *TBinaryProtocol) WriteBinary(value []byte) TProtocolException {
+ e := p.WriteI32(int32(len(value)))
+ if e != nil {
+ return e
+ }
+ _, err := p.trans.Write(value)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) WriteBinaryFromReader(reader io.Reader, size int) TProtocolException {
+ e := p.WriteI32(int32(size))
+ if e != nil {
+ return e
+ }
+ _, err := io.Copyn(p.trans, reader, int64(size))
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+
+/**
+ * Reading methods
+ */
+
+func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) {
+ size, e := p.ReadI32()
+ if e != nil {
+ return "", typeId, 0, NewTProtocolExceptionFromOsError(e)
+ }
+ if size < 0 {
+ typeId = TMessageType(size & 0x0ff)
+ version := int64(int64(size) & VERSION_MASK)
+ if version != VERSION_1 {
+ return name, typeId, seqId, NewTProtocolException(BAD_VERSION, "Bad version in ReadMessageBegin")
+ }
+ name, e = p.ReadString()
+ if e != nil {
+ return name, typeId, seqId, NewTProtocolExceptionFromOsError(e)
+ }
+ seqId, e = p.ReadI32()
+ if e != nil {
+ return name, typeId, seqId, NewTProtocolExceptionFromOsError(e)
+ }
+ return name, typeId, seqId, nil
+ }
+ if p._StrictRead {
+ return name, typeId, seqId, NewTProtocolException(BAD_VERSION, "Missing version in ReadMessageBegin")
+ }
+ name, e2 := p.readStringBody(int(size))
+ if e2 != nil {
+ return name, typeId, seqId, e2
+ }
+ b, e3 := p.ReadByte()
+ if e3 != nil {
+ return name, typeId, seqId, e3
+ }
+ typeId = TMessageType(b)
+ seqId, e4 := p.ReadI32()
+ if e4 != nil {
+ return name, typeId, seqId, e4
+ }
+ return name, typeId, seqId, nil
+}
+
+func (p *TBinaryProtocol) ReadMessageEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) ReadStructBegin() (name string, err TProtocolException) {
+ return
+}
+
+func (p *TBinaryProtocol) ReadStructEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err TProtocolException) {
+ t, err := p.ReadByte()
+ typeId = TType(t)
+ if err != nil {
+ return name, typeId, seqId, err
+ }
+ if t != STOP {
+ seqId, err = p.ReadI16()
+ }
+ return name, typeId, seqId, err
+}
+
+func (p *TBinaryProtocol) ReadFieldEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err TProtocolException) {
+ k, e := p.ReadByte()
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ kType = TType(k)
+ v, e := p.ReadByte()
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ vType = TType(v)
+ size32, e := p.ReadI32()
+ size = int(size32)
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ return kType, vType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadMapEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err TProtocolException) {
+ b, e := p.ReadByte()
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ elemType = TType(b)
+ size32, e := p.ReadI32()
+ size = int(size32)
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ return elemType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadListEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err TProtocolException) {
+ b, e := p.ReadByte()
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ elemType = TType(b)
+ size32, e := p.ReadI32()
+ size = int(size32)
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ return elemType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadSetEnd() TProtocolException {
+ return nil
+}
+
+func (p *TBinaryProtocol) ReadBool() (bool, TProtocolException) {
+ b, e := p.ReadByte()
+ v := true
+ if b != 1 {
+ v = false
+ }
+ return v, e
+}
+
+func (p *TBinaryProtocol) ReadByte() (value byte, err TProtocolException) {
+ buf := []byte{0}
+ err = p.readAll(buf)
+ return buf[0], err
+}
+
+func (p *TBinaryProtocol) ReadI16() (value int16, err TProtocolException) {
+ buf := []byte{0, 0}
+ err = p.readAll(buf)
+ value = int16(binary.BigEndian.Uint16(buf))
+ return value, err
+}
+
+func (p *TBinaryProtocol) ReadI32() (value int32, err TProtocolException) {
+ buf := []byte{0, 0, 0, 0}
+ err = p.readAll(buf)
+ value = int32(binary.BigEndian.Uint32(buf))
+ return value, err
+}
+
+func (p *TBinaryProtocol) ReadI64() (value int64, err TProtocolException) {
+ buf := []byte{0, 0, 0, 0, 0, 0, 0, 0}
+ err = p.readAll(buf)
+ value = int64(binary.BigEndian.Uint64(buf))
+ return value, err
+}
+
+func (p *TBinaryProtocol) ReadDouble() (value float64, err TProtocolException) {
+ buf := []byte{0, 0, 0, 0, 0, 0, 0, 0}
+ err = p.readAll(buf)
+ value = math.Float64frombits(binary.BigEndian.Uint64(buf))
+ return value, err
+}
+
+func (p *TBinaryProtocol) ReadString() (value string, err TProtocolException) {
+ size, e := p.ReadI32()
+ if e != nil {
+ return "", e
+ }
+ return p.readStringBody(int(size))
+}
+
+func (p *TBinaryProtocol) ReadBinary() ([]byte, TProtocolException) {
+ size, e := p.ReadI32()
+ if e != nil {
+ return nil, e
+ }
+ isize := int(size)
+ e = p.checkReadLength(isize)
+ if e != nil {
+ return nil, e
+ }
+ buf := make([]byte, isize)
+ _, err := p.trans.ReadAll(buf)
+ return buf, NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) Flush() (err TProtocolException) {
+ return NewTProtocolExceptionFromOsError(p.trans.Flush())
+}
+
+func (p *TBinaryProtocol) Skip(fieldType TType) (err TProtocolException) {
+ return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TBinaryProtocol) Transport() TTransport {
+ return p.trans
+}
+
+func (p *TBinaryProtocol) readAll(buf []byte) TProtocolException {
+ e := p.checkReadLength(len(buf))
+ if e != nil {
+ return e
+ }
+ _, err := p.trans.ReadAll(buf)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) setReadLength(readLength int) {
+ p._ReadLength = readLength
+ p._CheckReadLength = true
+}
+
+func (p *TBinaryProtocol) checkReadLength(length int) TProtocolException {
+ if p._CheckReadLength {
+ p._ReadLength = p._ReadLength - length
+ if p._ReadLength < 0 {
+ return NewTProtocolException(UNKNOWN_PROTOCOL_EXCEPTION, "Message length exceeded: "+string(length))
+ }
+ }
+ return nil
+}
+
+func (p *TBinaryProtocol) readStringBody(size int) (value string, err TProtocolException) {
+ if size < 0 {
+ return "", nil
+ }
+ err = p.checkReadLength(size)
+ if err != nil {
+ return "", err
+ }
+ isize := int(size)
+ buf := make([]byte, isize)
+ _, e := p.trans.ReadAll(buf)
+ return string(buf), NewTProtocolExceptionFromOsError(e)
+}
diff --git a/lib/go/thrift/tbinary_protocol_test.go b/lib/go/thrift/tbinary_protocol_test.go
new file mode 100644
index 0000000..b21b248
--- /dev/null
+++ b/lib/go/thrift/tbinary_protocol_test.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_test
+
+import (
+ . "thrift"
+ "testing"
+ //"bytes";
+)
+
+
+func TestReadWriteBinaryProtocol(t *testing.T) {
+ ReadWriteProtocolTest(t, NewTBinaryProtocolFactoryDefault())
+}
diff --git a/lib/go/thrift/tcompact_protocol.go b/lib/go/thrift/tcompact_protocol.go
new file mode 100644
index 0000000..9b780f7
--- /dev/null
+++ b/lib/go/thrift/tcompact_protocol.go
@@ -0,0 +1,856 @@
+/*
+ * 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 (
+ "container/vector"
+ "encoding/binary"
+ "fmt"
+ "math"
+ "os"
+ "strings"
+)
+
+const (
+ COMPACT_PROTOCOL_ID = 0x082
+ COMPACT_VERSION = 1
+ COMPACT_VERSION_MASK = 0x1f
+ COMPACT_TYPE_MASK = 0x0E0
+ COMPACT_TYPE_SHIFT_AMOUNT = 5
+)
+
+type TCompactType byte
+
+const (
+ COMPACT_BOOLEAN_TRUE = 0x01
+ COMPACT_BOOLEAN_FALSE = 0x02
+ COMPACT_BYTE = 0x03
+ COMPACT_I16 = 0x04
+ COMPACT_I32 = 0x05
+ COMPACT_I64 = 0x06
+ COMPACT_DOUBLE = 0x07
+ COMPACT_BINARY = 0x08
+ COMPACT_LIST = 0x09
+ COMPACT_SET = 0x0A
+ COMPACT_MAP = 0x0B
+ COMPACT_STRUCT = 0x0C
+)
+
+var (
+ _TTypeToCompactType []TCompactType
+ _TSTOP TField
+)
+
+func init() {
+ _TSTOP = NewTField("", STOP, 0)
+ _TTypeToCompactType = make([]TCompactType, int(UTF16)+1)
+ _TTypeToCompactType[int(STOP)] = STOP
+ _TTypeToCompactType[int(BOOL)] = COMPACT_BOOLEAN_TRUE
+ _TTypeToCompactType[int(BYTE)] = COMPACT_BYTE
+ _TTypeToCompactType[int(I16)] = COMPACT_I16
+ _TTypeToCompactType[int(I32)] = COMPACT_I32
+ _TTypeToCompactType[int(I64)] = COMPACT_I64
+ _TTypeToCompactType[int(DOUBLE)] = COMPACT_DOUBLE
+ _TTypeToCompactType[int(STRING)] = COMPACT_BINARY
+ _TTypeToCompactType[int(LIST)] = COMPACT_LIST
+ _TTypeToCompactType[int(SET)] = COMPACT_SET
+ _TTypeToCompactType[int(MAP)] = COMPACT_MAP
+ _TTypeToCompactType[int(STRUCT)] = COMPACT_STRUCT
+}
+
+type TCompactProtocolFactory struct{}
+
+func NewTCompactProtocolFactory() *TCompactProtocolFactory {
+ return &TCompactProtocolFactory{}
+}
+
+func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+ return NewTCompactProtocol(trans)
+}
+
+type TCompactProtocol struct {
+ trans TTransport
+
+ /**
+ * Used to keep track of the last field for the current and previous structs,
+ * so we can do the delta stuff.
+ */
+ lastField *vector.IntVector
+ lastFieldId int
+
+ /**
+ * If we encounter a boolean field begin, save the TField here so it can
+ * have the value incorporated.
+ */
+ booleanField TField
+
+ /**
+ * If we read a field header, and it's a boolean field, save the boolean
+ * value here so that readBool can use it.
+ */
+ boolValue bool
+ boolValueIsNotNull bool
+}
+
+/**
+ * Create a TCompactProtocol.
+ *
+ * @param transport the TTransport object to read from or write to.
+ */
+func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
+ return &TCompactProtocol{trans: trans, lastField: &vector.IntVector{}}
+}
+
+
+//
+// Public Writing methods.
+//
+
+/**
+ * Write a message header to the wire. Compact Protocol messages contain the
+ * protocol version so we can migrate forwards in the future if need be.
+ */
+func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) TProtocolException {
+ _, err := p.writeByteDirect(COMPACT_PROTOCOL_ID)
+ if err != nil {
+ return NewTProtocolExceptionFromOsError(err)
+ }
+ _, err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK))
+ if err != nil {
+ return NewTProtocolExceptionFromOsError(err)
+ }
+ _, err = p.writeVarint32(seqid)
+ if err != nil {
+ return NewTProtocolExceptionFromOsError(err)
+ }
+ e := p.WriteString(name)
+ return e
+
+}
+
+func (p *TCompactProtocol) WriteMessageEnd() TProtocolException { return nil }
+
+/**
+ * Write a struct begin. This doesn't actually put anything on the wire. We
+ * use it as an opportunity to put special placeholder markers on the field
+ * stack so we can get the field id deltas correct.
+ */
+func (p *TCompactProtocol) WriteStructBegin(name string) TProtocolException {
+ p.lastField.Push(p.lastFieldId)
+ p.lastFieldId = 0
+ return nil
+}
+
+/**
+ * Write a struct end. This doesn't actually put anything on the wire. We use
+ * this as an opportunity to pop the last field from the current struct off
+ * of the field stack.
+ */
+func (p *TCompactProtocol) WriteStructEnd() TProtocolException {
+ p.lastFieldId = p.lastField.Pop()
+ return nil
+}
+
+func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+ if typeId == BOOL {
+ // we want to possibly include the value, so we'll wait.
+ p.booleanField = NewTField(name, typeId, int(id))
+ return nil
+ }
+ _, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+
+/**
+ * The workhorse of writeFieldBegin. It has the option of doing a
+ * 'type override' of the type header. This is used specifically in the
+ * boolean field case.
+ */
+func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, os.Error) {
+ // short lastField = lastField_.pop();
+
+ // if there's a type override, use that.
+ var typeToWrite byte
+ if typeOverride == 0xFF {
+ typeToWrite = byte(p.getCompactType(typeId))
+ } else {
+ typeToWrite = typeOverride
+ }
+ // check if we can use delta encoding for the field id
+ fieldId := int(id)
+ written := 0
+ if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 {
+ // write them together
+ written, err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite)
+ if err != nil {
+ return written, err
+ }
+ } else {
+ // write them separate
+ n, err := p.writeByteDirect(typeToWrite)
+ if err != nil {
+ return n, err
+ }
+ err = p.WriteI16(id)
+ written = n + 2
+ if err != nil {
+ return written, err
+ }
+ }
+
+ p.lastFieldId = fieldId
+ // p.lastField.Push(field.id);
+ return written, nil
+}
+
+
+func (p *TCompactProtocol) WriteFieldEnd() TProtocolException { return nil }
+
+func (p *TCompactProtocol) WriteFieldStop() TProtocolException {
+ _, err := p.writeByteDirect(STOP)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+ if size == 0 {
+ _, err := p.writeByteDirect(0)
+ return NewTProtocolExceptionFromOsError(err)
+ }
+ _, err := p.writeVarint32(int32(size))
+ if err != nil {
+ return NewTProtocolExceptionFromOsError(err)
+ }
+ _, err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType)))
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteMapEnd() TProtocolException { return nil }
+
+/**
+ * Write a list header.
+ */
+func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+ _, err := p.writeCollectionBegin(elemType, size)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteListEnd() TProtocolException { return nil }
+
+/**
+ * Write a set header.
+ */
+func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+ _, err := p.writeCollectionBegin(elemType, size)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteSetEnd() TProtocolException { return nil }
+
+func (p *TCompactProtocol) WriteBool(value bool) TProtocolException {
+ v := byte(COMPACT_BOOLEAN_FALSE)
+ if value {
+ v = byte(COMPACT_BOOLEAN_TRUE)
+ }
+ if p.booleanField != nil {
+ // we haven't written the field header yet
+ _, err := p.writeFieldBeginInternal(p.booleanField.Name(), p.booleanField.TypeId(), int16(p.booleanField.Id()), v)
+ p.booleanField = nil
+ return NewTProtocolExceptionFromOsError(err)
+ }
+ // we're not part of a field, so just write the value.
+ _, err := p.writeByteDirect(v)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write a byte. Nothing to see here!
+ */
+func (p *TCompactProtocol) WriteByte(value byte) TProtocolException {
+ _, err := p.writeByteDirect(value)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write an I16 as a zigzag varint.
+ */
+func (p *TCompactProtocol) WriteI16(value int16) TProtocolException {
+ _, err := p.writeVarint32(p.int32ToZigzag(int32(value)))
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write an i32 as a zigzag varint.
+ */
+func (p *TCompactProtocol) WriteI32(value int32) TProtocolException {
+ _, err := p.writeVarint32(p.int32ToZigzag(value))
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write an i64 as a zigzag varint.
+ */
+func (p *TCompactProtocol) WriteI64(value int64) TProtocolException {
+ _, err := p.writeVarint64(p.int64ToZigzag(value))
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write a double to the wire as 8 bytes.
+ */
+func (p *TCompactProtocol) WriteDouble(value float64) TProtocolException {
+ buf := make([]byte, 8)
+ binary.LittleEndian.PutUint64(buf, math.Float64bits(value))
+ _, err := p.trans.Write(buf)
+ return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write a string to the wire with a varint size preceeding.
+ */
+func (p *TCompactProtocol) WriteString(value string) TProtocolException {
+ buf := make([]byte, len(value))
+ strings.NewReader(value).Read(buf)
+ return p.WriteBinary(buf)
+}
+
+/**
+ * Write a byte array, using a varint for the size.
+ */
+func (p *TCompactProtocol) WriteBinary(bin []byte) TProtocolException {
+ _, e := p.writeVarint32(int32(len(bin)))
+ if e != nil {
+ return NewTProtocolExceptionFromOsError(e)
+ }
+ if len(bin) > 0 {
+ _, e = p.trans.Write(bin)
+ return NewTProtocolExceptionFromOsError(e)
+ }
+ return nil
+}
+
+
+//
+// Reading methods.
+//
+
+/**
+ * Read a message header.
+ */
+func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) {
+ protocolId, err := p.ReadByte()
+ if protocolId != COMPACT_PROTOCOL_ID {
+ s := fmt.Sprintf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId)
+ return "", typeId, seqId, NewTProtocolException(BAD_VERSION, s)
+ }
+ versionAndType, err := p.ReadByte()
+ version := versionAndType & COMPACT_VERSION_MASK
+ typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & 0x03)
+ if err != nil {
+ return
+ }
+ if version != COMPACT_VERSION {
+ s := fmt.Sprintf("Expected version %02x but got %02x", COMPACT_VERSION, version)
+ err = NewTProtocolException(BAD_VERSION, s)
+ return
+ }
+ seqId, e := p.readVarint32()
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ name, err = p.ReadString()
+ return
+}
+
+func (p *TCompactProtocol) ReadMessageEnd() TProtocolException { return nil }
+
+/**
+ * Read a struct begin. There's nothing on the wire for this, but it is our
+ * opportunity to push a new struct begin marker onto the field stack.
+ */
+func (p *TCompactProtocol) ReadStructBegin() (name string, err TProtocolException) {
+ p.lastField.Push(p.lastFieldId)
+ p.lastFieldId = 0
+ return
+}
+
+/**
+ * Doesn't actually consume any wire data, just removes the last field for
+ * this struct from the field stack.
+ */
+func (p *TCompactProtocol) ReadStructEnd() TProtocolException {
+ // consume the last field we read off the wire.
+ p.lastFieldId = p.lastField.Pop()
+ return nil
+}
+
+/**
+ * Read a field header off the wire.
+ */
+func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err TProtocolException) {
+ t, err := p.ReadByte()
+ if err != nil {
+ return
+ }
+
+ // if it's a stop, then we can return immediately, as the struct is over.
+ if (t & 0x0f) == STOP {
+ return _TSTOP.Name(), _TSTOP.TypeId(), int16(_TSTOP.Id()), nil
+ }
+
+ // mask off the 4 MSB of the type header. it could contain a field id delta.
+ modifier := int16((t & 0xf0) >> 4)
+ if modifier == 0 {
+ // not a delta. look ahead for the zigzag varint field id.
+ id, err = p.ReadI16()
+ if err != nil {
+ return
+ }
+ } else {
+ // has a delta. add the delta to the last read field id.
+ id = int16(p.lastFieldId) + modifier
+ }
+ typeId, e := p.getTType(TCompactType(t & 0x0f))
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+
+ // if this happens to be a boolean field, the value is encoded in the type
+ if p.isBoolType(t) {
+ // save the boolean value in a special instance variable.
+ p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE)
+ p.boolValueIsNotNull = true
+ }
+
+ // push the new field onto the field stack so we can keep the deltas going.
+ p.lastFieldId = int(id)
+ return
+}
+
+func (p *TCompactProtocol) ReadFieldEnd() TProtocolException { return nil }
+
+/**
+ * Read a map header off the wire. If the size is zero, skip reading the key
+ * and value type. This means that 0-length maps will yield TMaps without the
+ * "correct" types.
+ */
+func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err TProtocolException) {
+ size32, e := p.readVarint32()
+ size = int(size32)
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ keyAndValueType := byte(STOP)
+ if size != 0 {
+ keyAndValueType, err = p.ReadByte()
+ if err != nil {
+ return
+ }
+ }
+ keyType, _ = p.getTType(TCompactType(keyAndValueType >> 4))
+ valueType, _ = p.getTType(TCompactType(keyAndValueType & 0xf))
+ return
+}
+
+func (p *TCompactProtocol) ReadMapEnd() TProtocolException { return nil }
+
+/**
+ * Read a list header off the wire. If the list size is 0-14, the size will
+ * be packed into the element type header. If it's a longer list, the 4 MSB
+ * of the element type header will be 0xF, and a varint will follow with the
+ * true size.
+ */
+func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err TProtocolException) {
+ size_and_type, err := p.ReadByte()
+ if err != nil {
+ return
+ }
+ size = int((size_and_type >> 4) & 0x0f)
+ if size == 15 {
+ size2, e := p.readVarint32()
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ size = int(size2)
+ }
+ elemType, e := p.getTType(TCompactType(size_and_type))
+ if e != nil {
+ err = NewTProtocolExceptionFromOsError(e)
+ return
+ }
+ return
+}
+
+func (p *TCompactProtocol) ReadListEnd() TProtocolException { return nil }
+
+/**
+ * Read a set header off the wire. If the set size is 0-14, the size will
+ * be packed into the element type header. If it's a longer set, the 4 MSB
+ * of the element type header will be 0xF, and a varint will follow with the
+ * true size.
+ */
+func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err TProtocolException) {
+ return p.ReadListBegin()
+}
+
+func (p *TCompactProtocol) ReadSetEnd() TProtocolException { return nil }
+
+/**
+ * Read a boolean off the wire. If this is a boolean field, the value should
+ * already have been read during readFieldBegin, so we'll just consume the
+ * pre-stored value. Otherwise, read a byte.
+ */
+func (p *TCompactProtocol) ReadBool() (value bool, err TProtocolException) {
+ if p.boolValueIsNotNull {
+ p.boolValueIsNotNull = false
+ return p.boolValue, nil
+ }
+ v, err := p.ReadByte()
+ return v == COMPACT_BOOLEAN_TRUE, err
+}
+
+/**
+ * Read a single byte off the wire. Nothing interesting here.
+ */
+func (p *TCompactProtocol) ReadByte() (value byte, err TProtocolException) {
+ buf := []byte{0}
+ _, e := p.trans.ReadAll(buf)
+ if e != nil {
+ return 0, NewTProtocolExceptionFromOsError(e)
+ }
+ return buf[0], nil
+}
+
+/**
+ * Read an i16 from the wire as a zigzag varint.
+ */
+func (p *TCompactProtocol) ReadI16() (value int16, err TProtocolException) {
+ v, err := p.ReadI32()
+ return int16(v), err
+}
+
+/**
+ * Read an i32 from the wire as a zigzag varint.
+ */
+func (p *TCompactProtocol) ReadI32() (value int32, err TProtocolException) {
+ v, e := p.readVarint32()
+ if e != nil {
+ return 0, NewTProtocolExceptionFromOsError(e)
+ }
+ value = p.zigzagToInt32(v)
+ return value, nil
+}
+
+/**
+ * Read an i64 from the wire as a zigzag varint.
+ */
+func (p *TCompactProtocol) ReadI64() (value int64, err TProtocolException) {
+ v, e := p.readVarint64()
+ if e != nil {
+ return 0, NewTProtocolExceptionFromOsError(e)
+ }
+ value = p.zigzagToInt64(v)
+ return value, nil
+}
+
+/**
+ * No magic here - just read a double off the wire.
+ */
+func (p *TCompactProtocol) ReadDouble() (value float64, err TProtocolException) {
+ longBits := make([]byte, 8)
+ _, e := p.trans.ReadAll(longBits)
+ if e != nil {
+ return 0.0, NewTProtocolExceptionFromOsError(e)
+ }
+ return math.Float64frombits(p.bytesToUint64(longBits)), nil
+}
+
+/**
+ * Reads a []byte (via readBinary), and then UTF-8 decodes it.
+ */
+func (p *TCompactProtocol) ReadString() (value string, err TProtocolException) {
+ v, e := p.ReadBinary()
+ return string(v), NewTProtocolExceptionFromOsError(e)
+}
+
+/**
+ * Read a []byte from the wire.
+ */
+func (p *TCompactProtocol) ReadBinary() (value []byte, err TProtocolException) {
+ length, e := p.readVarint32()
+ if e != nil {
+ return []byte{}, NewTProtocolExceptionFromOsError(e)
+ }
+ if length == 0 {
+ return []byte{}, nil
+ }
+
+ buf := make([]byte, length)
+ p.trans.ReadAll(buf)
+ return buf, nil
+}
+
+func (p *TCompactProtocol) Flush() (err TProtocolException) {
+ return NewTProtocolExceptionFromOsError(p.trans.Flush())
+}
+
+func (p *TCompactProtocol) Skip(fieldType TType) (err TProtocolException) {
+ return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TCompactProtocol) Transport() TTransport {
+ return p.trans
+}
+
+//
+// Internal writing methods
+//
+
+/**
+ * Abstract method for writing the start of lists and sets. List and sets on
+ * the wire differ only by the type indicator.
+ */
+func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, os.Error) {
+ if size <= 14 {
+ return p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType))))
+ }
+ n, err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType)))
+ if err != nil {
+ return n, err
+ }
+ m, err := p.writeVarint32(int32(size))
+ return n + m, err
+}
+
+/**
+ * Write an i32 as a varint. Results in 1-5 bytes on the wire.
+ * TODO(pomack): make a permanent buffer like writeVarint64?
+ */
+func (p *TCompactProtocol) writeVarint32(n int32) (int, os.Error) {
+ i32buf := make([]byte, 5)
+ idx := 0
+ for {
+ if (n & ^0x7F) == 0 {
+ i32buf[idx] = byte(n)
+ idx++
+ // p.writeByteDirect(byte(n));
+ break
+ // return;
+ } else {
+ i32buf[idx] = byte((n & 0x7F) | 0x80)
+ idx++
+ // p.writeByteDirect(byte(((n & 0x7F) | 0x80)));
+ u := uint32(n)
+ n = int32(u >> 7)
+ }
+ }
+ return p.trans.Write(i32buf[0:idx])
+}
+
+/**
+ * Write an i64 as a varint. Results in 1-10 bytes on the wire.
+ */
+func (p *TCompactProtocol) writeVarint64(n int64) (int, os.Error) {
+ varint64out := make([]byte, 10)
+ idx := 0
+ for {
+ if (n & ^0x7F) == 0 {
+ varint64out[idx] = byte(n)
+ idx++
+ break
+ } else {
+ varint64out[idx] = byte((n & 0x7F) | 0x80)
+ idx++
+ u := uint64(n)
+ n = int64(u >> 7)
+ }
+ }
+ return p.trans.Write(varint64out[0:idx])
+}
+
+/**
+ * Convert l into a zigzag long. This allows negative numbers to be
+ * represented compactly as a varint.
+ */
+func (p *TCompactProtocol) int64ToZigzag(l int64) int64 {
+ return (l << 1) ^ (l >> 63)
+}
+
+/**
+ * Convert l into a zigzag long. This allows negative numbers to be
+ * represented compactly as a varint.
+ */
+func (p *TCompactProtocol) int32ToZigzag(n int32) int32 {
+ return (n << 1) ^ (n >> 31)
+}
+
+func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) {
+ binary.LittleEndian.PutUint64(buf, n)
+}
+
+func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) {
+ binary.LittleEndian.PutUint64(buf, uint64(n))
+}
+
+/**
+ * Writes a byte without any possiblity of all that field header nonsense.
+ * Used internally by other writing methods that know they need to write a byte.
+ */
+func (p *TCompactProtocol) writeByteDirect(b byte) (int, os.Error) {
+ return p.trans.Write([]byte{b})
+}
+
+/**
+ * Writes a byte without any possiblity of all that field header nonsense.
+ */
+func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, os.Error) {
+ return p.writeByteDirect(byte(n))
+}
+
+
+//
+// Internal reading methods
+//
+
+/**
+ * Read an i32 from the wire as a varint. The MSB of each byte is set
+ * if there is another byte to follow. This can read up to 5 bytes.
+ */
+func (p *TCompactProtocol) readVarint32() (int32, os.Error) {
+ // if the wire contains the right stuff, this will just truncate the i64 we
+ // read and get us the right sign.
+ v, err := p.readVarint64()
+ return int32(v), err
+}
+
+
+/**
+ * Read an i64 from the wire as a proper varint. The MSB of each byte is set
+ * if there is another byte to follow. This can read up to 10 bytes.
+ */
+func (p *TCompactProtocol) readVarint64() (int64, os.Error) {
+ shift := uint(0)
+ result := int64(0)
+ for {
+ b, err := p.ReadByte()
+ if err != nil {
+ return 0, err
+ }
+ result |= int64(b&0x7f) << shift
+ if (b & 0x80) != 0x80 {
+ break
+ }
+ shift += 7
+ }
+ return result, nil
+}
+
+
+//
+// encoding helpers
+//
+
+/**
+ * Convert from zigzag int to int.
+ */
+func (p *TCompactProtocol) zigzagToInt32(n int32) int32 {
+ u := uint32(n)
+ return int32(u>>1) ^ -(n & 1)
+}
+
+/**
+ * Convert from zigzag long to long.
+ */
+func (p *TCompactProtocol) zigzagToInt64(n int64) int64 {
+ u := uint64(n)
+ return int64(u>>1) ^ -(n & 1)
+}
+
+/**
+ * Note that it's important that the mask bytes are long literals,
+ * otherwise they'll default to ints, and when you shift an int left 56 bits,
+ * you just get a messed up int.
+ */
+func (p *TCompactProtocol) bytesToInt64(b []byte) int64 {
+ return int64(binary.LittleEndian.Uint64(b))
+}
+
+/**
+ * Note that it's important that the mask bytes are long literals,
+ * otherwise they'll default to ints, and when you shift an int left 56 bits,
+ * you just get a messed up int.
+ */
+func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 {
+ return binary.LittleEndian.Uint64(b)
+}
+
+//
+// type testing and converting
+//
+
+func (p *TCompactProtocol) isBoolType(b byte) bool {
+ return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE
+}
+
+/**
+ * Given a TCompactType constant, convert it to its corresponding
+ * TType value.
+ */
+func (p *TCompactProtocol) getTType(t TCompactType) (TType, os.Error) {
+ switch byte(t) & 0x0f {
+ case STOP:
+ return STOP, nil
+ case COMPACT_BOOLEAN_FALSE:
+ case COMPACT_BOOLEAN_TRUE:
+ return BOOL, nil
+ case COMPACT_BYTE:
+ return BYTE, nil
+ case COMPACT_I16:
+ return I16, nil
+ case COMPACT_I32:
+ return I32, nil
+ case COMPACT_I64:
+ return I64, nil
+ case COMPACT_DOUBLE:
+ return DOUBLE, nil
+ case COMPACT_BINARY:
+ return STRING, nil
+ case COMPACT_LIST:
+ return LIST, nil
+ case COMPACT_SET:
+ return SET, nil
+ case COMPACT_MAP:
+ return MAP, nil
+ case COMPACT_STRUCT:
+ return STRUCT, nil
+ }
+ return STOP, NewTException("don't know what type: " + string(t&0x0f))
+}
+
+/**
+ * Given a TType value, find the appropriate TCompactProtocol.Types constant.
+ */
+func (p *TCompactProtocol) getCompactType(t TType) TCompactType {
+ return _TTypeToCompactType[int(t)]
+}
diff --git a/lib/go/thrift/tcompact_protocol_test.go b/lib/go/thrift/tcompact_protocol_test.go
new file mode 100644
index 0000000..da0e39c
--- /dev/null
+++ b/lib/go/thrift/tcompact_protocol_test.go
@@ -0,0 +1,56 @@
+/*
+ * 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"
+ "testing"
+ //"bytes";
+)
+
+func TestReadWriteCompactProtocol(t *testing.T) {
+ ReadWriteProtocolTest(t, NewTCompactProtocolFactory())
+ /*
+ transports := []TTransport{
+ NewTMemoryBuffer(),
+ NewTIOStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 16384))),
+ NewTFramedTransport(NewTMemoryBuffer()),
+ }
+ for _, trans := range transports {
+ p := NewTCompactProtocol(trans);
+ ReadWriteBool(t, p, trans);
+ p = NewTCompactProtocol(trans);
+ ReadWriteByte(t, p, trans);
+ p = NewTCompactProtocol(trans);
+ ReadWriteI16(t, p, trans);
+ p = NewTCompactProtocol(trans);
+ ReadWriteI32(t, p, trans);
+ p = NewTCompactProtocol(trans);
+ ReadWriteI64(t, p, trans);
+ p = NewTCompactProtocol(trans);
+ ReadWriteDouble(t, p, trans);
+ p = NewTCompactProtocol(trans);
+ ReadWriteString(t, p, trans);
+ p = NewTCompactProtocol(trans);
+ ReadWriteBinary(t, p, trans);
+ trans.Close();
+ }
+ */
+}
diff --git a/lib/go/thrift/tcompare.go b/lib/go/thrift/tcompare.go
new file mode 100644
index 0000000..01fef44
--- /dev/null
+++ b/lib/go/thrift/tcompare.go
@@ -0,0 +1,127 @@
+/*
+ * 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
+
+func CompareInt(i, j int) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareInt16(i, j int16) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareInt32(i, j int32) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareInt64(i, j int32) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareStringArray(i, j []string) int {
+ if cmp := CompareInt(len(i), len(j)); cmp != 0 {
+ return cmp
+ }
+ size := len(i)
+ for k := 0; k < size; k++ {
+ if cmp := CompareString(i[k], j[k]); cmp != 0 {
+ return cmp
+ }
+ }
+ return 0
+}
+
+func CompareString(i, j string) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareFloat(i, j float32) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareDouble(i, j float64) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareByte(i, j byte) int {
+ if i > j {
+ return 1
+ }
+ if i < j {
+ return -1
+ }
+ return 0
+}
+
+func CompareBool(i, j bool) int {
+ if i {
+ if j {
+ return 0
+ }
+ return 1
+ }
+ if j {
+ return -1
+ }
+ return 0
+}
diff --git a/lib/go/thrift/tcontainer.go b/lib/go/thrift/tcontainer.go
new file mode 100644
index 0000000..9ea3cba
--- /dev/null
+++ b/lib/go/thrift/tcontainer.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
+
+type TContainer interface {
+ Len() int
+ Contains(data interface{}) bool
+ Equals(other interface{}) bool
+ CompareTo(other interface{}) (int, bool)
+}
diff --git a/lib/go/thrift/texception.go b/lib/go/thrift/texception.go
new file mode 100644
index 0000000..be6cbd5
--- /dev/null
+++ b/lib/go/thrift/texception.go
@@ -0,0 +1,56 @@
+/*
+ * 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"
+)
+
+/**
+ * Generic exception class for Thrift.
+ *
+ */
+
+type TException interface {
+ String() string
+}
+
+type tException struct {
+ message string
+}
+
+func (p *tException) String() string {
+ return p.message
+}
+
+func NewTException(m string) TException {
+ return &tException{message: m}
+}
+
+func NewTExceptionFromOsError(e os.Error) TException {
+ if e == nil {
+ return nil
+ }
+ t, ok := e.(TException)
+ if ok {
+ return t
+ }
+ return NewTException(e.String())
+}
diff --git a/lib/go/thrift/texception_test.go b/lib/go/thrift/texception_test.go
new file mode 100644
index 0000000..50b3cdd
--- /dev/null
+++ b/lib/go/thrift/texception_test.go
@@ -0,0 +1,38 @@
+/*
+ * 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"
+ "os"
+ "testing"
+)
+
+
+func TestTException(t *testing.T) {
+ exc := NewTException("")
+ if exc.String() != "" {
+ t.Fatalf("Expected empty string for exception but found '%s'", exc.String())
+ }
+ exc = NewTExceptionFromOsError(os.EOF)
+ if exc.String() != os.EOF.String() {
+ t.Fatalf("Expected '%s', but found '%s'", os.EOF.String(), exc.String())
+ }
+}
diff --git a/lib/go/thrift/tfield.go b/lib/go/thrift/tfield.go
new file mode 100644
index 0000000..31d9b89
--- /dev/null
+++ b/lib/go/thrift/tfield.go
@@ -0,0 +1,281 @@
+/*
+ * 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 (
+ "sort"
+)
+
+/**
+ * Helper class that encapsulates field metadata.
+ *
+ */
+type TField interface {
+ Name() string
+ TypeId() TType
+ Id() int
+ String() string
+ CompareTo(other interface{}) (int, bool)
+ Equals(other interface{}) bool
+}
+
+type tField struct {
+ name string
+ typeId TType
+ id int
+}
+
+func NewTFieldDefault() TField {
+ return ANONYMOUS_FIELD
+}
+
+func NewTField(n string, t TType, i int) TField {
+ return &tField{name: n, typeId: t, id: i}
+}
+
+func (p *tField) Name() string {
+ if p == nil {
+ return ""
+ }
+ return p.name
+}
+
+func (p *tField) TypeId() TType {
+ if p == nil {
+ return TType(VOID)
+ }
+ return p.typeId
+}
+
+func (p *tField) Id() int {
+ if p == nil {
+ return -1
+ }
+ return p.id
+}
+
+func (p *tField) String() string {
+ if p == nil {
+ return "<nil>"
+ }
+ return "<TField name:'" + p.name + "' type:" + string(p.typeId) + " field-id:" + string(p.id) + ">"
+}
+
+func (p *tField) CompareTo(other interface{}) (int, bool) {
+ if other == nil {
+ return 1, true
+ }
+ if data, ok := other.(TField); ok {
+ if p.Id() != data.Id() {
+ return CompareInt(p.Id(), data.Id()), true
+ }
+ if p.TypeId() != data.TypeId() {
+ return CompareByte(byte(p.TypeId()), byte(data.TypeId())), true
+ }
+ return CompareString(p.Name(), data.Name()), true
+ }
+ return 0, false
+}
+
+func (p *tField) Equals(other interface{}) bool {
+ if p == nil {
+ return other == nil
+ }
+ if other == nil {
+ return false
+ }
+ if data, ok := other.(TField); ok {
+ return p.TypeId() == data.TypeId() && p.Id() == data.Id()
+ }
+ return false
+}
+
+var ANONYMOUS_FIELD TField
+
+type tFieldArray []TField
+
+func (p tFieldArray) Len() int {
+ return len(p)
+}
+
+func (p tFieldArray) Less(i, j int) bool {
+ return p[i].Id() < p[j].Id()
+}
+
+func (p tFieldArray) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+type TFieldContainer interface {
+ TContainer
+ FieldNameFromFieldId(id int) string
+ FieldIdFromFieldName(name string) int
+ FieldFromFieldId(id int) TField
+ FieldFromFieldName(name string) TField
+ At(i int) TField
+ Iter() <-chan TField
+}
+
+type tFieldContainer struct {
+ fields []TField
+ nameToFieldMap map[string]TField
+ idToFieldMap map[int]TField
+}
+
+func NewTFieldContainer(fields []TField) TFieldContainer {
+ sortedFields := make([]TField, len(fields))
+ nameToFieldMap := make(map[string]TField)
+ idToFieldMap := make(map[int]TField)
+ for i, field := range fields {
+ sortedFields[i] = field
+ idToFieldMap[field.Id()] = field
+ if field.Name() != "" {
+ nameToFieldMap[field.Name()] = field
+ }
+ }
+ sort.Sort(tFieldArray(sortedFields))
+ return &tFieldContainer{
+ fields: fields,
+ nameToFieldMap: nameToFieldMap,
+ idToFieldMap: idToFieldMap,
+ }
+}
+
+func (p *tFieldContainer) FieldNameFromFieldId(id int) string {
+ if field, ok := p.idToFieldMap[id]; ok {
+ return field.Name()
+ }
+ return ""
+}
+
+func (p *tFieldContainer) FieldIdFromFieldName(name string) int {
+ if field, ok := p.nameToFieldMap[name]; ok {
+ return field.Id()
+ }
+ return -1
+}
+
+func (p *tFieldContainer) FieldFromFieldId(id int) TField {
+ if field, ok := p.idToFieldMap[id]; ok {
+ return field
+ }
+ return ANONYMOUS_FIELD
+}
+
+func (p *tFieldContainer) FieldFromFieldName(name string) TField {
+ if field, ok := p.nameToFieldMap[name]; ok {
+ return field
+ }
+ return ANONYMOUS_FIELD
+}
+
+func (p *tFieldContainer) Len() int {
+ return len(p.fields)
+}
+
+func (p *tFieldContainer) At(i int) TField {
+ return p.FieldFromFieldId(i)
+}
+
+func (p *tFieldContainer) Contains(data interface{}) bool {
+ if i, ok := data.(int); ok {
+ for _, field := range p.fields {
+ if field.Id() == i {
+ return true
+ }
+ }
+ } else if i, ok := data.(int16); ok {
+ for _, field := range p.fields {
+ if field.Id() == int(i) {
+ return true
+ }
+ }
+ } else if s, ok := data.(string); ok {
+ for _, field := range p.fields {
+ if field.Name() == s {
+ return true
+ }
+ }
+ } else if f, ok := data.(TField); ok {
+ for _, field := range p.fields {
+ if field.Equals(f) {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+func (p *tFieldContainer) Equals(other interface{}) bool {
+ if other == nil {
+ return false
+ }
+ if data, ok := other.(TFieldContainer); ok {
+ if p.Len() != data.Len() {
+ return false
+ }
+ for _, field := range p.fields {
+ if !data.Contains(field) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+func (p *tFieldContainer) CompareTo(other interface{}) (int, bool) {
+ if other == nil {
+ return 1, true
+ }
+ if data, ok := other.(TFieldContainer); ok {
+ cont, ok2 := data.(*tFieldContainer)
+ if ok2 && p == cont {
+ return 0, true
+ }
+ if cmp := CompareInt(p.Len(), data.Len()); cmp != 0 {
+ return cmp, true
+ }
+ for _, field := range p.fields {
+ if cmp, ok3 := field.CompareTo(data.At(field.Id())); !ok3 || cmp != 0 {
+ return cmp, ok3
+ }
+ }
+ return 0, true
+ }
+ return 0, false
+}
+
+func (p *tFieldContainer) Iter() <-chan TField {
+ c := make(chan TField)
+ go p.iterate(c)
+ return c
+}
+
+func (p *tFieldContainer) iterate(c chan<- TField) {
+ for _, v := range p.fields {
+ c <- v
+ }
+ close(c)
+}
+
+func init() {
+ ANONYMOUS_FIELD = NewTField("", STOP, 0)
+}
diff --git a/lib/go/thrift/tframed_transport.go b/lib/go/thrift/tframed_transport.go
new file mode 100644
index 0000000..52049cb
--- /dev/null
+++ b/lib/go/thrift/tframed_transport.go
@@ -0,0 +1,133 @@
+/*
+ * 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/binary"
+ "bytes"
+ "os"
+)
+
+
+type TFramedTransport struct {
+ transport TTransport
+ writeBuffer *bytes.Buffer
+ readBuffer *bytes.Buffer
+}
+
+type tFramedTransportFactory struct {
+ factory TTransportFactory
+}
+
+func NewTFramedTransportFactory(factory TTransportFactory) TTransportFactory {
+ return &tFramedTransportFactory{factory: factory}
+}
+
+func (p *tFramedTransportFactory) GetTransport(base TTransport) TTransport {
+ return NewTFramedTransport(p.factory.GetTransport(base))
+}
+
+func NewTFramedTransport(transport TTransport) *TFramedTransport {
+ writeBuf := make([]byte, 0, 1024)
+ readBuf := make([]byte, 0, 1024)
+ return &TFramedTransport{transport: transport, writeBuffer: bytes.NewBuffer(writeBuf), readBuffer: bytes.NewBuffer(readBuf)}
+}
+
+func (p *TFramedTransport) Open() os.Error {
+ return p.transport.Open()
+}
+
+func (p *TFramedTransport) IsOpen() bool {
+ return p.transport.IsOpen()
+}
+
+func (p *TFramedTransport) Peek() bool {
+ return p.transport.Peek()
+}
+
+func (p *TFramedTransport) Close() os.Error {
+ return p.transport.Close()
+}
+
+func (p *TFramedTransport) Read(buf []byte) (int, os.Error) {
+ if p.readBuffer.Len() > 0 {
+ got, err := p.readBuffer.Read(buf)
+ if got > 0 {
+ return got, NewTTransportExceptionFromOsError(err)
+ }
+ }
+
+ // Read another frame of data
+ p.readFrame()
+
+ got, err := p.readBuffer.Read(buf)
+ return got, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TFramedTransport) ReadAll(buf []byte) (int, os.Error) {
+ return ReadAllTransport(p, buf)
+}
+
+func (p *TFramedTransport) Write(buf []byte) (int, os.Error) {
+ n, err := p.writeBuffer.Write(buf)
+ return n, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TFramedTransport) Flush() os.Error {
+ size := p.writeBuffer.Len()
+ buf := []byte{0, 0, 0, 0}
+ binary.BigEndian.PutUint32(buf, uint32(size))
+ _, err := p.transport.Write(buf)
+ if err != nil {
+ return NewTTransportExceptionFromOsError(err)
+ }
+ if size > 0 {
+ n, err := p.writeBuffer.WriteTo(p.transport)
+ if err != nil {
+ print("Error while flushing write buffer of size ", size, " to transport, only wrote ", n, " bytes: ", err.String(), "\n")
+ return NewTTransportExceptionFromOsError(err)
+ }
+ }
+ err = p.transport.Flush()
+ return NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TFramedTransport) readFrame() (int, os.Error) {
+ buf := []byte{0, 0, 0, 0}
+ _, err := p.transport.ReadAll(buf)
+ if err != nil {
+ return 0, err
+ }
+ size := int(binary.BigEndian.Uint32(buf))
+ if size < 0 {
+ // TODO(pomack) log error
+ return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Read a negative frame size ("+string(size)+")")
+ }
+ if size == 0 {
+ return 0, nil
+ }
+ buf2 := make([]byte, size)
+ n, err := p.transport.ReadAll(buf2)
+ if err != nil {
+ return n, err
+ }
+ p.readBuffer = bytes.NewBuffer(buf2)
+ return size, nil
+}
diff --git a/lib/go/thrift/tframed_transport_test.go b/lib/go/thrift/tframed_transport_test.go
new file mode 100644
index 0000000..566318c
--- /dev/null
+++ b/lib/go/thrift/tframed_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_test
+
+import (
+ . "thrift"
+ "testing"
+)
+
+func TestFramedTransport(t *testing.T) {
+ trans := NewTFramedTransport(NewTMemoryBuffer())
+ TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/thttp_client.go b/lib/go/thrift/thttp_client.go
new file mode 100644
index 0000000..e09ecdf
--- /dev/null
+++ b/lib/go/thrift/thttp_client.go
@@ -0,0 +1,146 @@
+/*
+ * 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"
+ "http"
+ "os"
+)
+
+
+type THttpClient struct {
+ response *http.Response
+ url *http.URL
+ requestBuffer *bytes.Buffer
+ nsecConnectTimeout int64
+ nsecReadTimeout int64
+}
+
+type THttpClientTransportFactory struct {
+ url string
+ isPost bool
+}
+
+func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport {
+ if trans != nil {
+ t, ok := trans.(*THttpClient)
+ if ok && t.url != nil {
+ if t.requestBuffer != nil {
+ t2, _ := NewTHttpPostClient(t.url.String())
+ return t2
+ }
+ t2, _ := NewTHttpClient(t.url.String())
+ return t2
+ }
+ }
+ if p.isPost {
+ s, _ := NewTHttpPostClient(p.url)
+ return s
+ }
+ s, _ := NewTHttpClient(p.url)
+ return s
+}
+
+func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory {
+ return &THttpClientTransportFactory{url: url, isPost: false}
+}
+
+func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory {
+ return &THttpClientTransportFactory{url: url, isPost: true}
+}
+
+
+func NewTHttpClient(url string) (TTransport, os.Error) {
+ response, finalUrl, err := http.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ parsedURL, err := http.ParseURL(finalUrl)
+ if err != nil {
+ return nil, err
+ }
+ return &THttpClient{response: response, url: parsedURL}, nil
+}
+
+func NewTHttpPostClient(url string) (TTransport, os.Error) {
+ parsedURL, err := http.ParseURL(url)
+ if err != nil {
+ return nil, err
+ }
+ buf := make([]byte, 0, 1024)
+ return &THttpClient{url: parsedURL, requestBuffer: bytes.NewBuffer(buf)}, nil
+}
+
+func (p *THttpClient) Open() os.Error {
+ // do nothing
+ return nil
+}
+
+func (p *THttpClient) IsOpen() bool {
+ return p.response != nil || p.requestBuffer != nil
+}
+
+func (p *THttpClient) Peek() bool {
+ return p.IsOpen()
+}
+
+func (p *THttpClient) Close() os.Error {
+ if p.response != nil && p.response.Body != nil {
+ err := p.response.Body.Close()
+ p.response = nil
+ return err
+ }
+ if p.requestBuffer != nil {
+ p.requestBuffer.Reset()
+ p.requestBuffer = nil
+ }
+ return nil
+}
+
+func (p *THttpClient) Read(buf []byte) (int, os.Error) {
+ if p.response == nil {
+ return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.")
+ }
+ n, err := p.response.Body.Read(buf)
+ return n, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *THttpClient) ReadAll(buf []byte) (int, os.Error) {
+ return ReadAllTransport(p, buf)
+}
+
+func (p *THttpClient) Write(buf []byte) (int, os.Error) {
+ n, err := p.requestBuffer.Write(buf)
+ return n, err
+}
+
+func (p *THttpClient) Flush() os.Error {
+ response, err := http.Post(p.url.String(), "application/x-thrift", p.requestBuffer)
+ if err != nil {
+ return NewTTransportExceptionFromOsError(err)
+ }
+ if response.StatusCode != http.StatusOK {
+ // TODO(pomack) log bad response
+ return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+string(response.StatusCode))
+ }
+ p.response = response
+ return nil
+}
diff --git a/lib/go/thrift/thttp_client_test.go b/lib/go/thrift/thttp_client_test.go
new file mode 100644
index 0000000..1af8cd3
--- /dev/null
+++ b/lib/go/thrift/thttp_client_test.go
@@ -0,0 +1,45 @@
+/*
+ * 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"
+ "testing"
+ "http"
+ "net"
+)
+
+func TestHttpClient(t *testing.T) {
+ addr, err := FindAvailableTCPServerPort(40000)
+ if err != nil {
+ t.Fatalf("Unable to find available tcp port addr: %s", err)
+ }
+ l, err := net.Listen(addr.Network(), addr.String())
+ if err != nil {
+ t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err)
+ }
+ go http.Serve(l, &HTTPEchoServer{})
+ trans, err := NewTHttpPostClient("http://" + addr.String())
+ if err != nil {
+ l.Close()
+ t.Fatalf("Unable to connect to %s: %s", addr.String(), err)
+ }
+ TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/tiostream_transport.go b/lib/go/thrift/tiostream_transport.go
new file mode 100644
index 0000000..5c4beea
--- /dev/null
+++ b/lib/go/thrift/tiostream_transport.go
@@ -0,0 +1,231 @@
+/*
+ * 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"
+ "io"
+ "os"
+)
+
+/**
+ * This is the most commonly used base transport. It takes an InputStream
+ * and an OutputStream and uses those to perform all transport operations.
+ * This allows for compatibility with all the nice constructs Java already
+ * has to provide a variety of types of streams.
+ *
+ */
+type TIOStreamTransport struct {
+ Reader io.Reader
+ Writer io.Writer
+ IsReadWriter bool
+}
+
+type TIOStreamTransportFactory struct {
+ Reader io.Reader
+ Writer io.Writer
+ IsReadWriter bool
+}
+
+func (p *TIOStreamTransportFactory) GetTransport(trans TTransport) TTransport {
+ if trans != nil {
+ t, ok := trans.(*TIOStreamTransport)
+ if ok {
+ if t.IsReadWriter {
+ return NewTIOStreamTransportRW(t.Reader.(io.ReadWriter))
+ }
+ if t.Reader != nil && t.Writer != nil {
+ return NewTIOStreamTransportRAndW(t.Reader, t.Writer)
+ }
+ if t.Reader != nil && t.Writer == nil {
+ return NewTIOStreamTransportR(t.Reader)
+ }
+ if t.Reader == nil && t.Writer != nil {
+ return NewTIOStreamTransportW(t.Writer)
+ }
+ return NewTIOStreamTransportDefault()
+ }
+ }
+ if p.IsReadWriter {
+ return NewTIOStreamTransportRW(p.Reader.(io.ReadWriter))
+ }
+ if p.Reader != nil && p.Writer != nil {
+ return NewTIOStreamTransportRAndW(p.Reader, p.Writer)
+ }
+ if p.Reader != nil && p.Writer == nil {
+ return NewTIOStreamTransportR(p.Reader)
+ }
+ if p.Reader == nil && p.Writer != nil {
+ return NewTIOStreamTransportW(p.Writer)
+ }
+ return NewTIOStreamTransportDefault()
+}
+
+func NewTIOStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *TIOStreamTransportFactory {
+ return &TIOStreamTransportFactory{Reader: reader, Writer: writer, IsReadWriter: isReadWriter}
+}
+
+
+/**
+ * Subclasses can invoke the default constructor and then assign the input
+ * streams in the open method.
+ */
+func NewTIOStreamTransportDefault() *TIOStreamTransport {
+ return &TIOStreamTransport{}
+}
+
+/**
+ * Input stream constructor.
+ *
+ * @param is Input stream to read from
+ */
+func NewTIOStreamTransportR(r io.Reader) *TIOStreamTransport {
+ return &TIOStreamTransport{Reader: bufio.NewReader(r)}
+}
+
+/**
+ * Output stream constructor.
+ *
+ * @param os Output stream to read from
+ */
+func NewTIOStreamTransportW(w io.Writer) *TIOStreamTransport {
+ return &TIOStreamTransport{Writer: bufio.NewWriter(w)}
+}
+
+/**
+ * Two-way stream constructor.
+ *
+ * @param is Input stream to read from
+ * @param os Output stream to read from
+ */
+func NewTIOStreamTransportRAndW(r io.Reader, w io.Writer) *TIOStreamTransport {
+ return &TIOStreamTransport{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
+}
+
+/**
+ * Two-way stream constructor.
+ *
+ * @param is Input stream to read from
+ * @param os Output stream to read from
+ */
+func NewTIOStreamTransportRW(rw io.ReadWriter) *TIOStreamTransport {
+ // bufio has a bug where once a Reader hits EOF, a new Write never brings the reader out of EOF
+ // even if reader and writer use the same underlier
+ //bufrw := bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw));
+ return &TIOStreamTransport{Reader: rw, Writer: rw, IsReadWriter: true}
+}
+
+/**
+ * The streams must already be open at construction time, so this should
+ * always return true.
+ *
+ * @return true
+ */
+func (p *TIOStreamTransport) IsOpen() bool {
+ return true
+}
+
+/**
+ * The streams must already be open. This method does nothing.
+ */
+func (p *TIOStreamTransport) Open() os.Error {
+ return nil
+}
+
+func (p *TIOStreamTransport) Peek() bool {
+ return p.IsOpen()
+}
+
+/**
+ * Closes both the input and output streams.
+ */
+func (p *TIOStreamTransport) Close() os.Error {
+ closedReader := false
+ if p.Reader != nil {
+ c, ok := p.Reader.(io.Closer)
+ if ok {
+ e := c.Close()
+ closedReader = true
+ if e != nil {
+ LOGGER.Print("Error closing input stream.", e)
+ }
+ }
+ p.Reader = nil
+ }
+ if p.Writer != nil && (!closedReader || !p.IsReadWriter) {
+ c, ok := p.Writer.(io.Closer)
+ if ok {
+ e := c.Close()
+ if e != nil {
+ LOGGER.Print("Error closing output stream.", e)
+ }
+ }
+ p.Writer = nil
+ }
+ return nil
+}
+
+/**
+ * Reads from the underlying input stream if not null.
+ */
+func (p *TIOStreamTransport) Read(buf []byte) (int, os.Error) {
+ if p.Reader == nil {
+ return 0, NewTTransportException(NOT_OPEN, "Cannot read from null inputStream")
+ }
+ n, err := p.Reader.Read(buf)
+ return n, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TIOStreamTransport) ReadAll(buf []byte) (int, os.Error) {
+ return ReadAllTransport(p, buf)
+}
+
+
+/**
+ * Writes to the underlying output stream if not null.
+ */
+func (p *TIOStreamTransport) Write(buf []byte) (int, os.Error) {
+ if p.Writer == nil {
+ LOGGER.Print("Could not write to iostream as Writer is null\n")
+ return 0, NewTTransportException(NOT_OPEN, "Cannot write to null outputStream")
+ }
+ n, err := p.Writer.Write(buf)
+ if n == 0 || err != nil {
+ LOGGER.Print("Error writing to iostream, only wrote ", n, " bytes: ", err.String(), "\n")
+ }
+ return n, NewTTransportExceptionFromOsError(err)
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TIOStreamTransport) Flush() os.Error {
+ if p.Writer == nil {
+ return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream")
+ }
+ f, ok := p.Writer.(Flusher)
+ if ok {
+ err := f.Flush()
+ if err != nil {
+ return NewTTransportExceptionFromOsError(err)
+ }
+ }
+ return nil
+}
diff --git a/lib/go/thrift/tiostream_transport_test.go b/lib/go/thrift/tiostream_transport_test.go
new file mode 100644
index 0000000..a7425c7
--- /dev/null
+++ b/lib/go/thrift/tiostream_transport_test.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_test
+
+import (
+ . "thrift"
+ "testing"
+ "bytes"
+)
+
+func TestIOStreamTransport(t *testing.T) {
+ trans := NewTIOStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 1024)))
+ TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/tjson_protocol.go b/lib/go/thrift/tjson_protocol.go
new file mode 100644
index 0000000..45ab700
--- /dev/null
+++ b/lib/go/thrift/tjson_protocol.go
@@ -0,0 +1,537 @@
+/*
+ * 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.Push(int(_CONTEXT_IN_TOPLEVEL))
+ v.dumpContext.Push(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) TProtocolException {
+ 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() TProtocolException {
+ return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteStructBegin(name string) TProtocolException {
+ if e := p.OutputObjectBegin(); e != nil {
+ return e
+ }
+ return nil
+}
+
+func (p *TJSONProtocol) WriteStructEnd() TProtocolException {
+ return p.OutputObjectEnd()
+}
+
+func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+ 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() TProtocolException {
+ return p.OutputObjectEnd()
+}
+
+func (p *TJSONProtocol) WriteFieldStop() TProtocolException { return nil }
+
+func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+ 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() TProtocolException {
+ return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+ return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TJSONProtocol) WriteListEnd() TProtocolException {
+ return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+ return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TJSONProtocol) WriteSetEnd() TProtocolException {
+ return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteBool(b bool) TProtocolException {
+ return p.OutputBool(b)
+}
+
+func (p *TJSONProtocol) WriteByte(b byte) TProtocolException {
+ return p.WriteI32(int32(b))
+}
+
+func (p *TJSONProtocol) WriteI16(v int16) TProtocolException {
+ return p.WriteI32(int32(v))
+}
+
+func (p *TJSONProtocol) WriteI32(v int32) TProtocolException {
+ return p.OutputI64(int64(v))
+}
+
+func (p *TJSONProtocol) WriteI64(v int64) TProtocolException {
+ return p.OutputI64(int64(v))
+}
+
+func (p *TJSONProtocol) WriteDouble(v float64) TProtocolException {
+ return p.OutputF64(v)
+}
+
+func (p *TJSONProtocol) WriteString(v string) TProtocolException {
+ return p.OutputString(v)
+}
+
+func (p *TJSONProtocol) 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
+ }
+ p.writer.Write(JSON_QUOTE_BYTES)
+ writer := base64.NewEncoder(base64.StdEncoding, p.writer)
+ if _, e := writer.Write(v); e != nil {
+ return NewTProtocolExceptionFromOsError(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 TProtocolException) {
+ 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 {
+ return name, typeId, seqId, NewTProtocolException(INVALID_DATA, fmt.Sprint("Unknown Protocol version ", version, ", expected version ", THRIFT_JSON_PROTOCOL_VERSION, "\n"))
+ }
+ 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() TProtocolException {
+ err := p.ParseListEnd()
+ return err
+}
+
+func (p *TJSONProtocol) ReadStructBegin() (name string, err TProtocolException) {
+ _, err = p.ParseObjectStart()
+ return "", err
+}
+
+func (p *TJSONProtocol) ReadStructEnd() TProtocolException {
+ return p.ParseObjectEnd()
+}
+
+func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, TProtocolException) {
+ 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() TProtocolException {
+ return p.ParseObjectEnd()
+}
+
+func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e TProtocolException) {
+ 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() TProtocolException {
+ return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e TProtocolException) {
+ return p.ParseElemListBegin()
+}
+
+func (p *TJSONProtocol) ReadListEnd() TProtocolException {
+ return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e TProtocolException) {
+ return p.ParseElemListBegin()
+}
+
+func (p *TJSONProtocol) ReadSetEnd() TProtocolException {
+ return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) 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 *TJSONProtocol) ReadByte() (byte, TProtocolException) {
+ v, err := p.ReadI64()
+ return byte(v), err
+}
+
+func (p *TJSONProtocol) ReadI16() (int16, TProtocolException) {
+ v, err := p.ReadI64()
+ return int16(v), err
+}
+
+func (p *TJSONProtocol) ReadI32() (int32, TProtocolException) {
+ v, err := p.ReadI64()
+ return int32(v), err
+}
+
+func (p *TJSONProtocol) ReadI64() (int64, TProtocolException) {
+ v, _, err := p.ParseI64()
+ return v, err
+}
+
+func (p *TJSONProtocol) ReadDouble() (float64, TProtocolException) {
+ v, _, err := p.ParseF64()
+ return v, err
+}
+
+func (p *TJSONProtocol) 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 *TJSONProtocol) 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 *TJSONProtocol) Flush() (err TProtocolException) {
+ return NewTProtocolExceptionFromOsError(p.writer.Flush())
+}
+
+func (p *TJSONProtocol) Skip(fieldType TType) (err TProtocolException) {
+ return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TJSONProtocol) Transport() TTransport {
+ return p.trans
+}
+
+func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e TProtocolException) {
+ 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) TProtocolException {
+ 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 ENUM:
+ return "i32"
+ case UTF16:
+ return "str"
+ case GENERIC:
+ return "gen"
+ }
+ 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 "enm":
+ return TType(ENUM)
+ case "u16":
+ return TType(UTF16)
+ case "gen":
+ return TType(GENERIC)
+ }
+ return TType(STOP)
+}
diff --git a/lib/go/thrift/tjson_protocol_test.go b/lib/go/thrift/tjson_protocol_test.go
new file mode 100644
index 0000000..60f0f2e
--- /dev/null
+++ b/lib/go/thrift/tjson_protocol_test.go
@@ -0,0 +1,674 @@
+/*
+ * 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"
+ "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.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 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.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 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.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 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.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 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.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 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.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 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.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 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.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 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.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 TestReadJSONProtocolI64(t *testing.T) {
+ thetype := "int64"
+ for _, value := range INT64_VALUES {
+ trans := NewTMemoryBuffer()
+ p := NewTJSONProtocol(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 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.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 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.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 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.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 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.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 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.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()
+ 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.String())
+ }
+ 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.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 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.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 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.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 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.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)
+ }
+ expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin()
+ if err != nil {
+ t.Fatalf("Error while reading map begin: %s", err.String())
+ }
+ 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.String())
+ }
+ 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.String())
+ }
+ s := strconv.Ftoa64(dv, 'g', 10)
+ 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.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 TestReadWriteJSONStruct(t *testing.T) {
+ thetype := "struct"
+ trans := NewTMemoryBuffer()
+ p := NewTJSONProtocol(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())
+ }
+ p.Flush()
+ t.Log("Memory buffer contents: ", trans.String())
+ expectedString := "{\"1\":{\"i32\":25},\"2\":{\"i32\":102},\"3\":{\"i32\":1},\"4\":{\"str\":\"Add: 25 + 102\"}}"
+ if expectedString != trans.String() {
+ t.Fatalf("Expected JSON Struct with value %#v but have %#v", expectedString, 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 TestReadWriteJSONProtocol(t *testing.T) {
+ ReadWriteProtocolTest(t, NewTJSONProtocolFactory())
+}
diff --git a/lib/go/thrift/tlist.go b/lib/go/thrift/tlist.go
new file mode 100644
index 0000000..778fc3b
--- /dev/null
+++ b/lib/go/thrift/tlist.go
@@ -0,0 +1,222 @@
+/*
+ * 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 (
+ "container/vector"
+)
+
+/**
+ * Helper class that encapsulates list metadata.
+ *
+ */
+type TList interface {
+ TContainer
+ ElemType() TType
+ At(i int) interface{}
+ Set(i int, data interface{})
+ Push(data interface{})
+ Pop() interface{}
+ Swap(i, j int)
+ Insert(i int, data interface{})
+ Delete(i int)
+ Less(i, j int) bool
+ Iter() <-chan interface{}
+}
+
+type tList struct {
+ elemType TType
+ l *vector.Vector
+}
+
+func NewTList(t TType, s int) TList {
+ var v vector.Vector
+ return &tList{elemType: t, l: v.Resize(s, s)}
+}
+
+func NewTListDefault() TList {
+ var v vector.Vector
+ return &tList{elemType: TType(STOP), l: &v}
+}
+
+func (p *tList) ElemType() TType {
+ return p.elemType
+}
+
+func (p *tList) Len() int {
+ return p.l.Len()
+}
+
+func (p *tList) At(i int) interface{} {
+ return p.l.At(i)
+}
+
+func (p *tList) Set(i int, data interface{}) {
+ if p.elemType.IsEmptyType() {
+ p.elemType = TypeFromValue(data)
+ }
+ if data, ok := p.elemType.CoerceData(data); ok {
+ p.l.Set(i, data)
+ }
+}
+
+func (p *tList) Push(data interface{}) {
+ if p.elemType.IsEmptyType() {
+ p.elemType = TypeFromValue(data)
+ }
+ data, ok := p.elemType.CoerceData(data)
+ if ok {
+ p.l.Push(data)
+ }
+}
+
+func (p *tList) Pop() interface{} {
+ return p.l.Pop()
+}
+
+func (p *tList) Swap(i, j int) {
+ p.l.Swap(i, j)
+}
+
+func (p *tList) Insert(i int, data interface{}) {
+ p.l.Insert(i, data)
+}
+
+func (p *tList) Delete(i int) {
+ p.l.Delete(i)
+}
+
+func (p *tList) Contains(data interface{}) bool {
+ return p.indexOf(data) >= 0
+}
+
+func (p *tList) Less(i, j int) bool {
+ return p.l.Less(i, j)
+}
+
+func (p *tList) Iter() <-chan interface{} {
+ c := make(chan interface{})
+ go p.iterate(c)
+ return c
+}
+
+func (p *tList) iterate(c chan<- interface{}) {
+ for _, elem := range *p.l {
+ c <- elem
+ }
+ close(c)
+}
+
+func (p *tList) indexOf(data interface{}) int {
+ if data == nil {
+ size := p.l.Len()
+ for i := 0; i < size; i++ {
+ if p.l.At(i) == nil {
+ return i
+ }
+ }
+ return -1
+ }
+ data, ok := p.elemType.CoerceData(data)
+ if data == nil || !ok {
+ return -1
+ }
+ size := p.l.Len()
+ if p.elemType.IsBaseType() || p.elemType.IsEnum() {
+ for i := 0; i < size; i++ {
+ if data == p.l.At(i) {
+ return i
+ }
+ }
+ return -1
+ }
+ if cmp, ok := data.(EqualsOtherInterface); ok {
+ for i := 0; i < size; i++ {
+ if cmp.Equals(p.l.At(i)) {
+ return i
+ }
+ }
+ return -1
+ }
+ switch p.elemType {
+ case MAP:
+ if cmp, ok := data.(EqualsMap); ok {
+ for i := 0; i < size; i++ {
+ v := p.l.At(i)
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TMap)) {
+ return i
+ }
+ }
+ return -1
+ }
+ case SET:
+ if cmp, ok := data.(EqualsSet); ok {
+ for i := 0; i < size; i++ {
+ v := p.l.At(i)
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TSet)) {
+ return i
+ }
+ }
+ return -1
+ }
+ case LIST:
+ if cmp, ok := data.(EqualsList); ok {
+ for i := 0; i < size; i++ {
+ v := p.l.At(i)
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TList)) {
+ return i
+ }
+ }
+ return -1
+ }
+ case STRUCT:
+ if cmp, ok := data.(EqualsStruct); ok {
+ for i := 0; i < size; i++ {
+ v := p.l.At(i)
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TStruct)) {
+ return i
+ }
+ }
+ return -1
+ }
+ }
+ return -1
+}
+
+func (p *tList) Equals(other interface{}) bool {
+ c, cok := p.CompareTo(other)
+ return cok && c == 0
+}
+
+func (p *tList) CompareTo(other interface{}) (int, bool) {
+ return TType(LIST).Compare(p, other)
+}
diff --git a/lib/go/thrift/tmap.go b/lib/go/thrift/tmap.go
new file mode 100644
index 0000000..d042f05
--- /dev/null
+++ b/lib/go/thrift/tmap.go
@@ -0,0 +1,763 @@
+/*
+ * 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 (
+ "container/list"
+ "reflect"
+)
+
+/**
+ * Helper class that encapsulates map metadata.
+ *
+ */
+type TMap interface {
+ KeyType() TType
+ ValueType() TType
+ Len() int
+ Set(key, value interface{})
+ Get(key interface{}) (interface{}, bool)
+ Contains(key interface{}) bool
+ Iter() <-chan TMapElem
+ KeyIter() <-chan interface{}
+ ValueIter() <-chan interface{}
+ Keys() []interface{}
+ Values() []interface{}
+ Less(other interface{}) bool
+ Equals(other interface{}) bool
+ CompareTo(other interface{}) (int, bool)
+}
+
+type TMapElem interface {
+ Key() interface{}
+ Value() interface{}
+}
+
+type tMap struct {
+ keyType TType
+ valueType TType
+ size int
+ l *list.List
+ b map[bool]interface{}
+ i08 map[byte]interface{}
+ i16 map[int16]interface{}
+ i32 map[int32]interface{}
+ i64 map[int64]interface{}
+ f64 map[float64]interface{}
+ s map[string]interface{}
+}
+
+type tMapElem struct {
+ key interface{}
+ value interface{}
+}
+
+func (p *tMapElem) Key() interface{} {
+ return p.key
+}
+
+func (p *tMapElem) Value() interface{} {
+ return p.value
+}
+
+func NewTMapElem(k, v interface{}) TMapElem {
+ return &tMapElem{key: k, value: v}
+}
+
+func NewTMap(k, v TType, s int) TMap {
+ return &tMap{keyType: k, valueType: v, size: s, l: list.New()}
+}
+
+func NewTMapDefault() TMap {
+ return NewTMap(STOP, STOP, 0)
+}
+
+func (p *tMap) KeyType() TType {
+ return p.keyType
+}
+
+func (p *tMap) ValueType() TType {
+ return p.valueType
+}
+
+func (p *tMap) Len() int {
+ if p.l.Len() != 0 {
+ return p.l.Len()
+ }
+ switch p.KeyType() {
+ case STOP, VOID:
+ return 0
+ case BOOL:
+ return len(p.b)
+ case BYTE:
+ return len(p.i08)
+ case I16:
+ return len(p.i16)
+ case I32:
+ return len(p.i32)
+ case I64:
+ return len(p.i64)
+ case DOUBLE:
+ return len(p.f64)
+ case STRING, UTF8, UTF16:
+ return len(p.s)
+ default:
+ return p.size
+ }
+ return p.size
+}
+
+func (p *tMap) Get(key interface{}) (interface{}, bool) {
+ if p.KeyType().IsEmptyType() {
+ return nil, false
+ }
+ if key == nil {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ return e.Value(), true
+ }
+ }
+ return nil, false
+ }
+ useKey, ok := p.KeyType().CoerceData(key)
+ if !ok {
+ return nil, false
+ }
+ switch p.KeyType() {
+ case STOP, VOID:
+ // if here, then we don't have a key type yet and key is not nil
+ // so this is pretty much an empty map
+ return nil, false
+ case BOOL:
+ m := p.b
+ if m == nil {
+ return nil, false
+ }
+ if v, ok := m[useKey.(bool)]; ok {
+ return v, true
+ }
+ return nil, true
+ case BYTE:
+ m := p.i08
+ if v, ok := m[useKey.(byte)]; ok {
+ return v, true
+ }
+ return nil, false
+ case DOUBLE:
+ m := p.f64
+ if m == nil {
+ return nil, false
+ }
+ if v, ok := m[useKey.(float64)]; ok {
+ return v, true
+ }
+ return nil, false
+ case I16:
+ m := p.i16
+ if m == nil {
+ return nil, false
+ }
+ if v, ok := m[useKey.(int16)]; ok {
+ return v, true
+ }
+ return nil, false
+ case I32:
+ m := p.i32
+ if m == nil {
+ return nil, false
+ }
+ if v, ok := m[useKey.(int32)]; ok {
+ return v, true
+ }
+ return nil, false
+ case I64:
+ m := p.i64
+ if m == nil {
+ return nil, false
+ }
+ if v, ok := m[useKey.(int64)]; ok {
+ return v, true
+ }
+ return nil, false
+ case STRING, UTF8, UTF16:
+ // TODO(pomack) properly handle ENUM
+ m := p.s
+ if m == nil {
+ return nil, false
+ }
+ if v, ok := m[useKey.(string)]; ok {
+ return v, true
+ }
+ return nil, false
+ case STRUCT:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ structkey, ok := k.(TStruct)
+ if ok {
+ if structkey.Equals(useKey.(TStruct)) {
+ return e.Value(), true
+ }
+ continue
+ }
+ if reflect.DeepEqual(useKey, k) {
+ return e.Value(), true
+ }
+ }
+ return nil, false
+ case MAP:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ mapkey, ok := k.(TMap)
+ if ok {
+ if mapkey.Equals(useKey.(TMap)) {
+ return e.Value(), true
+ }
+ continue
+ }
+ if reflect.DeepEqual(useKey, k) {
+ return e.Value(), true
+ }
+ }
+ return nil, false
+ case SET:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ setkey, ok := k.(TSet)
+ if ok {
+ if setkey.Equals(useKey.(TSet)) {
+ return e.Value(), true
+ }
+ continue
+ }
+ if reflect.DeepEqual(useKey, k) {
+ return e.Value(), true
+ }
+ }
+ return nil, false
+ case LIST:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ listkey, ok := k.(TList)
+ if ok {
+ if listkey.Equals(useKey.(TList)) {
+ return e.Value(), true
+ }
+ continue
+ }
+ if reflect.DeepEqual(useKey, k) {
+ return e.Value(), true
+ }
+ }
+ return nil, false
+ default:
+ panic("Invalid Thrift element type")
+ }
+ return nil, false
+}
+
+
+func (p *tMap) Set(key, value interface{}) {
+ if p.KeyType() == STOP || p.KeyType() == VOID {
+ p.keyType = TypeFromValue(key)
+ }
+ coercedKey, ok := p.KeyType().CoerceData(key)
+ if !ok {
+ return
+ }
+ if p.ValueType() == STOP || p.ValueType() == VOID {
+ p.valueType = TypeFromValue(value)
+ }
+ coercedValue, ok := p.ValueType().CoerceData(value)
+ if !ok {
+ return
+ }
+ newElem := NewTMapElem(coercedKey, coercedValue)
+ if !p.KeyType().IsBaseType() {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ k := elem.Value.(TMapElem).Key()
+ if cmp, ok := p.KeyType().Compare(coercedKey, k); ok && cmp >= 0 {
+ if cmp == 0 {
+ p.l.InsertAfter(newElem, elem)
+ p.l.Remove(elem)
+ return
+ }
+ p.l.InsertBefore(newElem, elem)
+ return
+ }
+ }
+ p.l.PushBack(newElem)
+ return
+ }
+ if key == nil {
+ return
+ }
+ switch p.KeyType() {
+ case STOP, VOID:
+ // if here, then we don't have a key type yet and key is not nil
+ // so this is pretty much an empty map
+ return
+ case BOOL:
+ if p.b == nil {
+ p.b = make(map[bool]interface{})
+ }
+ b := coercedKey.(bool)
+ p.b[b] = value
+ case BYTE:
+ if p.i08 == nil {
+ p.i08 = make(map[byte]interface{})
+ }
+ b := coercedKey.(byte)
+ p.i08[b] = value
+ case DOUBLE:
+ if p.f64 == nil {
+ p.f64 = make(map[float64]interface{})
+ }
+ b := coercedKey.(float64)
+ p.f64[b] = value
+ case I16:
+ if p.i16 == nil {
+ p.i16 = make(map[int16]interface{})
+ }
+ b := coercedKey.(int16)
+ p.i16[b] = value
+ case I32:
+ if p.i32 == nil {
+ p.i32 = make(map[int32]interface{})
+ }
+ b := coercedKey.(int32)
+ p.i32[b] = value
+ case I64:
+ if p.i64 == nil {
+ p.i64 = make(map[int64]interface{})
+ }
+ b := coercedKey.(int64)
+ p.i64[b] = value
+ case STRING, UTF8, UTF16:
+ if p.s == nil {
+ p.s = make(map[string]interface{})
+ }
+ b := coercedKey.(string)
+ p.s[b] = value
+ case STRUCT, MAP, SET, LIST:
+ panic("Should never be here")
+ default:
+ panic("Should never be here")
+ }
+}
+
+func (p *tMap) Contains(key interface{}) bool {
+ coercedKey, ok := p.KeyType().CoerceData(key)
+ if !ok {
+ return false
+ }
+ if coercedKey == nil {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ k := elem.Value.(TMapElem).Key()
+ if k == nil {
+ return true
+ }
+ }
+ return false
+ }
+ if !ok {
+ return false
+ }
+ switch p.KeyType() {
+ case STOP:
+ // if here, then we don't have a key type yet and key is not nil
+ // so this is pretty much an empty map
+ return false
+ case VOID:
+ // if here, then we don't have a key type yet and key is not nil
+ // so this is pretty much an empty map
+ return false
+ case BOOL:
+ m := p.b
+ if m == nil {
+ return false
+ }
+ _, ok := m[coercedKey.(bool)]
+ return ok
+ case BYTE:
+ m := p.i08
+ _, ok := m[coercedKey.(byte)]
+ return ok
+ case DOUBLE:
+ m := p.f64
+ if m == nil {
+ return false
+ }
+ _, ok := m[coercedKey.(float64)]
+ return ok
+ case I16:
+ m := p.i16
+ if m == nil {
+ return false
+ }
+ _, ok := m[coercedKey.(int16)]
+ return ok
+ case I32:
+ m := p.i32
+ if m == nil {
+ return false
+ }
+ _, ok := m[coercedKey.(int32)]
+ return ok
+ case I64:
+ m := p.i64
+ if m == nil {
+ return false
+ }
+ _, ok := m[coercedKey.(int64)]
+ return ok
+ case STRING, UTF8, UTF16:
+ // TODO(pomack) properly handle ENUM
+ m := p.s
+ if m == nil {
+ return false
+ }
+ _, ok := m[coercedKey.(string)]
+ return ok
+ case STRUCT:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ structkey, ok := k.(TStruct)
+ if ok {
+ if structkey.Equals(coercedKey.(TStruct)) {
+ return true
+ }
+ continue
+ }
+ if reflect.DeepEqual(coercedKey, k) {
+ return true
+ }
+ }
+ return false
+ case MAP:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ mapkey, ok := k.(TMap)
+ if ok {
+ if mapkey.Equals(coercedKey.(TMap)) {
+ return true
+ }
+ continue
+ }
+ }
+ return false
+ case SET:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ setkey, ok := k.(TSet)
+ if ok {
+ if setkey.Equals(coercedKey.(TSet)) {
+ return true
+ }
+ continue
+ }
+ }
+ return false
+ case LIST:
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ e := elem.Value.(TMapElem)
+ k := e.Key()
+ if k == nil {
+ continue
+ }
+ listkey, ok := k.(TList)
+ if ok {
+ if listkey.Equals(coercedKey.(TList)) {
+ return true
+ }
+ continue
+ }
+ }
+ return false
+ default:
+ panic("Invalid Thrift element type")
+ }
+ return false
+}
+
+// Iterate over all elements; driver for range
+func (p *tMap) iterate(c chan<- TMapElem) {
+ switch p.KeyType() {
+ case STOP, VOID:
+ close(c)
+ case BOOL:
+ for k, v := range p.b {
+ c <- NewTMapElem(k, v)
+ }
+ close(c)
+ case BYTE:
+ for k, v := range p.i08 {
+ c <- NewTMapElem(k, v)
+ }
+ close(c)
+ case I16:
+ for k, v := range p.i16 {
+ c <- NewTMapElem(k, v)
+ }
+ close(c)
+ case I32:
+ for k, v := range p.i32 {
+ c <- NewTMapElem(k, v)
+ }
+ close(c)
+ case I64:
+ for k, v := range p.i64 {
+ c <- NewTMapElem(k, v)
+ }
+ close(c)
+ case DOUBLE:
+ for k, v := range p.f64 {
+ c <- NewTMapElem(k, v)
+ }
+ close(c)
+ case STRING, UTF8, UTF16:
+ for k, v := range p.s {
+ c <- NewTMapElem(k, v)
+ }
+ close(c)
+ case STRUCT:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem)
+ }
+ close(c)
+ case LIST:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem)
+ }
+ close(c)
+ case SET:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem)
+ }
+ close(c)
+ default:
+ panic("Invalid Thrift type")
+ }
+}
+
+// Channel iterator for range.
+func (p *tMap) Iter() <-chan TMapElem {
+ c := make(chan TMapElem)
+ go p.iterate(c)
+ return c
+}
+
+// Iterate over all keys; driver for range
+func (p *tMap) iterateKeys(c chan<- interface{}) {
+ switch p.KeyType() {
+ case STOP, VOID:
+ close(c)
+ case BOOL:
+ for k, _ := range p.b {
+ c <- k
+ }
+ close(c)
+ case BYTE:
+ for k, _ := range p.i08 {
+ c <- k
+ }
+ close(c)
+ case I16:
+ for k, _ := range p.i16 {
+ c <- k
+ }
+ close(c)
+ case I32:
+ for k, _ := range p.i32 {
+ c <- k
+ }
+ close(c)
+ case I64:
+ for k, _ := range p.i64 {
+ c <- k
+ }
+ close(c)
+ case DOUBLE:
+ for k, _ := range p.f64 {
+ c <- k
+ }
+ close(c)
+ case STRING, UTF8, UTF16:
+ for k, _ := range p.s {
+ c <- k
+ }
+ close(c)
+ case STRUCT:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem).Key()
+ }
+ close(c)
+ case LIST:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem).Key()
+ }
+ close(c)
+ case SET:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem).Key()
+ }
+ close(c)
+ default:
+ panic("Invalid Thrift type")
+ }
+}
+
+func (p *tMap) KeyIter() <-chan interface{} {
+ c := make(chan interface{})
+ go p.iterateKeys(c)
+ return c
+}
+
+// Iterate over all values; driver for range
+func (p *tMap) iterateValues(c chan<- interface{}) {
+ switch p.KeyType() {
+ case STOP, VOID:
+ close(c)
+ case BOOL:
+ for _, v := range p.b {
+ c <- v
+ }
+ close(c)
+ case BYTE:
+ for _, v := range p.i08 {
+ c <- v
+ }
+ close(c)
+ case I16:
+ for _, v := range p.i16 {
+ c <- v
+ }
+ close(c)
+ case I32:
+ for _, v := range p.i32 {
+ c <- v
+ }
+ close(c)
+ case I64:
+ for _, v := range p.i64 {
+ c <- v
+ }
+ close(c)
+ case DOUBLE:
+ for _, v := range p.f64 {
+ c <- v
+ }
+ close(c)
+ case STRING, UTF8, UTF16:
+ for _, v := range p.s {
+ c <- v
+ }
+ close(c)
+ case STRUCT:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem).Value()
+ }
+ close(c)
+ case LIST:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem).Value()
+ }
+ close(c)
+ case SET:
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ c <- v.Value.(TMapElem).Value()
+ }
+ close(c)
+ default:
+ panic("Invalid Thrift type")
+ }
+}
+
+func (p *tMap) ValueIter() <-chan interface{} {
+ c := make(chan interface{})
+ go p.iterateValues(c)
+ return c
+}
+
+
+func (p *tMap) Less(other interface{}) bool {
+ cmp, ok := p.CompareTo(other)
+ return ok && cmp > 0
+}
+
+func (p *tMap) Equals(other interface{}) bool {
+ c, cok := p.CompareTo(other)
+ return cok && c == 0
+}
+
+func (p *tMap) CompareTo(other interface{}) (int, bool) {
+ return TType(MAP).Compare(p, other)
+}
+
+func (p *tMap) Keys() []interface{} {
+ size := p.Len()
+ values := make([]interface{}, size, size)
+ i := 0
+ for k := range p.KeyIter() {
+ values[i] = k
+ i++
+ }
+ return values
+}
+
+func (p *tMap) Values() []interface{} {
+ size := p.Len()
+ values := make([]interface{}, size, size)
+ i := 0
+ for v := range p.ValueIter() {
+ values[i] = v
+ i++
+ }
+ return values
+}
diff --git a/lib/go/thrift/tmemory_buffer.go b/lib/go/thrift/tmemory_buffer.go
new file mode 100644
index 0000000..69b794e
--- /dev/null
+++ b/lib/go/thrift/tmemory_buffer.go
@@ -0,0 +1,127 @@
+/*
+ * 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"
+ "os"
+)
+
+/**
+ * Memory buffer-based implementation of the TTransport interface.
+ *
+ */
+type TMemoryBuffer struct {
+ buf *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{buf: &bytes.Buffer{}, size: 0}
+}
+
+func NewTMemoryBufferLen(size int) *TMemoryBuffer {
+ buf := make([]byte, 0, size)
+ return &TMemoryBuffer{buf: bytes.NewBuffer(buf), size: size}
+}
+
+func (p *TMemoryBuffer) IsOpen() bool {
+ return true
+}
+
+func (p *TMemoryBuffer) Open() os.Error {
+ return nil
+}
+
+func (p *TMemoryBuffer) Peek() bool {
+ return p.IsOpen()
+}
+
+func (p *TMemoryBuffer) Close() os.Error {
+ p.buf.Reset()
+ return nil
+}
+
+func (p *TMemoryBuffer) Read(buf []byte) (int, os.Error) {
+ return p.buf.Read(buf)
+}
+
+func (p *TMemoryBuffer) ReadAll(buf []byte) (int, os.Error) {
+ return ReadAllTransport(p, buf)
+}
+
+func (p *TMemoryBuffer) ReadByte() (byte, os.Error) {
+ return p.buf.ReadByte()
+}
+
+func (p *TMemoryBuffer) ReadFrom(r io.Reader) (int64, os.Error) {
+ return p.buf.ReadFrom(r)
+}
+
+func (p *TMemoryBuffer) Write(buf []byte) (int, os.Error) {
+ return p.buf.Write(buf)
+}
+
+func (p *TMemoryBuffer) WriteString(buf string) (int, os.Error) {
+ return p.buf.WriteString(buf)
+}
+
+func (p *TMemoryBuffer) WriteTo(w io.Writer) (int64, os.Error) {
+ return p.buf.WriteTo(w)
+}
+
+func (p *TMemoryBuffer) Flush() os.Error {
+ return nil
+}
+
+func (p *TMemoryBuffer) Reset() {
+ p.buf.Reset()
+}
+
+func (p *TMemoryBuffer) Bytes() []byte {
+ return p.buf.Bytes()
+}
+
+func (p *TMemoryBuffer) Len() int {
+ return p.buf.Len()
+}
+
+func (p *TMemoryBuffer) String() string {
+ return p.buf.String()
+}
diff --git a/lib/go/thrift/tmemory_buffer_test.go b/lib/go/thrift/tmemory_buffer_test.go
new file mode 100644
index 0000000..5d17864
--- /dev/null
+++ b/lib/go/thrift/tmemory_buffer_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_test
+
+import (
+ . "thrift"
+ "testing"
+)
+
+func TestMemoryBuffer(t *testing.T) {
+ trans := NewTMemoryBufferLen(1024)
+ TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/tmessage.go b/lib/go/thrift/tmessage.go
new file mode 100644
index 0000000..c768cb4
--- /dev/null
+++ b/lib/go/thrift/tmessage.go
@@ -0,0 +1,70 @@
+/*
+ * 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 TMessage interface {
+ Name() string
+ TypeId() TMessageType
+ SeqId() int
+ Equals(other TMessage) bool
+}
+type tMessage struct {
+ name string
+ typeId TMessageType
+ seqid int
+}
+
+func NewTMessageDefault() TMessage {
+ return NewTMessage("", STOP, 0)
+}
+
+func NewTMessage(n string, t TMessageType, s int) TMessage {
+ return &tMessage{name: n, typeId: t, seqid: s}
+}
+
+func (p *tMessage) Name() string {
+ return p.name
+}
+
+func (p *tMessage) TypeId() TMessageType {
+ return p.typeId
+}
+
+func (p *tMessage) SeqId() int {
+ return p.seqid
+}
+
+func (p *tMessage) String() string {
+ return "<TMessage name:'" + p.name + "' type: " + string(p.typeId) + " seqid:" + string(p.seqid) + ">"
+}
+
+func (p *tMessage) Equals(other TMessage) bool {
+ return p.name == other.Name() && p.typeId == other.TypeId() && p.seqid == other.SeqId()
+}
+
+var EMPTY_MESSAGE TMessage
+
+func init() {
+ EMPTY_MESSAGE = NewTMessageDefault()
+}
diff --git a/lib/go/thrift/tmessagetype.go b/lib/go/thrift/tmessagetype.go
new file mode 100644
index 0000000..b31c66c
--- /dev/null
+++ b/lib/go/thrift/tmessagetype.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
+
+/**
+ * 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
+)
diff --git a/lib/go/thrift/tnonblocking_server.go b/lib/go/thrift/tnonblocking_server.go
new file mode 100644
index 0000000..e234c5a
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_server.go
@@ -0,0 +1,178 @@
+/*
+ * 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"
+)
+
+/**
+ * A nonblocking TServer implementation. This allows for fairness amongst all
+ * connected clients in terms of invocations.
+ *
+ * This server is inherently single-threaded. If you want a limited thread pool
+ * coupled with invocation-fairness, see THsHaServer.
+ *
+ * To use this server, you MUST use a TFramedTransport at the outermost
+ * transport, otherwise this server will be unable to determine when a whole
+ * method call has been read off the wire. Clients must also use TFramedTransport.
+ */
+type TNonblockingServer struct {
+ /** Flag for stopping the server */
+ stopped bool
+
+ processorFactory TProcessorFactory
+ serverTransport TServerTransport
+ inputTransportFactory TTransportFactory
+ outputTransportFactory TTransportFactory
+ inputProtocolFactory TProtocolFactory
+ outputProtocolFactory TProtocolFactory
+}
+
+
+func NewTNonblockingServer2(processor TProcessor, serverTransport TServerTransport) *TNonblockingServer {
+ return NewTNonblockingServerFactory2(NewTProcessorFactory(processor), serverTransport)
+}
+
+func NewTNonblockingServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TNonblockingServer {
+ return NewTNonblockingServerFactory4(NewTProcessorFactory(processor),
+ serverTransport,
+ transportFactory,
+ protocolFactory,
+ )
+}
+
+func NewTNonblockingServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TNonblockingServer {
+ return NewTNonblockingServerFactory6(NewTProcessorFactory(processor),
+ serverTransport,
+ inputTransportFactory,
+ outputTransportFactory,
+ inputProtocolFactory,
+ outputProtocolFactory,
+ )
+}
+
+func NewTNonblockingServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TNonblockingServer {
+ return NewTNonblockingServerFactory6(processorFactory,
+ serverTransport,
+ NewTTransportFactory(),
+ NewTTransportFactory(),
+ NewTBinaryProtocolFactoryDefault(),
+ NewTBinaryProtocolFactoryDefault(),
+ )
+}
+
+func NewTNonblockingServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TNonblockingServer {
+ return NewTNonblockingServerFactory6(processorFactory,
+ serverTransport,
+ transportFactory,
+ transportFactory,
+ protocolFactory,
+ protocolFactory,
+ )
+}
+
+func NewTNonblockingServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TNonblockingServer {
+ return &TNonblockingServer{processorFactory: processorFactory,
+ serverTransport: serverTransport,
+ inputTransportFactory: inputTransportFactory,
+ outputTransportFactory: outputTransportFactory,
+ inputProtocolFactory: inputProtocolFactory,
+ outputProtocolFactory: outputProtocolFactory,
+ }
+}
+
+func (p *TNonblockingServer) ProcessorFactory() TProcessorFactory {
+ return p.processorFactory
+}
+
+func (p *TNonblockingServer) ServerTransport() TServerTransport {
+ return p.serverTransport
+}
+
+func (p *TNonblockingServer) InputTransportFactory() TTransportFactory {
+ return p.inputTransportFactory
+}
+
+func (p *TNonblockingServer) OutputTransportFactory() TTransportFactory {
+ return p.outputTransportFactory
+}
+
+func (p *TNonblockingServer) InputProtocolFactory() TProtocolFactory {
+ return p.inputProtocolFactory
+}
+
+func (p *TNonblockingServer) OutputProtocolFactory() TProtocolFactory {
+ return p.outputProtocolFactory
+}
+
+func (p *TNonblockingServer) 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 {
+ go p.processRequest(client)
+ }
+ }
+ return nil
+}
+
+func (p *TNonblockingServer) Stop() os.Error {
+ p.stopped = true
+ p.serverTransport.Interrupt()
+ return nil
+}
+
+func (p *TNonblockingServer) IsStopped() bool {
+ return p.stopped
+}
+
+func (p *TNonblockingServer) 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
+ }
+ }
+}
diff --git a/lib/go/thrift/tnonblocking_server_socket.go b/lib/go/thrift/tnonblocking_server_socket.go
new file mode 100644
index 0000000..3c9dbaa
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_server_socket.go
@@ -0,0 +1,169 @@
+/*
+ * 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"
+)
+
+/**
+ * Socket implementation of the TTransport interface. To be commented soon!
+ */
+type TNonblockingServerSocket struct {
+ listener net.Listener
+ addr net.Addr
+ /**
+ * Socket timeout
+ */
+ nsecTimeout int64
+}
+
+type TNonblockingServerSocketTransportFactory struct {
+ addr net.Addr
+}
+
+func (p *TNonblockingServerSocketTransportFactory) GetTransport(trans TTransport) TTransport {
+ if trans != nil {
+ t, ok := trans.(*TNonblockingServerSocket)
+ if ok && t.addr != nil {
+ s, _ := NewTNonblockingServerSocketAddr(t.addr)
+ s.SetTimeout(t.nsecTimeout)
+ return s
+ }
+ }
+ s, _ := NewTNonblockingServerSocketAddr(p.addr)
+ return s
+}
+
+func NewTNonblockingServerSocketTransportFactory(addr net.Addr) *TNonblockingServerSocketTransportFactory {
+ return &TNonblockingServerSocketTransportFactory{addr: addr}
+}
+
+
+func NewTNonblockingServerSocketListener(listener net.Listener) (*TNonblockingServerSocket, TTransportException) {
+ s := &TNonblockingServerSocket{listener: listener, addr: listener.Addr()}
+ return s, nil
+}
+
+func NewTNonblockingServerSocketAddr(addr net.Addr) (*TNonblockingServerSocket, TTransportException) {
+ s := &TNonblockingServerSocket{addr: addr}
+ return s, nil
+}
+
+func (p *TNonblockingServerSocket) Listen() os.Error {
+ return p.Open()
+}
+
+/**
+ * Sets the socket timeout
+ *
+ * @param timeout Nanoseconds timeout
+ */
+func (p *TNonblockingServerSocket) SetTimeout(nsecTimeout int64) os.Error {
+ p.nsecTimeout = nsecTimeout
+ return nil
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TNonblockingServerSocket) IsOpen() bool {
+ return p.listener != nil
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TNonblockingServerSocket) Open() os.Error {
+ if !p.IsOpen() {
+ l, err := net.Listen(p.addr.Network(), p.addr.String())
+ if err != nil {
+ return err
+ }
+ p.listener = l
+ return nil
+ }
+ return NewTTransportException(ALREADY_OPEN, "Server socket already open")
+}
+
+/**
+ * Perform a nonblocking read into buffer.
+ */
+func (p *TNonblockingServerSocket) Read(buf []byte) (int, os.Error) {
+ return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Read([]byte) is not implemented")
+}
+
+func (p *TNonblockingServerSocket) ReadAll(buf []byte) (int, os.Error) {
+ return ReadAllTransport(p, buf)
+}
+
+/**
+ * Perform a nonblocking write of the data in buffer;
+ */
+func (p *TNonblockingServerSocket) Write(buf []byte) (int, os.Error) {
+ return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Write([]byte) is not implemented")
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TNonblockingServerSocket) Flush() os.Error {
+ return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Flush() is not implemented")
+}
+
+func (p *TNonblockingServerSocket) Addr() net.Addr {
+ return p.addr
+}
+
+func (p *TNonblockingServerSocket) Accept() (TTransport, os.Error) {
+ if !p.IsOpen() {
+ return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
+ }
+ conn, err := p.listener.Accept()
+ if err != nil {
+ return nil, NewTTransportExceptionFromOsError(err)
+ }
+ conn.SetTimeout(p.nsecTimeout)
+ return NewTSocketConn(conn)
+}
+
+func (p *TNonblockingServerSocket) Peek() bool {
+ return p.IsOpen()
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TNonblockingServerSocket) Close() (err os.Error) {
+ if p.IsOpen() {
+ err := p.listener.Close()
+ if err != nil {
+ return NewTTransportExceptionFromOsError(err)
+ }
+ p.listener = nil
+ }
+ return nil
+}
+
+func (p *TNonblockingServerSocket) Interrupt() os.Error {
+ // probably not right
+ return p.Close()
+}
diff --git a/lib/go/thrift/tnonblocking_socket.go b/lib/go/thrift/tnonblocking_socket.go
new file mode 100644
index 0000000..a1c0310
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_socket.go
@@ -0,0 +1,192 @@
+/*
+ * 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"
+)
+
+/**
+ * Socket implementation of the TTransport interface. To be commented soon!
+ */
+type TNonblockingSocket struct {
+ conn net.Conn
+ addr net.Addr
+ /**
+ * Socket timeout
+ */
+ nsecTimeout int64
+}
+
+type TNonblockingSocketTransportFactory struct {
+ addr net.Addr
+}
+
+func (p *TNonblockingSocketTransportFactory) GetTransport(trans TTransport) TTransport {
+ if trans != nil {
+ t, ok := trans.(*TNonblockingSocket)
+ if ok {
+ s, _ := NewTNonblockingSocketAddr(t.addr)
+ s.SetTimeout(t.nsecTimeout)
+ return s
+ }
+ }
+ s, _ := NewTNonblockingSocketAddr(p.addr)
+ return s
+}
+
+func NewTNonblockingSocketTransportFactory(addr net.Addr) *TNonblockingSocketTransportFactory {
+ return &TNonblockingSocketTransportFactory{addr: addr}
+}
+
+func NewTNonblockingSocketConn(conn net.Conn) (*TNonblockingSocket, TTransportException) {
+ s := &TNonblockingSocket{conn: conn, addr: conn.RemoteAddr()}
+ return s, nil
+}
+
+func NewTNonblockingSocketAddr(addr net.Addr) (*TNonblockingSocket, TTransportException) {
+ s := &TNonblockingSocket{addr: addr}
+ return s, nil
+}
+
+/**
+ * Sets the socket timeout
+ *
+ * @param nsecTimeout Nanoseconds timeout
+ */
+func (p *TNonblockingSocket) 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
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TNonblockingSocket) IsOpen() bool {
+ return p.conn != nil
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TNonblockingSocket) 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
+}
+
+/**
+ * Perform a nonblocking read into buffer.
+ */
+func (p *TNonblockingSocket) 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 *TNonblockingSocket) ReadAll(buf []byte) (int, os.Error) {
+ return ReadAllTransport(p, buf)
+}
+
+/**
+ * Perform a nonblocking write of the data in buffer;
+ */
+func (p *TNonblockingSocket) Write(buf []byte) (int, os.Error) {
+ if !p.IsOpen() {
+ return 0, NewTTransportException(NOT_OPEN, "Connection not open")
+ }
+ return p.conn.Write(buf)
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TNonblockingSocket) Flush() os.Error {
+ if !p.IsOpen() {
+ return NewTTransportException(NOT_OPEN, "Connection not open")
+ }
+ f, ok := p.conn.(Flusher)
+ if ok {
+ err := f.Flush()
+ if err != nil {
+ return NewTTransportExceptionFromOsError(err)
+ }
+ }
+ return nil
+}
+
+func (p *TNonblockingSocket) Addr() net.Addr {
+ return p.addr
+}
+
+func (p *TNonblockingSocket) Peek() bool {
+ return p.IsOpen()
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TNonblockingSocket) Close() os.Error {
+ if p.conn != nil {
+ if err := p.conn.Close(); err != nil {
+ LOGGER.Print("Could not close socket.", err.String())
+ return err
+ }
+ p.conn = nil
+ }
+ return nil
+}
+
+func (p *TNonblockingSocket) Interrupt() os.Error {
+ if !p.IsOpen() {
+ return nil
+ }
+ // TODO(pomack) fix Interrupt as it is probably not right
+ return p.Close()
+}
diff --git a/lib/go/thrift/tnonblocking_transport.go b/lib/go/thrift/tnonblocking_transport.go
new file mode 100644
index 0000000..da9c26d
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_transport.go
@@ -0,0 +1,24 @@
+/*
+ * 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 TNonblockingTransport interface {
+ TTransport
+}
diff --git a/lib/go/thrift/tnonblocking_transport_test.go b/lib/go/thrift/tnonblocking_transport_test.go
new file mode 100644
index 0000000..7d019db
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_transport_test.go
@@ -0,0 +1,88 @@
+/*
+ * 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"
+ "testing"
+ "net"
+)
+
+func TestNonblockingTransportServerToClient(t *testing.T) {
+
+ addr, err := FindAvailableTCPServerPort(40000)
+ if err != nil {
+ t.Fatalf("Unable to find available tcp port addr: %s", err)
+ }
+ trans1, err := NewTNonblockingServerSocketAddr(addr)
+ if err != nil {
+ t.Fatalf("Unable to setup server socket listener: %s", err)
+ }
+ trans1.Open()
+ trans2, err := NewTNonblockingSocketAddr(addr)
+ if err != nil {
+ t.Fatalf("Unable to setup client socket: %s", err)
+ }
+ trans1.SetTimeout(10)
+ trans2.SetTimeout(10)
+ err = trans2.Open()
+ if err != nil {
+ t.Fatalf("Unable to connect client to server: %s", err)
+ }
+ s, err := trans1.Accept()
+ if err != nil {
+ t.Fatalf("Unable to accept client connection from server: %s", err)
+ }
+ //s.SetTimeout(10)
+ TransportTest(t, NewTFramedTransport(s), NewTFramedTransport(trans2))
+ trans1.Close()
+}
+
+func TestNonblockingTransportClientToServer(t *testing.T) {
+ addr, err := FindAvailableTCPServerPort(40000)
+ if err != nil {
+ t.Fatalf("Unable to find available tcp port addr: %s", err)
+ }
+ l, err := net.Listen(addr.Network(), addr.String())
+ if err != nil {
+ t.Fatalf("Unable to setup listener: %s", err)
+ }
+ trans1, err := NewTNonblockingServerSocketListener(l)
+ if err != nil {
+ t.Fatalf("Unable to setup server socket listener: %s", err)
+ }
+ trans2, err := NewTNonblockingSocketAddr(l.Addr())
+ if err != nil {
+ t.Fatalf("Unable to setup client socket: %s", err)
+ }
+ trans1.SetTimeout(10)
+ trans2.SetTimeout(10)
+ err = trans2.Open()
+ if err != nil {
+ t.Fatalf("Unable to connect client to server: %s", err)
+ }
+ s, err := trans1.Accept()
+ if err != nil {
+ t.Fatalf("Unable to accept client connection from server: %s", err)
+ }
+ //s.SetTimeout(10)
+ TransportTest(t, NewTFramedTransport(trans2), NewTFramedTransport(s))
+ trans1.Close()
+}
diff --git a/lib/go/thrift/tnumeric.go b/lib/go/thrift/tnumeric.go
new file mode 100644
index 0000000..b1f6508
--- /dev/null
+++ b/lib/go/thrift/tnumeric.go
@@ -0,0 +1,165 @@
+/*
+ * 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.Ftoa64(dValue, 'g', 10)
+ 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.Atoi64(sValue)
+ dValue, _ := strconv.Atof64(sValue)
+ 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.Atoi64(sValue)
+ dValue, _ := strconv.Atof64(sValue)
+ 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}
+}
diff --git a/lib/go/thrift/tprocessor.go b/lib/go/thrift/tprocessor.go
new file mode 100644
index 0000000..d2bb5e4
--- /dev/null
+++ b/lib/go/thrift/tprocessor.go
@@ -0,0 +1,33 @@
+/*
+ * 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)
+}
diff --git a/lib/go/thrift/tprocessor_factory.go b/lib/go/thrift/tprocessor_factory.go
new file mode 100644
index 0000000..72681ab
--- /dev/null
+++ b/lib/go/thrift/tprocessor_factory.go
@@ -0,0 +1,62 @@
+/*
+ * 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
+}
diff --git a/lib/go/thrift/tprotocol.go b/lib/go/thrift/tprotocol.go
new file mode 100644
index 0000000..dcb27a8
--- /dev/null
+++ b/lib/go/thrift/tprotocol.go
@@ -0,0 +1,201 @@
+/*
+ * 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 EmptyInterface interface{}
+
+type TProtocol interface {
+ WriteMessageBegin(name string, typeId TMessageType, seqid int32) TProtocolException
+ WriteMessageEnd() TProtocolException
+ WriteStructBegin(name string) TProtocolException
+ WriteStructEnd() TProtocolException
+ WriteFieldBegin(name string, typeId TType, id int16) TProtocolException
+ WriteFieldEnd() TProtocolException
+ WriteFieldStop() TProtocolException
+ WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException
+ WriteMapEnd() TProtocolException
+ WriteListBegin(elemType TType, size int) TProtocolException
+ WriteListEnd() TProtocolException
+ WriteSetBegin(elemType TType, size int) TProtocolException
+ WriteSetEnd() TProtocolException
+ WriteBool(value bool) TProtocolException
+ WriteByte(value byte) TProtocolException
+ WriteI16(value int16) TProtocolException
+ WriteI32(value int32) TProtocolException
+ WriteI64(value int64) TProtocolException
+ WriteDouble(value float64) TProtocolException
+ WriteString(value string) TProtocolException
+ WriteBinary(value []byte) TProtocolException
+
+ ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err TProtocolException)
+ ReadMessageEnd() TProtocolException
+ ReadStructBegin() (name string, err TProtocolException)
+ ReadStructEnd() TProtocolException
+ ReadFieldBegin() (name string, typeId TType, id int16, err TProtocolException)
+ ReadFieldEnd() TProtocolException
+ ReadMapBegin() (keyType TType, valueType TType, size int, err TProtocolException)
+ ReadMapEnd() TProtocolException
+ ReadListBegin() (elemType TType, size int, err TProtocolException)
+ ReadListEnd() TProtocolException
+ ReadSetBegin() (elemType TType, size int, err TProtocolException)
+ ReadSetEnd() TProtocolException
+ ReadBool() (value bool, err TProtocolException)
+ ReadByte() (value byte, err TProtocolException)
+ ReadI16() (value int16, err TProtocolException)
+ ReadI32() (value int32, err TProtocolException)
+ ReadI64() (value int64, err TProtocolException)
+ ReadDouble() (value float64, err TProtocolException)
+ ReadString() (value string, err TProtocolException)
+ ReadBinary() (value []byte, err TProtocolException)
+
+ Skip(fieldType TType) (err TProtocolException)
+ Flush() (err TProtocolException)
+
+ Transport() TTransport
+}
+
+/**
+ * The maximum recursive depth the skip() function will traverse before
+ * throwing a TException.
+ */
+var (
+ MaxSkipDepth = 1<<31 - 1
+)
+
+/**
+ * Specifies the maximum recursive depth that the skip function will
+ * traverse before throwing a TException. This is a global setting, so
+ * any call to skip in this JVM will enforce this value.
+ *
+ * @param depth the maximum recursive depth. A value of 2 would allow
+ * the skip function to skip a structure or collection with basic children,
+ * but it would not permit skipping a struct that had a field containing
+ * a child struct. A value of 1 would only allow skipping of simple
+ * types and empty structs/collections.
+ */
+func SetMaxSkipDepth(depth int) {
+ MaxSkipDepth = depth
+}
+
+/**
+ * Skips over the next data element from the provided input TProtocol object.
+ *
+ * @param prot the protocol object to read from
+ * @param type the next value will be intepreted as this TType value.
+ */
+func SkipDefaultDepth(prot TProtocol, typeId TType) (err TProtocolException) {
+ return Skip(prot, typeId, MaxSkipDepth)
+}
+
+/**
+ * Skips over the next data element from the provided input TProtocol object.
+ *
+ * @param prot the protocol object to read from
+ * @param type the next value will be intepreted as this TType value.
+ * @param maxDepth this function will only skip complex objects to this
+ * recursive depth, to prevent Java stack overflow.
+ */
+func Skip(self TProtocol, fieldType TType, maxDepth int) (err TProtocolException) {
+ 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:
+ {
+ _, err = self.ReadStructBegin()
+ if err != nil {
+ return
+ }
+ for {
+ _, typeId, _, _ := self.ReadFieldBegin()
+ if typeId == STOP {
+ break
+ }
+ Skip(self, typeId, maxDepth-1)
+ self.ReadFieldEnd()
+ }
+ return self.ReadStructEnd()
+ }
+ case MAP:
+ {
+ keyType, valueType, l, err := self.ReadMapBegin()
+ if err != nil {
+ return err
+ }
+ size := int(l)
+ for i := 0; i < size; i++ {
+ Skip(self, keyType, maxDepth-1)
+ self.Skip(valueType)
+ }
+ return self.ReadMapEnd()
+ }
+ case SET:
+ {
+ elemType, l, err := self.ReadSetBegin()
+ if err != nil {
+ return err
+ }
+ size := int(l)
+ for i := 0; i < size; i++ {
+ Skip(self, elemType, maxDepth-1)
+ }
+ return self.ReadSetEnd()
+ }
+ case LIST:
+ {
+ elemType, l, err := self.ReadListBegin()
+ if err != nil {
+ return err
+ }
+ size := int(l)
+ for i := 0; i < size; i++ {
+ Skip(self, elemType, maxDepth-1)
+ }
+ return self.ReadListEnd()
+ }
+ }
+ return nil
+}
diff --git a/lib/go/thrift/tprotocol_exception.go b/lib/go/thrift/tprotocol_exception.go
new file mode 100644
index 0000000..2dac97e
--- /dev/null
+++ b/lib/go/thrift/tprotocol_exception.go
@@ -0,0 +1,130 @@
+/*
+ * 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"
+ "os"
+)
+
+/**
+ * Protocol exceptions.
+ *
+ */
+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 NewTProtocolExceptionDefault() TProtocolException {
+ return NewTProtocolExceptionDefaultType(UNKNOWN_PROTOCOL_EXCEPTION)
+}
+
+func NewTProtocolExceptionDefaultType(t int) TProtocolException {
+ return NewTProtocolException(t, "")
+}
+
+func NewTProtocolExceptionDefaultString(m string) TProtocolException {
+ return NewTProtocolException(UNKNOWN_PROTOCOL_EXCEPTION, m)
+}
+
+func NewTProtocolException(t int, m string) TProtocolException {
+ return &tProtocolException{typeId: t, message: m}
+}
+
+func NewTProtocolExceptionReadField(fieldId int, fieldName string, structName string, e TProtocolException) TProtocolException {
+ t := e.TypeId()
+ if t == UNKNOWN_PROTOCOL_EXCEPTION {
+ t = INVALID_DATA
+ }
+ return NewTProtocolException(t, "Unable to read field "+string(fieldId)+" ("+fieldName+") in "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionWriteField(fieldId int, fieldName string, structName string, e TProtocolException) TProtocolException {
+ t := e.TypeId()
+ if t == UNKNOWN_PROTOCOL_EXCEPTION {
+ t = INVALID_DATA
+ }
+ return NewTProtocolException(t, "Unable to write field "+string(fieldId)+" ("+fieldName+") in "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionReadStruct(structName string, e TProtocolException) TProtocolException {
+ t := e.TypeId()
+ if t == UNKNOWN_PROTOCOL_EXCEPTION {
+ t = INVALID_DATA
+ }
+ return NewTProtocolException(t, "Unable to read struct "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionWriteStruct(structName string, e TProtocolException) TProtocolException {
+ t := e.TypeId()
+ if t == UNKNOWN_PROTOCOL_EXCEPTION {
+ t = INVALID_DATA
+ }
+ return NewTProtocolException(t, "Unable to write struct "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionFromOsError(e os.Error) TProtocolException {
+ if e == nil {
+ return nil
+ }
+ if t, ok := e.(TProtocolException); ok {
+ return t
+ }
+ if te, ok := e.(TTransportException); ok {
+ return NewTProtocolExceptionFromTransportException(te)
+ }
+ if _, ok := e.(base64.CorruptInputError); ok {
+ return NewTProtocolException(INVALID_DATA, e.String())
+ }
+ return NewTProtocolExceptionDefaultString(e.String())
+}
+
+func NewTProtocolExceptionFromTransportException(e TTransportException) TProtocolException {
+ if e == nil {
+ return nil
+ }
+ if t, ok := e.(TProtocolException); ok {
+ return t
+ }
+ return NewTProtocolExceptionDefaultString(e.String())
+}
diff --git a/lib/go/thrift/tprotocol_factory.go b/lib/go/thrift/tprotocol_factory.go
new file mode 100644
index 0000000..2eed2c2
--- /dev/null
+++ b/lib/go/thrift/tprotocol_factory.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
+
+/**
+ * Factory interface for constructing protocol instances.
+ *
+ */
+type TProtocolFactory interface {
+ GetProtocol(trans TTransport) TProtocol
+}
diff --git a/lib/go/thrift/tprotocol_test.go b/lib/go/thrift/tprotocol_test.go
new file mode 100644
index 0000000..22d6ad6
--- /dev/null
+++ b/lib/go/thrift/tprotocol_test.go
@@ -0,0 +1,1817 @@
+/*
+ * 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"
+ "testing"
+ "http"
+ "math"
+ "net"
+ "io"
+ "os"
+ "bytes"
+ "fmt"
+)
+
+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) {
+ w.WriteHeader(http.StatusOK)
+ io.Copy(w, req.Body)
+}
+
+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)
+ }
+ l, err := net.Listen(addr.Network(), addr.String())
+ if err != nil {
+ t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err)
+ }
+ 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)
+ transports := []TTransportFactory{
+ NewTMemoryBufferTransportFactory(1024),
+ NewTIOStreamTransportFactory(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)
+ ReadWriteWork(t, p, trans)
+ trans.Close()
+ }
+ for _, tf := range transports {
+ trans := tf.GetTransport(nil)
+ p := protocolFactory.GetProtocol(trans)
+ ReadWriteCalculate(t, p, trans)
+ trans.Close()
+ }
+
+ // this test doesn't work in all cases due to EOF issues between
+ // buffer read and buffer write when using the same bufio for both
+ //for _, tf := range transports {
+ // trans := tf.GetTransport(nil)
+ // p := GetProtocol(trans);
+ // ReadWriteI64(t, p, trans);
+ // ReadWriteDouble(t, p, trans);
+ // ReadWriteBinary(t, p, trans);
+ // ReadWriteByte(t, p, trans);
+ // trans.Close()
+ //}
+
+ l.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.String())
+ }
+ 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)
+ }
+ }
+ }
+}
+
+
+func ReadWriteWork(t *testing.T, p TProtocol, trans TTransport) {
+ thetype := "struct"
+ orig := NewWork()
+ orig.Num1 = 25
+ orig.Num2 = 102
+ orig.Op = ADD
+ orig.Comment = "Add: 25 + 102"
+ return
+ if e := orig.Write(p); e != nil {
+ t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String())
+ }
+ read := NewWork()
+ e := read.Read(p)
+ 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 ReadWriteCalculate(t *testing.T, p TProtocol, trans TTransport) {
+ messageName := "calculate"
+ logid := int32(12)
+ seqId := int32(35)
+ w := NewWork()
+ w.Num1 = 25
+ w.Num2 = 102
+ w.Op = ADD
+ w.Comment = "Add: 25 + 102"
+
+ args31 := NewCalculateArgs()
+ args31.Logid = logid
+ args31.W = w
+ p.WriteMessageBegin(messageName, CALL, seqId)
+ if err := args31.Write(p); err != nil {
+ t.Fatalf("%s: %T %T Unable to write message: %s", messageName, p, trans, err.String())
+ }
+ p.WriteMessageEnd()
+ p.Transport().Flush()
+
+ name, ttype, seqid, err1 := p.ReadMessageBegin()
+ if err1 != nil {
+ t.Fatalf("%s: %T %T Unable to read message begin: %s", messageName, p, trans, err1.String())
+ }
+ if name != messageName {
+ t.Errorf("%s: %T %T Expected message named \"%s\", but was: \"%s\"", messageName, p, trans, messageName, name)
+ }
+ if ttype != CALL {
+ t.Errorf("%s: %T %T Expected message type \"%s\", but was: \"%s\"", messageName, p, trans, CALL, ttype)
+ }
+ if seqid != seqId {
+ t.Errorf("%s: %T %T Expected message type \"%s\", but was: \"%s\"", messageName, p, trans, seqId, seqid)
+ }
+ calcArgs := NewCalculateArgs()
+ err2 := calcArgs.Read(p)
+ if !args31.Equals(calcArgs) {
+ //cmp1, _ := args31.W.CompareTo(calcArgs.W)
+ cmp2, ok := args31.CompareTo(calcArgs)
+ t.Errorf("%s: %T %T Calculate args not as expected, %T vs %T, cmp: %#v, ok: %#v, equals: %#v", messageName, p, trans, args31, calcArgs, cmp2, ok, args31.Equals(calcArgs))
+ }
+ if err2 != nil {
+ t.Fatalf("%s: %T %T Unable to read message end: %s", messageName, p, trans, err2.String())
+ }
+ err3 := p.ReadMessageEnd()
+ if err3 != nil {
+ t.Fatalf("%s: %T %T Unable to read message end: %s", messageName, p, trans, err3.String())
+ }
+}
+
+
+/**
+ *You can define enums, which are just 32 bit integers. Values are optional
+ *and start at 1 if not supplied, C style again.
+ */
+type Operation int
+
+const (
+ ADD Operation = 1
+ SUBTRACT Operation = 2
+ MULTIPLY Operation = 3
+ DIVIDE Operation = 4
+)
+
+func (p Operation) String() string {
+ switch p {
+ case ADD:
+ return "ADD"
+ case SUBTRACT:
+ return "SUBTRACT"
+ case MULTIPLY:
+ return "MULTIPLY"
+ case DIVIDE:
+ return "DIVIDE"
+ }
+ return ""
+}
+
+func FromOperationString(s string) Operation {
+ switch s {
+ case "ADD":
+ return ADD
+ case "SUBTRACT":
+ return SUBTRACT
+ case "MULTIPLY":
+ return MULTIPLY
+ case "DIVIDE":
+ return DIVIDE
+ }
+ return Operation(-10000)
+}
+
+func (p Operation) Value() int {
+ return int(p)
+}
+
+func (p Operation) IsEnum() bool {
+ return true
+}
+
+/**
+ *Thrift lets you do typedefs to get pretty names for your types. Standard
+ *C style here.
+ */
+type MyInteger int32
+
+const INT32CONSTANT = 9853
+
+var MAPCONSTANT TMap
+/**
+ * Structs are the basic complex data structures. They are comprised of fields
+ * which each have an integer identifier, a type, a symbolic name, and an
+ * optional default value.
+ *
+ * Fields can be declared "optional", which ensures they will not be included
+ * in the serialized output if they aren't set. Note that this requires some
+ * manual management in some languages.
+ *
+ * Attributes:
+ * - Num1
+ * - Num2
+ * - Op
+ * - Comment
+ */
+type Work struct {
+ TStruct
+ _ interface{} "num1" // nil # 0
+ Num1 int32 "num1" // 1
+ Num2 int32 "num2" // 2
+ Op Operation "op" // 3
+ Comment string "comment" // 4
+}
+
+func NewWork() *Work {
+ output := &Work{
+ TStruct: NewTStruct("Work", []TField{
+ NewTField("num1", I32, 1),
+ NewTField("num2", I32, 2),
+ NewTField("op", I32, 3),
+ NewTField("comment", STRING, 4),
+ }),
+ }
+ {
+ output.Num1 = 0
+ }
+ return output
+}
+
+func (p *Work) Read(iprot TProtocol) (err TProtocolException) {
+ _, err = iprot.ReadStructBegin()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ for {
+ fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+ if fieldId < 0 {
+ fieldId = int16(p.FieldIdFromFieldName(fieldName))
+ } else if fieldName == "" {
+ fieldName = p.FieldNameFromFieldId(int(fieldId))
+ }
+ if fieldTypeId == GENERIC {
+ fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+ }
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ if fieldTypeId == STOP {
+ break
+ }
+ if fieldId == 1 || fieldName == "num1" {
+ if fieldTypeId == I32 {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else if fieldId == 2 || fieldName == "num2" {
+ if fieldTypeId == I32 {
+ err = p.ReadField2(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField2(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else if fieldId == 3 || fieldName == "op" {
+ if fieldTypeId == I32 {
+ err = p.ReadField3(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField3(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else if fieldId == 4 || fieldName == "comment" {
+ if fieldTypeId == STRING {
+ err = p.ReadField4(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField4(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *Work) ReadField1(iprot TProtocol) (err TProtocolException) {
+ v4, err5 := iprot.ReadI32()
+ if err5 != nil {
+ return NewTProtocolExceptionReadField(1, "num1", p.ThriftName(), err5)
+ }
+ p.Num1 = v4
+ return err
+}
+
+func (p *Work) ReadFieldNum1(iprot TProtocol) TProtocolException {
+ return p.ReadField1(iprot)
+}
+
+func (p *Work) ReadField2(iprot TProtocol) (err TProtocolException) {
+ v6, err7 := iprot.ReadI32()
+ if err7 != nil {
+ return NewTProtocolExceptionReadField(2, "num2", p.ThriftName(), err7)
+ }
+ p.Num2 = v6
+ return err
+}
+
+func (p *Work) ReadFieldNum2(iprot TProtocol) TProtocolException {
+ return p.ReadField2(iprot)
+}
+
+func (p *Work) ReadField3(iprot TProtocol) (err TProtocolException) {
+ v8, err9 := iprot.ReadI32()
+ if err9 != nil {
+ return NewTProtocolExceptionReadField(3, "op", p.ThriftName(), err9)
+ }
+ p.Op = Operation(v8)
+ return err
+}
+
+func (p *Work) ReadFieldOp(iprot TProtocol) TProtocolException {
+ return p.ReadField3(iprot)
+}
+
+func (p *Work) ReadField4(iprot TProtocol) (err TProtocolException) {
+ v10, err11 := iprot.ReadString()
+ if err11 != nil {
+ return NewTProtocolExceptionReadField(4, "comment", p.ThriftName(), err11)
+ }
+ p.Comment = v10
+ return err
+}
+
+func (p *Work) ReadFieldComment(iprot TProtocol) TProtocolException {
+ return p.ReadField4(iprot)
+}
+
+func (p *Work) Write(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteStructBegin("Work")
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ err = p.WriteField1(oprot)
+ if err != nil {
+ return err
+ }
+ err = p.WriteField2(oprot)
+ if err != nil {
+ return err
+ }
+ err = p.WriteField3(oprot)
+ if err != nil {
+ return err
+ }
+ err = p.WriteField4(oprot)
+ if err != nil {
+ return err
+ }
+ err = oprot.WriteFieldStop()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+ }
+ err = oprot.WriteStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *Work) WriteField1(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("num1", I32, 1)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err)
+ }
+ err = oprot.WriteI32(int32(p.Num1))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *Work) WriteFieldNum1(oprot TProtocol) TProtocolException {
+ return p.WriteField1(oprot)
+}
+
+func (p *Work) WriteField2(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("num2", I32, 2)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err)
+ }
+ err = oprot.WriteI32(int32(p.Num2))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *Work) WriteFieldNum2(oprot TProtocol) TProtocolException {
+ return p.WriteField2(oprot)
+}
+
+func (p *Work) WriteField3(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("op", I32, 3)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err)
+ }
+ err = oprot.WriteI32(int32(p.Op))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *Work) WriteFieldOp(oprot TProtocol) TProtocolException {
+ return p.WriteField3(oprot)
+}
+
+func (p *Work) WriteField4(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("comment", STRING, 4)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err)
+ }
+ err = oprot.WriteString(string(p.Comment))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *Work) WriteFieldComment(oprot TProtocol) TProtocolException {
+ return p.WriteField4(oprot)
+}
+
+func (p *Work) TStructName() string {
+ return "Work"
+}
+
+func (p *Work) ThriftName() string {
+ return "Work"
+}
+
+func (p *Work) String() string {
+ if p == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("Work(%+v)", *p)
+}
+
+func (p *Work) CompareTo(other interface{}) (int, bool) {
+ if other == nil {
+ return 1, true
+ }
+ data, ok := other.(*Work)
+ if !ok {
+ return 0, false
+ }
+ if p.Num1 != data.Num1 {
+ if p.Num1 < data.Num1 {
+ return -1, true
+ }
+ return 1, true
+ }
+ if p.Num2 != data.Num2 {
+ if p.Num2 < data.Num2 {
+ return -1, true
+ }
+ return 1, true
+ }
+ if p.Op != data.Op {
+ if p.Op < data.Op {
+ return -1, true
+ }
+ return 1, true
+ }
+ if p.Comment != data.Comment {
+ if p.Comment < data.Comment {
+ return -1, true
+ }
+ return 1, true
+ }
+ return 0, true
+}
+
+func (p *Work) AttributeByFieldId(id int) interface{} {
+ switch id {
+ default:
+ return nil
+ case 1:
+ return p.Num1
+ case 2:
+ return p.Num2
+ case 3:
+ return p.Op
+ case 4:
+ return p.Comment
+ }
+ return nil
+}
+
+func (p *Work) TStructFields() TFieldContainer {
+ return NewTFieldContainer([]TField{
+ NewTField("num1", I32, 1),
+ NewTField("num2", I32, 2),
+ NewTField("op", I32, 3),
+ NewTField("comment", STRING, 4),
+ })
+}
+
+
+type ICalculator interface {
+ /**
+ * Parameters:
+ * - Key
+ */
+ Calculate(logid int32, w *Work) (retval30 int32, ouch *InvalidOperation, err os.Error)
+}
+
+type CalculatorClient struct {
+ Transport TTransport
+ ProtocolFactory TProtocolFactory
+ InputProtocol TProtocol
+ OutputProtocol TProtocol
+ SeqId int32
+}
+
+func NewCalculatorClientFactory(t TTransport, f TProtocolFactory) *CalculatorClient {
+ return &CalculatorClient{Transport: t,
+ ProtocolFactory: f,
+ InputProtocol: f.GetProtocol(t),
+ OutputProtocol: f.GetProtocol(t),
+ SeqId: 0,
+ }
+}
+
+func NewCalculatorClientProtocol(t TTransport, iprot TProtocol, oprot TProtocol) *CalculatorClient {
+ return &CalculatorClient{Transport: t,
+ ProtocolFactory: nil,
+ InputProtocol: iprot,
+ OutputProtocol: oprot,
+ SeqId: 0,
+ }
+}
+
+
+/**
+ * Parameters:
+ * - Logid
+ * - W
+ */
+func (p *CalculatorClient) Calculate(logid int32, w *Work) (retval30 int32, ouch *InvalidOperation, err os.Error) {
+ err = p.SendCalculate(logid, w)
+ if err != nil {
+ return
+ }
+ return p.RecvCalculate()
+}
+
+func (p *CalculatorClient) SendCalculate(logid int32, w *Work) (err os.Error) {
+ oprot := p.OutputProtocol
+ if oprot != nil {
+ oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+ p.OutputProtocol = oprot
+ }
+ oprot.WriteMessageBegin("calculate", CALL, p.SeqId)
+ args31 := NewCalculateArgs()
+ args31.Logid = logid
+ args31.W = w
+ err = args31.Write(oprot)
+ oprot.WriteMessageEnd()
+ oprot.Transport().Flush()
+ return
+}
+
+
+func (p *CalculatorClient) RecvCalculate() (value int32, ouch *InvalidOperation, err os.Error) {
+ iprot := p.InputProtocol
+ if iprot == nil {
+ iprot = p.ProtocolFactory.GetProtocol(p.Transport)
+ p.InputProtocol = iprot
+ }
+ _, mTypeId, _, err := iprot.ReadMessageBegin()
+ if err != nil {
+ return
+ }
+ if mTypeId == EXCEPTION {
+ error33 := NewTApplicationExceptionDefault()
+ error34, err := error33.Read(iprot)
+ if err != nil {
+ return
+ }
+ if err = iprot.ReadMessageEnd(); err != nil {
+ return
+ }
+ err = error34
+ return
+ }
+ result32 := NewCalculateResult()
+ err = result32.Read(iprot)
+ iprot.ReadMessageEnd()
+ value = result32.Success
+ if result32.Ouch != nil {
+ ouch = result32.Ouch
+ }
+ return
+}
+
+
+/**
+ * Attributes:
+ * - Logid
+ * - W
+ */
+type CalculateArgs struct {
+ TStruct
+ _ interface{} "logid" // nil # 0
+ Logid int32 "logid" // 1
+ W *Work "w" // 2
+}
+
+func NewCalculateArgs() *CalculateArgs {
+ output := &CalculateArgs{
+ TStruct: NewTStruct("calculate_args", []TField{
+ NewTField("logid", I32, 1),
+ NewTField("w", STRUCT, 2),
+ }),
+ }
+ {
+ }
+ return output
+}
+
+func (p *CalculateArgs) Read(iprot TProtocol) (err TProtocolException) {
+ _, err = iprot.ReadStructBegin()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ for {
+ fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+ if fieldId < 0 {
+ fieldId = int16(p.FieldIdFromFieldName(fieldName))
+ } else if fieldName == "" {
+ fieldName = p.FieldNameFromFieldId(int(fieldId))
+ }
+ if fieldTypeId == GENERIC {
+ fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+ }
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ if fieldTypeId == STOP {
+ break
+ }
+ if fieldId == 1 || fieldName == "logid" {
+ if fieldTypeId == I32 {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else if fieldId == 2 || fieldName == "w" {
+ if fieldTypeId == STRUCT {
+ err = p.ReadField2(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField2(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *CalculateArgs) ReadField1(iprot TProtocol) (err TProtocolException) {
+ v47, err48 := iprot.ReadI32()
+ if err48 != nil {
+ return NewTProtocolExceptionReadField(1, "logid", p.ThriftName(), err48)
+ }
+ p.Logid = v47
+ return err
+}
+
+func (p *CalculateArgs) ReadFieldLogid(iprot TProtocol) TProtocolException {
+ return p.ReadField1(iprot)
+}
+
+func (p *CalculateArgs) ReadField2(iprot TProtocol) (err TProtocolException) {
+ p.W = NewWork()
+ err51 := p.W.Read(iprot)
+ if err51 != nil {
+ return NewTProtocolExceptionReadStruct("p.WWork", err51)
+ }
+ return err
+}
+
+func (p *CalculateArgs) ReadFieldW(iprot TProtocol) TProtocolException {
+ return p.ReadField2(iprot)
+}
+
+func (p *CalculateArgs) Write(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteStructBegin("calculate_args")
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ err = p.WriteField1(oprot)
+ if err != nil {
+ return err
+ }
+ err = p.WriteField2(oprot)
+ if err != nil {
+ return err
+ }
+ err = oprot.WriteFieldStop()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+ }
+ err = oprot.WriteStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *CalculateArgs) WriteField1(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("logid", I32, 1)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err)
+ }
+ err = oprot.WriteI32(int32(p.Logid))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *CalculateArgs) WriteFieldLogid(oprot TProtocol) TProtocolException {
+ return p.WriteField1(oprot)
+}
+
+func (p *CalculateArgs) WriteField2(oprot TProtocol) (err TProtocolException) {
+ if p.W != nil {
+ err = oprot.WriteFieldBegin("w", STRUCT, 2)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "w", p.ThriftName(), err)
+ }
+ err = p.W.Write(oprot)
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct("Work", err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "w", p.ThriftName(), err)
+ }
+ }
+ return err
+}
+
+func (p *CalculateArgs) WriteFieldW(oprot TProtocol) TProtocolException {
+ return p.WriteField2(oprot)
+}
+
+func (p *CalculateArgs) TStructName() string {
+ return "CalculateArgs"
+}
+
+func (p *CalculateArgs) ThriftName() string {
+ return "calculate_args"
+}
+
+func (p *CalculateArgs) String() string {
+ if p == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("CalculateArgs(%+v)", *p)
+}
+
+func (p *CalculateArgs) CompareTo(other interface{}) (int, bool) {
+ if other == nil {
+ return 1, true
+ }
+ data, ok := other.(*CalculateArgs)
+ if !ok {
+ return 0, false
+ }
+ if p.Logid != data.Logid {
+ if p.Logid < data.Logid {
+ return -1, true
+ }
+ return 1, true
+ }
+ if cmp, ok := p.W.CompareTo(data.W); !ok || cmp != 0 {
+ return cmp, ok
+ }
+ return 0, true
+}
+
+func (p *CalculateArgs) AttributeByFieldId(id int) interface{} {
+ switch id {
+ default:
+ return nil
+ case 1:
+ return p.Logid
+ case 2:
+ return p.W
+ }
+ return nil
+}
+
+func (p *CalculateArgs) TStructFields() TFieldContainer {
+ return NewTFieldContainer([]TField{
+ NewTField("logid", I32, 1),
+ NewTField("w", STRUCT, 2),
+ })
+}
+
+/**
+ * Attributes:
+ * - Success
+ * - Ouch
+ */
+type CalculateResult struct {
+ TStruct
+ Success int32 "success" // 0
+ Ouch *InvalidOperation "ouch" // 1
+}
+
+func NewCalculateResult() *CalculateResult {
+ output := &CalculateResult{
+ TStruct: NewTStruct("calculate_result", []TField{
+ NewTField("success", I32, 0),
+ NewTField("ouch", STRUCT, 1),
+ }),
+ }
+ {
+ }
+ return output
+}
+
+func (p *CalculateResult) Read(iprot TProtocol) (err TProtocolException) {
+ _, err = iprot.ReadStructBegin()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ for {
+ fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+ if fieldId < 0 {
+ fieldId = int16(p.FieldIdFromFieldName(fieldName))
+ } else if fieldName == "" {
+ fieldName = p.FieldNameFromFieldId(int(fieldId))
+ }
+ if fieldTypeId == GENERIC {
+ fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+ }
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ if fieldTypeId == STOP {
+ break
+ }
+ if fieldId == 0 || fieldName == "success" {
+ if fieldTypeId == I32 {
+ err = p.ReadField0(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField0(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else if fieldId == 1 || fieldName == "ouch" {
+ if fieldTypeId == STRUCT {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *CalculateResult) ReadField0(iprot TProtocol) (err TProtocolException) {
+ v52, err53 := iprot.ReadI32()
+ if err53 != nil {
+ return NewTProtocolExceptionReadField(0, "success", p.ThriftName(), err53)
+ }
+ p.Success = v52
+ return err
+}
+
+func (p *CalculateResult) ReadFieldSuccess(iprot TProtocol) TProtocolException {
+ return p.ReadField0(iprot)
+}
+
+func (p *CalculateResult) ReadField1(iprot TProtocol) (err TProtocolException) {
+ p.Ouch = NewInvalidOperation()
+ err56 := p.Ouch.Read(iprot)
+ if err56 != nil {
+ return NewTProtocolExceptionReadStruct("p.OuchInvalidOperation", err56)
+ }
+ return err
+}
+
+func (p *CalculateResult) ReadFieldOuch(iprot TProtocol) TProtocolException {
+ return p.ReadField1(iprot)
+}
+
+func (p *CalculateResult) Write(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteStructBegin("calculate_result")
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ err = p.WriteField0(oprot)
+ if err != nil {
+ return err
+ }
+ err = p.WriteField1(oprot)
+ if err != nil {
+ return err
+ }
+ err = oprot.WriteFieldStop()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+ }
+ err = oprot.WriteStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *CalculateResult) WriteField0(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("success", I32, 0)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err)
+ }
+ err = oprot.WriteI32(int32(p.Success))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *CalculateResult) WriteFieldSuccess(oprot TProtocol) TProtocolException {
+ return p.WriteField0(oprot)
+}
+
+func (p *CalculateResult) WriteField1(oprot TProtocol) (err TProtocolException) {
+ if p.Ouch != nil {
+ err = oprot.WriteFieldBegin("ouch", STRUCT, 1)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "ouch", p.ThriftName(), err)
+ }
+ err = p.Ouch.Write(oprot)
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct("InvalidOperation", err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "ouch", p.ThriftName(), err)
+ }
+ }
+ return err
+}
+
+func (p *CalculateResult) WriteFieldOuch(oprot TProtocol) TProtocolException {
+ return p.WriteField1(oprot)
+}
+
+func (p *CalculateResult) TStructName() string {
+ return "CalculateResult"
+}
+
+func (p *CalculateResult) ThriftName() string {
+ return "calculate_result"
+}
+
+func (p *CalculateResult) String() string {
+ if p == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("CalculateResult(%+v)", *p)
+}
+
+func (p *CalculateResult) CompareTo(other interface{}) (int, bool) {
+ if other == nil {
+ return 1, true
+ }
+ data, ok := other.(*CalculateResult)
+ if !ok {
+ return 0, false
+ }
+ if p.Success != data.Success {
+ if p.Success < data.Success {
+ return -1, true
+ }
+ return 1, true
+ }
+ if cmp, ok := p.Ouch.CompareTo(data.Ouch); !ok || cmp != 0 {
+ return cmp, ok
+ }
+ return 0, true
+}
+
+func (p *CalculateResult) AttributeByFieldId(id int) interface{} {
+ switch id {
+ default:
+ return nil
+ case 0:
+ return p.Success
+ case 1:
+ return p.Ouch
+ }
+ return nil
+}
+
+func (p *CalculateResult) TStructFields() TFieldContainer {
+ return NewTFieldContainer([]TField{
+ NewTField("success", I32, 0),
+ NewTField("ouch", STRUCT, 1),
+ })
+}
+
+
+/**
+ * Structs can also be exceptions, if they are nasty.
+ *
+ * Attributes:
+ * - What
+ * - Why
+ */
+type InvalidOperation struct {
+ TStruct
+ _ interface{} "what" // nil # 0
+ What int32 "what" // 1
+ Why string "why" // 2
+}
+
+func NewInvalidOperation() *InvalidOperation {
+ output := &InvalidOperation{
+ TStruct: NewTStruct("InvalidOperation", []TField{
+ NewTField("what", I32, 1),
+ NewTField("why", STRING, 2),
+ }),
+ }
+ {
+ }
+ return output
+}
+
+func (p *InvalidOperation) Read(iprot TProtocol) (err TProtocolException) {
+ _, err = iprot.ReadStructBegin()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ for {
+ fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+ if fieldId < 0 {
+ fieldId = int16(p.FieldIdFromFieldName(fieldName))
+ } else if fieldName == "" {
+ fieldName = p.FieldNameFromFieldId(int(fieldId))
+ }
+ if fieldTypeId == GENERIC {
+ fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+ }
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ if fieldTypeId == STOP {
+ break
+ }
+ if fieldId == 1 || fieldName == "what" {
+ if fieldTypeId == I32 {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField1(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else if fieldId == 2 || fieldName == "why" {
+ if fieldTypeId == STRING {
+ err = p.ReadField2(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else if fieldTypeId == VOID {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ } else {
+ err = p.ReadField2(iprot)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ } else {
+ err = iprot.Skip(fieldTypeId)
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+ }
+ }
+ err = iprot.ReadStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *InvalidOperation) ReadField1(iprot TProtocol) (err TProtocolException) {
+ v12, err13 := iprot.ReadI32()
+ if err13 != nil {
+ return NewTProtocolExceptionReadField(1, "what", p.ThriftName(), err13)
+ }
+ p.What = v12
+ return err
+}
+
+func (p *InvalidOperation) ReadFieldWhat(iprot TProtocol) TProtocolException {
+ return p.ReadField1(iprot)
+}
+
+func (p *InvalidOperation) ReadField2(iprot TProtocol) (err TProtocolException) {
+ v14, err15 := iprot.ReadString()
+ if err15 != nil {
+ return NewTProtocolExceptionReadField(2, "why", p.ThriftName(), err15)
+ }
+ p.Why = v14
+ return err
+}
+
+func (p *InvalidOperation) ReadFieldWhy(iprot TProtocol) TProtocolException {
+ return p.ReadField2(iprot)
+}
+
+func (p *InvalidOperation) Write(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteStructBegin("InvalidOperation")
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ err = p.WriteField1(oprot)
+ if err != nil {
+ return err
+ }
+ err = p.WriteField2(oprot)
+ if err != nil {
+ return err
+ }
+ err = oprot.WriteFieldStop()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+ }
+ err = oprot.WriteStructEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *InvalidOperation) WriteField1(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("what", I32, 1)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err)
+ }
+ err = oprot.WriteI32(int32(p.What))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *InvalidOperation) WriteFieldWhat(oprot TProtocol) TProtocolException {
+ return p.WriteField1(oprot)
+}
+
+func (p *InvalidOperation) WriteField2(oprot TProtocol) (err TProtocolException) {
+ err = oprot.WriteFieldBegin("why", STRING, 2)
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err)
+ }
+ err = oprot.WriteString(string(p.Why))
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err)
+ }
+ err = oprot.WriteFieldEnd()
+ if err != nil {
+ return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err)
+ }
+ return err
+}
+
+func (p *InvalidOperation) WriteFieldWhy(oprot TProtocol) TProtocolException {
+ return p.WriteField2(oprot)
+}
+
+func (p *InvalidOperation) TStructName() string {
+ return "InvalidOperation"
+}
+
+func (p *InvalidOperation) ThriftName() string {
+ return "InvalidOperation"
+}
+
+func (p *InvalidOperation) String() string {
+ if p == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf("InvalidOperation(%+v)", *p)
+}
+
+func (p *InvalidOperation) CompareTo(other interface{}) (int, bool) {
+ if other == nil {
+ return 1, true
+ }
+ data, ok := other.(*InvalidOperation)
+ if !ok {
+ return 0, false
+ }
+ if p.What != data.What {
+ if p.What < data.What {
+ return -1, true
+ }
+ return 1, true
+ }
+ if p.Why != data.Why {
+ if p.Why < data.Why {
+ return -1, true
+ }
+ return 1, true
+ }
+ return 0, true
+}
+
+func (p *InvalidOperation) AttributeByFieldId(id int) interface{} {
+ switch id {
+ default:
+ return nil
+ case 1:
+ return p.What
+ case 2:
+ return p.Why
+ }
+ return nil
+}
+
+func (p *InvalidOperation) TStructFields() TFieldContainer {
+ return NewTFieldContainer([]TField{
+ NewTField("what", I32, 1),
+ NewTField("why", STRING, 2),
+ })
+}
diff --git a/lib/go/thrift/tserver.go b/lib/go/thrift/tserver.go
new file mode 100644
index 0000000..6bc3167
--- /dev/null
+++ b/lib/go/thrift/tserver.go
@@ -0,0 +1,61 @@
+/*
+ * 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"
+)
+
+type TServer interface {
+ /**
+ * Core processor
+ */
+ ProcessorFactory() TProcessorFactory
+ /**
+ * Server transport
+ */
+ ServerTransport() TServerTransport
+ /**
+ * Input Transport Factory
+ */
+ InputTransportFactory() TTransportFactory
+ /**
+ * Output Transport Factory
+ */
+ OutputTransportFactory() TTransportFactory
+ /**
+ * Input Protocol Factory
+ */
+ InputProtocolFactory() TProtocolFactory
+ /**
+ * Output Protocol Factory
+ */
+ OutputProtocolFactory() TProtocolFactory
+
+ /**
+ * The run method fires up the server and gets things going.
+ */
+ Serve() os.Error
+ /**
+ * Stop the server. This is optional on a per-implementation basis. Not
+ * all servers are required to be cleanly stoppable.
+ */
+ Stop() os.Error
+}
diff --git a/lib/go/thrift/tserver_socket.go b/lib/go/thrift/tserver_socket.go
new file mode 100644
index 0000000..dc3e748
--- /dev/null
+++ b/lib/go/thrift/tserver_socket.go
@@ -0,0 +1,194 @@
+/*
+ * 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"
+)
+
+
+type TServerSocket struct {
+ /**
+ * Underlying socket conection object
+ */
+ conn net.Conn
+ /**
+ * Underlying socket conection object
+ */
+ listener net.Listener
+
+ /**
+ * Address to listen on
+ */
+ addr net.Addr
+
+ /**
+ * Client timeout in nanoseconds
+ */
+ nsecClientTimeout int64
+}
+
+type TServerSocketTransportFactory struct {
+ addr net.Addr
+ nsecClientTimeout int64
+}
+
+func (p *TServerSocketTransportFactory) GetTransport(trans TTransport) TTransport {
+ if trans != nil {
+ t, ok := trans.(*TServerSocket)
+ if ok && t.addr != nil {
+ s, _ := NewTServerSocketAddrTimeout(t.addr, t.nsecClientTimeout)
+ return s
+ }
+ }
+ s, _ := NewTServerSocketAddrTimeout(p.addr, p.nsecClientTimeout)
+ return s
+}
+
+func NewTServerSocketTransportFactory(addr net.Addr, nsecClientTimeout int64) *TServerSocketTransportFactory {
+ return &TServerSocketTransportFactory{addr: addr, nsecClientTimeout: nsecClientTimeout}
+}
+
+func NewTServerSocketConn(conn net.Conn) *TServerSocket {
+ return NewTServerSocketConnTimeout(conn, 0)
+}
+
+func NewTServerSocketConnTimeout(conn net.Conn, nsecClientTimeout int64) *TServerSocket {
+ v := &TServerSocket{conn: conn, addr: conn.LocalAddr(), nsecClientTimeout: nsecClientTimeout}
+ conn.SetTimeout(nsecClientTimeout)
+ return v
+}
+
+func NewTServerSocketAddr(addr net.Addr) (*TServerSocket, TTransportException) {
+ return NewTServerSocketAddrTimeout(addr, 0)
+}
+
+func NewTServerSocketAddrTimeout(addr net.Addr, nsecClientTimeout int64) (*TServerSocket, TTransportException) {
+ s := &TServerSocket{addr: addr, nsecClientTimeout: nsecClientTimeout}
+ return s, nil
+}
+
+func (p *TServerSocket) Listen() (err os.Error) {
+ if p.listener == nil {
+ if p.listener, err = net.Listen("tcp", p.addr.String()); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (p *TServerSocket) Accept() (TTransport, os.Error) {
+ if p.listener == nil {
+ if err := p.Listen(); err != nil {
+ return nil, NewTTransportExceptionFromOsError(err)
+ }
+ if p.listener == nil {
+ return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
+ }
+ }
+ conn, err := p.listener.Accept()
+ if err != nil {
+ return nil, NewTTransportExceptionFromOsError(err)
+ }
+ conn.SetTimeout(p.nsecClientTimeout)
+ return NewTSocketConn(conn)
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TServerSocket) IsOpen() bool {
+ return p.listener != nil
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TServerSocket) Open() os.Error {
+ if !p.IsOpen() {
+ l, err := net.Listen(p.addr.Network(), p.addr.String())
+ if err != nil {
+ return err
+ }
+ p.listener = l
+ return nil
+ }
+ return NewTTransportException(ALREADY_OPEN, "Server socket already open")
+}
+
+/**
+ * Perform a nonblocking read into buffer.
+ */
+func (p *TServerSocket) Read(buf []byte) (int, os.Error) {
+ return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Read([]byte) is not implemented")
+}
+
+func (p *TServerSocket) ReadAll(buf []byte) (int, os.Error) {
+ return ReadAllTransport(p, buf)
+}
+
+/**
+ * Perform a nonblocking write of the data in buffer;
+ */
+func (p *TServerSocket) Write(buf []byte) (int, os.Error) {
+ return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Write([]byte) is not implemented")
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TServerSocket) Flush() os.Error {
+ return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Flush() is not implemented")
+}
+
+func (p *TServerSocket) Addr() net.Addr {
+ return p.addr
+}
+
+func (p *TServerSocket) Peek() bool {
+ return p.IsOpen()
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TServerSocket) Close() (err os.Error) {
+ if p.IsOpen() {
+ err := p.listener.Close()
+ if err != nil {
+ return NewTTransportExceptionFromOsError(err)
+ }
+ p.listener = nil
+ }
+ if p.conn != nil {
+ err := p.conn.Close()
+ if err != nil {
+ return NewTTransportExceptionFromOsError(err)
+ }
+ p.conn = nil
+ }
+ return nil
+}
+
+func (p *TServerSocket) Interrupt() os.Error {
+ // TODO(pomack) fix Interrupt as it is probably not right
+ return NewTTransportExceptionFromOsError(p.Close())
+}
diff --git a/lib/go/thrift/tserver_test.go b/lib/go/thrift/tserver_test.go
new file mode 100644
index 0000000..3cbe879
--- /dev/null
+++ b/lib/go/thrift/tserver_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_test
+
+import (
+ "testing"
+)
+
+func TestNothing(t *testing.T) {
+
+}
diff --git a/lib/go/thrift/tserver_transport.go b/lib/go/thrift/tserver_transport.go
new file mode 100644
index 0000000..ef3a462
--- /dev/null
+++ b/lib/go/thrift/tserver_transport.go
@@ -0,0 +1,41 @@
+/*
+ * 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"
+
+/**
+ * Server transport. Object which provides client transports.
+ *
+ */
+type TServerTransport interface {
+ Listen() os.Error
+ Accept() (TTransport, os.Error)
+ Close() os.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() os.Error
+}
diff --git a/lib/go/thrift/tset.go b/lib/go/thrift/tset.go
new file mode 100644
index 0000000..f868109
--- /dev/null
+++ b/lib/go/thrift/tset.go
@@ -0,0 +1,207 @@
+/*
+ * 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 (
+ "container/list"
+)
+
+/**
+ * Helper class that encapsulates set metadata.
+ *
+ */
+type TSet interface {
+ TContainer
+ ElemType() TType
+ Add(data interface{})
+ Remove(data interface{})
+ Less(other interface{}) bool
+ Front() *list.Element
+ Back() *list.Element
+ Values() []interface{}
+}
+
+type tSet struct {
+ elemType TType
+ size int
+ l *list.List
+}
+
+func NewTSet(t TType, s int) TSet {
+ return &tSet{elemType: t, size: s, l: list.New()}
+}
+
+func NewTSetDefault() TSet {
+ return NewTSet(STOP, 0)
+}
+
+func (p *tSet) ElemType() TType {
+ return p.elemType
+}
+
+func (p *tSet) Front() *list.Element {
+ return p.l.Front()
+}
+
+func (p *tSet) Back() *list.Element {
+ return p.l.Back()
+}
+
+func (p *tSet) Len() int {
+ if p.l.Len() != 0 {
+ return p.l.Len()
+ }
+ return p.size
+}
+
+func (p *tSet) Contains(data interface{}) bool {
+ return p.find(data) != nil
+}
+
+func (p *tSet) Add(other interface{}) {
+ if data, ok := p.elemType.CoerceData(other); ok {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ if cmp, ok := p.elemType.Compare(data, elem.Value); ok && cmp >= 0 {
+ if cmp > 0 {
+ p.l.InsertBefore(data, elem)
+ }
+ return
+ }
+ }
+ }
+}
+
+func (p *tSet) Remove(data interface{}) {
+ elem := p.find(data)
+ if elem != nil {
+ p.l.Remove(elem)
+ }
+}
+
+func (p *tSet) Less(other interface{}) bool {
+ cmp, ok := p.CompareTo(other)
+ return ok && cmp > 0
+}
+
+func (p *tSet) Equals(other interface{}) bool {
+ c, cok := p.CompareTo(other)
+ return cok && c == 0
+}
+
+func (p *tSet) CompareTo(other interface{}) (int, bool) {
+ return TType(SET).Compare(p, other)
+}
+
+func (p *tSet) find(data interface{}) *list.Element {
+ if data == nil {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ if elem.Value == nil {
+ return elem
+ }
+ }
+ return nil
+ }
+ data, ok := p.elemType.CoerceData(data)
+ if data == nil || !ok {
+ return nil
+ }
+ if p.elemType.IsBaseType() || p.elemType.IsEnum() {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ if data == elem.Value {
+ return elem
+ }
+ }
+ return nil
+ }
+ if cmp, ok := data.(EqualsOtherInterface); ok {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ if cmp.Equals(elem.Value) {
+ return elem
+ }
+ }
+ return nil
+ }
+ switch p.elemType {
+ case MAP:
+ if cmp, ok := data.(EqualsMap); ok {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ v := elem.Value
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TMap)) {
+ return elem
+ }
+ }
+ return nil
+ }
+ case SET:
+ if cmp, ok := data.(EqualsSet); ok {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ v := elem.Value
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TSet)) {
+ return elem
+ }
+ }
+ return nil
+ }
+ case LIST:
+ if cmp, ok := data.(EqualsList); ok {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ v := elem.Value
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TList)) {
+ return elem
+ }
+ }
+ return nil
+ }
+ case STRUCT:
+ if cmp, ok := data.(EqualsStruct); ok {
+ for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+ v := elem.Value
+ if v == nil {
+ continue
+ }
+ if cmp.Equals(v.(TStruct)) {
+ return elem
+ }
+ }
+ return nil
+ }
+ }
+ return nil
+}
+
+func (p *tSet) Values() []interface{} {
+ size := p.l.Len()
+ values := make([]interface{}, size, size)
+ i := 0
+ for v := p.l.Front(); v != nil; v = v.Next() {
+ values[i] = v.Value
+ i++
+ }
+ return values
+}
diff --git a/lib/go/thrift/tsimple_json_protocol.go b/lib/go/thrift/tsimple_json_protocol.go
new file mode 100644
index 0000000..569dd9c
--- /dev/null
+++ b/lib/go/thrift/tsimple_json_protocol.go
@@ -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
+}
diff --git a/lib/go/thrift/tsimple_json_protocol_test.go b/lib/go/thrift/tsimple_json_protocol_test.go
new file mode 100644
index 0000000..e57d55b
--- /dev/null
+++ b/lib/go/thrift/tsimple_json_protocol_test.go
@@ -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())
+}
diff --git a/lib/go/thrift/tsimple_server.go b/lib/go/thrift/tsimple_server.go
new file mode 100644
index 0000000..6c7d656
--- /dev/null
+++ b/lib/go/thrift/tsimple_server.go
@@ -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
+ }
+ }
+}
diff --git a/lib/go/thrift/tsocket.go b/lib/go/thrift/tsocket.go
new file mode 100644
index 0000000..758c132
--- /dev/null
+++ b/lib/go/thrift/tsocket.go
@@ -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()
+}
diff --git a/lib/go/thrift/tstruct.go b/lib/go/thrift/tstruct.go
new file mode 100644
index 0000000..5eaffae
--- /dev/null
+++ b/lib/go/thrift/tstruct.go
@@ -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("")
+}
diff --git a/lib/go/thrift/ttransport.go b/lib/go/thrift/ttransport.go
new file mode 100644
index 0000000..45557f8
--- /dev/null
+++ b/lib/go/thrift/ttransport.go
@@ -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)
+}
diff --git a/lib/go/thrift/ttransport_exception.go b/lib/go/thrift/ttransport_exception.go
new file mode 100644
index 0000000..b9fae17
--- /dev/null
+++ b/lib/go/thrift/ttransport_exception.go
@@ -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())
+}
diff --git a/lib/go/thrift/ttransport_factory.go b/lib/go/thrift/ttransport_factory.go
new file mode 100644
index 0000000..4ab4dbe
--- /dev/null
+++ b/lib/go/thrift/ttransport_factory.go
@@ -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{}
+}
diff --git a/lib/go/thrift/ttransport_test.go b/lib/go/thrift/ttransport_test.go
new file mode 100644
index 0000000..b9630de
--- /dev/null
+++ b/lib/go/thrift/ttransport_test.go
@@ -0,0 +1,131 @@
+/*
+ * 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"
+ "testing"
+ "net"
+ "os"
+ "strconv"
+)
+
+const TRANSPORT_BINARY_DATA_SIZE = 4096
+
+var (
+ transport_bdata []byte // test data for writing; same as data
+)
+
+func init() {
+ transport_bdata = make([]byte, TRANSPORT_BINARY_DATA_SIZE)
+ for i := 0; i < TRANSPORT_BINARY_DATA_SIZE; i++ {
+ transport_bdata[i] = byte((i + 'a') % 255)
+ }
+}
+
+func TransportTest(t *testing.T, writeTrans TTransport, readTrans TTransport) {
+ buf := make([]byte, TRANSPORT_BINARY_DATA_SIZE)
+ if !writeTrans.IsOpen() {
+ err := writeTrans.Open()
+ if err != nil {
+ t.Fatalf("Transport %T cannot open write transport: %s", writeTrans, err)
+ }
+ }
+ if !readTrans.IsOpen() {
+ err := readTrans.Open()
+ if err != nil {
+ t.Fatalf("Transport %T cannot open read transport: %s", readTrans, err)
+ }
+ }
+ _, err := writeTrans.Write(transport_bdata)
+ if err != nil {
+ t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err)
+ }
+ err = writeTrans.Flush()
+ if err != nil {
+ t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err)
+ }
+ n, err := readTrans.ReadAll(buf)
+ if err != nil {
+ t.Errorf("Transport %T cannot read binary data of length %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, err)
+ }
+ if n != TRANSPORT_BINARY_DATA_SIZE {
+ t.Errorf("Transport %T read only %d instead of %d bytes of binary data", readTrans, n, TRANSPORT_BINARY_DATA_SIZE)
+ }
+ for k, v := range buf {
+ if v != transport_bdata[k] {
+ t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k)
+ }
+ }
+ _, err = writeTrans.Write(transport_bdata)
+ if err != nil {
+ t.Fatalf("Transport %T cannot write binary data 2 of length %d: %s", writeTrans, len(transport_bdata), err)
+ }
+ err = writeTrans.Flush()
+ if err != nil {
+ t.Fatalf("Transport %T cannot flush write binary data 2: %s", writeTrans, err)
+ }
+ b := readTrans.Peek()
+ if b != true {
+ t.Errorf("Transport %T returned %s for Peek()", readTrans, b)
+ }
+ buf = make([]byte, TRANSPORT_BINARY_DATA_SIZE)
+ read := 1
+ for n = 0; n < TRANSPORT_BINARY_DATA_SIZE && read != 0; {
+ read, err = readTrans.Read(buf[n:])
+ if err != nil {
+ t.Errorf("Transport %T cannot read binary data 2 of total length %d from offset %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, n, err)
+ }
+ n += read
+ }
+ if n != TRANSPORT_BINARY_DATA_SIZE {
+ t.Errorf("Transport %T read only %d instead of %d bytes of binary data 2", readTrans, n, TRANSPORT_BINARY_DATA_SIZE)
+ }
+ for k, v := range buf {
+ if v != transport_bdata[k] {
+ t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k)
+ }
+ }
+}
+
+func CloseTransports(t *testing.T, readTrans TTransport, writeTrans TTransport) {
+ err := readTrans.Close()
+ if err != nil {
+ t.Errorf("Transport %T cannot close read transport: %s", readTrans, err)
+ }
+ if writeTrans != readTrans {
+ err = writeTrans.Close()
+ if err != nil {
+ t.Errorf("Transport %T cannot close write transport: %s", writeTrans, err)
+ }
+ }
+}
+
+func FindAvailableTCPServerPort(startPort int) (net.Addr, os.Error) {
+ for i := startPort; i < 65535; i++ {
+ s := "127.0.0.1:" + strconv.Itoa(i)
+ l, err := net.Listen("tcp", s)
+ if err == nil {
+ l.Close()
+ return net.ResolveTCPAddr(s)
+ }
+ }
+ return nil, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Could not find available server port")
+}
diff --git a/lib/go/thrift/ttype.go b/lib/go/thrift/ttype.go
new file mode 100644
index 0000000..d024b39
--- /dev/null
+++ b/lib/go/thrift/ttype.go
@@ -0,0 +1,975 @@
+/*
+ * 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 (
+ "container/list"
+ "container/vector"
+ "strconv"
+)
+
+/**
+ * Type constants in the Thrift protocol.
+ */
+type TType byte
+
+const (
+ STOP = 0
+ VOID = 1
+ BOOL = 2
+ BYTE = 3
+ I08 = 3
+ DOUBLE = 4
+ I16 = 6
+ I32 = 8
+ I64 = 10
+ STRING = 11
+ UTF7 = 11
+ STRUCT = 12
+ MAP = 13
+ SET = 14
+ LIST = 15
+ ENUM = 16
+ UTF8 = 16
+ UTF16 = 17
+ GENERIC = 127
+)
+
+func (p TType) String() string {
+ switch p {
+ case STOP:
+ return "STOP"
+ case VOID:
+ return "VOID"
+ case BOOL:
+ return "BOOL"
+ case BYTE:
+ return "BYTE"
+ case DOUBLE:
+ return "DOUBLE"
+ case I16:
+ return "I16"
+ case I32:
+ return "I32"
+ case I64:
+ return "I64"
+ case STRING:
+ return "STRING"
+ case STRUCT:
+ return "STRUCT"
+ case MAP:
+ return "MAP"
+ case SET:
+ return "SET"
+ case LIST:
+ return "LIST"
+ case ENUM:
+ return "ENUM"
+ case UTF16:
+ return "UTF16"
+ case GENERIC:
+ return "GENERIC"
+ }
+ return "Unknown"
+}
+
+func (p TType) IsBaseType() bool {
+ switch p {
+ case BOOL, BYTE, DOUBLE, I16, I32, I64, STRING, UTF8, UTF16:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsEmptyType() bool {
+ switch p {
+ case STOP, VOID:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsEnum() bool {
+ switch p {
+ case ENUM:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsNumericType() bool {
+ switch p {
+ case ENUM, BOOL, BYTE, DOUBLE, I16, I32, I64:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsStringType() bool {
+ switch p {
+ case STRING, UTF8, UTF16:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsContainer() bool {
+ switch p {
+ case MAP, SET, LIST:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsStruct() bool {
+ switch p {
+ case STRUCT:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsMap() bool {
+ switch p {
+ case MAP:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsList() bool {
+ switch p {
+ case LIST:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsSet() bool {
+ switch p {
+ case SET:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) IsInt() bool {
+ switch p {
+ case BYTE, I16, I32, I64:
+ return true
+ default:
+ return false
+ }
+ return false
+}
+
+func (p TType) Coerce(other interface{}) TType {
+ if other == nil {
+ return TType(STOP)
+ }
+ switch b := other.(type) {
+ default:
+ return TType(STOP)
+ case nil:
+ return TType(STOP)
+ case TType:
+ return b
+ case byte:
+ return TType(b)
+ case int:
+ return TType(byte(b))
+ case int8:
+ return TType(byte(b))
+ case int32:
+ return TType(byte(b))
+ case int64:
+ return TType(byte(b))
+ case uint:
+ return TType(byte(b))
+ case uint32:
+ return TType(byte(b))
+ case uint64:
+ return TType(byte(b))
+ case float32:
+ return TType(byte(int(b)))
+ case float64:
+ return TType(byte(int(b)))
+ }
+ return TType(STOP)
+}
+
+func (p TType) LessType(other interface{}) bool {
+ return p < p.Coerce(other)
+}
+
+func (p TType) Less(i, j interface{}) bool {
+ cmp, ok := p.Compare(i, j)
+ return ok && cmp > 0
+}
+
+
+func (p TType) Compare(i, j interface{}) (int, bool) {
+ if i == j {
+ return 0, true
+ }
+ if i == nil {
+ if j == nil {
+ return 0, true
+ }
+ return -1, true
+ }
+ if j == nil {
+ return 1, true
+ }
+ ci, iok := p.CoerceData(i)
+ cj, jok := p.CoerceData(j)
+ if iok && !jok {
+ return 1, true
+ }
+ if !iok && jok {
+ return -1, true
+ }
+ // hopefully this doesn't happen as Compare() would continuously return 0, false
+ if !iok && !jok {
+ return 0, false
+ }
+ if ci == cj {
+ return 0, true
+ }
+ if ci == nil {
+ if cj == nil {
+ return 0, true
+ }
+ return -1, true
+ }
+ if cj == nil {
+ return 1, true
+ }
+ switch p {
+ case STOP, VOID:
+ // hopefully this doesn't happen as Compare() would continuously return 0, false
+ return 0, false
+ case BOOL:
+ vi := ci.(bool)
+ vj := cj.(bool)
+ if vi == vj {
+ return 0, true
+ }
+ if vi == false {
+ return -1, true
+ }
+ return 1, true
+ case BYTE:
+ vi := ci.(byte)
+ vj := cj.(byte)
+ if vi == vj {
+ return 0, true
+ }
+ if vi < vj {
+ return -1, true
+ }
+ return 1, true
+ case DOUBLE:
+ vi := ci.(float64)
+ vj := cj.(float64)
+ if vi == vj {
+ return 0, true
+ }
+ if vi < vj {
+ return -1, true
+ }
+ return 1, true
+ case I16:
+ vi := ci.(int16)
+ vj := cj.(int16)
+ if vi == vj {
+ return 0, true
+ }
+ if vi < vj {
+ return -1, true
+ }
+ return 1, true
+ case I32:
+ vi := ci.(int32)
+ vj := cj.(int32)
+ if vi == vj {
+ return 0, true
+ }
+ if vi < vj {
+ return -1, true
+ }
+ return 1, true
+ case I64:
+ vi := ci.(int64)
+ vj := cj.(int64)
+ if vi == vj {
+ return 0, true
+ }
+ if vi < vj {
+ return -1, true
+ }
+ return 1, true
+ case STRING, UTF8, UTF16:
+ vi := ci.(string)
+ vj := cj.(string)
+ if vi == vj {
+ return 0, true
+ }
+ if vi < vj {
+ return -1, true
+ }
+ return 1, true
+ case STRUCT:
+ si := ci.(TStruct)
+ sj := cj.(TStruct)
+ if cmp := CompareString(si.ThriftName(), sj.ThriftName()); cmp != 0 {
+ return cmp, true
+ }
+ if cmp, ok := si.TStructFields().CompareTo(sj.TStructFields()); !ok || cmp != 0 {
+ return cmp, ok
+ }
+ for field := range si.TStructFields().Iter() {
+ a := si.AttributeFromFieldId(field.Id())
+ b := sj.AttributeFromFieldId(field.Id())
+ if cmp, ok := field.TypeId().Compare(a, b); !ok || cmp != 0 {
+ return cmp, ok
+ }
+ }
+ return 0, true
+ case MAP:
+ mi := ci.(TMap)
+ mj := cj.(TMap)
+ ei := mi.KeyType()
+ if ej := mj.KeyType(); ei != ej {
+ return CompareInt(int(ei), int(ej)), true
+ }
+ if size := mi.Len(); size != mj.Len() {
+ return CompareInt(size, mj.Len()), true
+ }
+ if c, cok := ei.Compare(mi.Keys(), mj.Keys()); c != 0 || !cok {
+ return c, cok
+ }
+ return ei.Compare(mi.Values(), mj.Values())
+ case LIST:
+ li := ci.(TList)
+ lj := cj.(TList)
+ ei := li.ElemType()
+ ej := lj.ElemType()
+ if ei != ej {
+ return CompareInt(int(ei), int(ej)), true
+ }
+ size := li.Len()
+ if size != lj.Len() {
+ return CompareInt(size, lj.Len()), true
+ }
+ for k := 0; k < size; k++ {
+ vi := li.At(k)
+ vj := lj.At(k)
+ c, cok := ei.Compare(vi, vj)
+ if c != 0 || !cok {
+ return c, cok
+ }
+ }
+ return 0, true
+ case SET:
+ li := ci.(TSet)
+ lj := cj.(TSet)
+ ei := li.ElemType()
+ ej := lj.ElemType()
+ if ei != ej {
+ return CompareInt(int(ei), int(ej)), true
+ }
+ size := li.Len()
+ if size != lj.Len() {
+ return CompareInt(size, lj.Len()), true
+ }
+ return ei.Compare(li.Values(), lj.Values())
+ default:
+ panic("Invalid thrift type to coerce")
+ }
+ return 0, false
+}
+
+func (p TType) CompareValueArrays(li, lj []interface{}) (int, bool) {
+ size := len(li)
+ if cmp := CompareInt(size, len(lj)); cmp != 0 {
+ return cmp, true
+ }
+ for i := 0; i < size; i++ {
+ vi := li[i]
+ vj := lj[i]
+ c, cok := p.Compare(vi, vj)
+ if c != 0 || !cok {
+ return c, cok
+ }
+ }
+ return 0, true
+}
+
+func (p TType) Equals(other interface{}) bool {
+ return p == p.Coerce(other)
+}
+
+type Stringer interface {
+ String() string
+}
+
+type Enumer interface {
+ String() string
+ Value() int
+ IsEnum() bool
+}
+
+func TypeFromValue(data interface{}) TType {
+ switch i := data.(type) {
+ default:
+ return STOP
+ case nil:
+ return VOID
+ case bool:
+ return BOOL
+ case float32, float64:
+ return DOUBLE
+ case int, int32:
+ return I32
+ case byte:
+ return BYTE
+ case int8:
+ return I08
+ case int16:
+ return I16
+ case int64:
+ return I64
+ case string:
+ return STRING
+ case TStruct:
+ return STRUCT
+ case TMap:
+ return MAP
+ case TSet:
+ return SET
+ case []interface{}, *list.List, *vector.Vector, TList:
+ return LIST
+ }
+ return STOP
+}
+
+func (p TType) CoerceData(data interface{}) (interface{}, bool) {
+ if data == nil {
+ switch p {
+ case STOP:
+ return nil, true
+ case VOID:
+ return nil, true
+ case BOOL:
+ return false, true
+ case BYTE:
+ return byte(0), true
+ case DOUBLE:
+ return float64(0), true
+ case I16:
+ return int16(0), true
+ case I32:
+ return int32(0), true
+ case I64:
+ return int64(0), true
+ case STRING, UTF8, UTF16:
+ return "", true
+ case STRUCT:
+ return NewTStructEmpty(""), true
+ case MAP:
+ return NewTMapDefault(), true
+ case LIST:
+ return NewTListDefault(), true
+ case SET:
+ return NewTSetDefault(), true
+ default:
+ panic("Invalid thrift type to coerce")
+ }
+ }
+ switch p {
+ case STOP:
+ return nil, true
+ case VOID:
+ return nil, true
+ case BOOL:
+ switch b := data.(type) {
+ default:
+ return false, false
+ case bool:
+ return b, true
+ case Numeric:
+ return bool(b.Int() != 0), true
+ case int:
+ return b != 0, true
+ case byte:
+ return b != 0, true
+ case int8:
+ return b != 0, true
+ case int16:
+ return b != 0, true
+ case int32:
+ return b != 0, true
+ case int64:
+ return b != 0, true
+ case uint:
+ return b != 0, true
+ case uint16:
+ return b != 0, true
+ case uint32:
+ return b != 0, true
+ case uint64:
+ return b != 0, true
+ case float32:
+ return b != 0, true
+ case float64:
+ return b != 0, true
+ case Stringer:
+ v := b.String()
+ if v == "false" || v == "0" || len(v) == 0 {
+ return false, true
+ }
+ return true, true
+ case string:
+ if b == "false" || b == "0" || len(b) == 0 {
+ return false, true
+ }
+ return true, true
+ }
+ case BYTE:
+ if b, ok := data.(byte); ok {
+ return b, true
+ }
+ if b, ok := data.(Numeric); ok {
+ return b.Byte(), true
+ }
+ if b, ok := data.(bool); ok {
+ if b {
+ return byte(1), true
+ }
+ return byte(0), true
+ }
+ if b, ok := data.(int); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(int8); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(int16); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(int32); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(int64); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(uint); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(uint8); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(uint16); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(uint32); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(uint64); ok {
+ return byte(b), true
+ }
+ if b, ok := data.(float32); ok {
+ return byte(int(b)), true
+ }
+ if b, ok := data.(float64); ok {
+ return byte(int(b)), true
+ }
+ if b, ok := data.(Stringer); ok {
+ data = b.String()
+ }
+ if b, ok := data.(string); ok {
+ i1, err := strconv.Atoi(b)
+ if err != nil {
+ return byte(int(i1)), true
+ }
+ }
+ return byte(0), false
+ case DOUBLE:
+ if b, ok := data.(float32); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(float64); ok {
+ return b, true
+ }
+ if b, ok := data.(Numeric); ok {
+ return bool(b.Float64() != 0.0), true
+ }
+ if b, ok := data.(byte); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(bool); ok {
+ if b {
+ return float64(1.0), true
+ }
+ return float64(0.0), true
+ }
+ if b, ok := data.(int); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(int8); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(int16); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(int32); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(int64); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(uint); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(uint8); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(uint16); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(uint32); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(uint64); ok {
+ return float64(b), true
+ }
+ if b, ok := data.(Stringer); ok {
+ data = b.String()
+ }
+ if b, ok := data.(string); ok {
+ d1, err := strconv.Atof64(b)
+ if err != nil {
+ return d1, true
+ }
+ }
+ return float64(0), false
+ case I16:
+ if b, ok := data.(int16); ok {
+ return b, true
+ }
+ if b, ok := data.(int); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(Numeric); ok {
+ return bool(b.Int16() != 0), true
+ }
+ if b, ok := data.(byte); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(bool); ok {
+ if b {
+ return int16(1.0), true
+ }
+ return int16(0.0), true
+ }
+ if b, ok := data.(int8); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(int32); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(int64); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(uint); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(uint8); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(uint16); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(uint32); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(uint64); ok {
+ return int16(b), true
+ }
+ if b, ok := data.(float32); ok {
+ return int16(int(b)), true
+ }
+ if b, ok := data.(float64); ok {
+ return int16(int(b)), true
+ }
+ if b, ok := data.(Stringer); ok {
+ data = b.String()
+ }
+ if b, ok := data.(string); ok {
+ i1, err := strconv.Atoi(b)
+ if err != nil {
+ return int16(i1), true
+ }
+ }
+ return int16(0), false
+ case I32:
+ if b, ok := data.(int32); ok {
+ return b, true
+ }
+ if b, ok := data.(int); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(Numeric); ok {
+ return bool(b.Int32() != 0), true
+ }
+ if b, ok := data.(byte); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(bool); ok {
+ if b {
+ return int32(1.0), true
+ }
+ return int32(0.0), true
+ }
+ if b, ok := data.(int8); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(int16); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(int64); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(uint); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(uint8); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(uint16); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(uint32); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(uint64); ok {
+ return int32(b), true
+ }
+ if b, ok := data.(float32); ok {
+ return int32(int(b)), true
+ }
+ if b, ok := data.(float64); ok {
+ return int32(int(b)), true
+ }
+ if b, ok := data.(Stringer); ok {
+ data = b.String()
+ }
+ if b, ok := data.(string); ok {
+ i1, err := strconv.Atoi(b)
+ if err != nil {
+ return int32(i1), true
+ }
+ }
+ return int32(0), false
+ case I64:
+ if b, ok := data.(int64); ok {
+ return b, true
+ }
+ if b, ok := data.(int32); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(int); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(Numeric); ok {
+ return bool(b.Int64() != 0), true
+ }
+ if b, ok := data.(byte); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(bool); ok {
+ if b {
+ return int64(1.0), true
+ }
+ return int64(0.0), true
+ }
+ if b, ok := data.(int8); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(int16); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(uint); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(uint8); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(uint16); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(uint32); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(uint64); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(float32); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(float64); ok {
+ return int64(b), true
+ }
+ if b, ok := data.(Stringer); ok {
+ data = b.String()
+ }
+ if b, ok := data.(string); ok {
+ i1, err := strconv.Atoi64(b)
+ if err != nil {
+ return i1, true
+ }
+ }
+ return int64(0), false
+ case STRING, UTF8, UTF16:
+ if b, ok := data.(Enumer); ok {
+ if i1, ok := data.(int); ok {
+ return i1, true
+ }
+ return b.String(), true
+ }
+ if b, ok := data.(Stringer); ok {
+ return b.String(), true
+ }
+ if b, ok := data.(string); ok {
+ return b, true
+ }
+ if b, ok := data.(int); ok {
+ return string(b), true
+ }
+ if b, ok := data.(byte); ok {
+ return string(b), true
+ }
+ if b, ok := data.(bool); ok {
+ if b {
+ return "true", true
+ }
+ return "false", true
+ }
+ if b, ok := data.(int8); ok {
+ return string(b), true
+ }
+ if b, ok := data.(int16); ok {
+ return string(b), true
+ }
+ if b, ok := data.(int32); ok {
+ return string(b), true
+ }
+ if b, ok := data.(int64); ok {
+ return string(b), true
+ }
+ if b, ok := data.(uint); ok {
+ return string(b), true
+ }
+ if b, ok := data.(uint8); ok {
+ return string(b), true
+ }
+ if b, ok := data.(uint16); ok {
+ return string(b), true
+ }
+ if b, ok := data.(uint32); ok {
+ return string(b), true
+ }
+ if b, ok := data.(uint64); ok {
+ return string(b), true
+ }
+ if b, ok := data.(float32); ok {
+ return strconv.Ftoa32(b, 'g', -1), true
+ }
+ if b, ok := data.(float64); ok {
+ return strconv.Ftoa64(b, 'g', -1), true
+ }
+ return "", false
+ case STRUCT:
+ if b, ok := data.(TStruct); ok {
+ return b, true
+ }
+ return NewTStructEmpty(""), true
+ case MAP:
+ if b, ok := data.(TMap); ok {
+ return b, true
+ }
+ return NewTMapDefault(), false
+ case LIST:
+ if b, ok := data.(TList); ok {
+ return b, true
+ }
+ return NewTListDefault(), false
+ case SET:
+ if b, ok := data.(TSet); ok {
+ return b, true
+ }
+ return NewTSetDefault(), false
+ default:
+ panic("Invalid thrift type to coerce")
+ }
+ return nil, false
+}
+
+type EqualsOtherInterface interface {
+ Equals(other interface{}) bool
+}
+
+type EqualsMap interface {
+ Equals(other TMap) bool
+}
+
+type EqualsSet interface {
+ Equals(other TSet) bool
+}
+
+type EqualsList interface {
+ Equals(other TList) bool
+}
+
+type EqualsStruct interface {
+ Equals(other TStruct) bool
+}