You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by cl...@apache.org on 2011/02/20 03:39:21 UTC
svn commit: r1072478 [4/8] - in /thrift/trunk: ./ compiler/cpp/
compiler/cpp/src/generate/ lib/ lib/go/ lib/go/thrift/ test/ tutorial/go/
tutorial/go/src/
Added: thrift/trunk/lib/go/thrift/tframed_transport.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tframed_transport.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tframed_transport.go (added)
+++ thrift/trunk/lib/go/thrift/tframed_transport.go Sun Feb 20 02:39:19 2011
@@ -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
+}
Added: thrift/trunk/lib/go/thrift/tframed_transport_test.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tframed_transport_test.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tframed_transport_test.go (added)
+++ thrift/trunk/lib/go/thrift/tframed_transport_test.go Sun Feb 20 02:39:19 2011
@@ -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)
+}
Added: thrift/trunk/lib/go/thrift/thttp_client.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/thttp_client.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/thttp_client.go (added)
+++ thrift/trunk/lib/go/thrift/thttp_client.go Sun Feb 20 02:39:19 2011
@@ -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
+}
Added: thrift/trunk/lib/go/thrift/thttp_client_test.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/thttp_client_test.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/thttp_client_test.go (added)
+++ thrift/trunk/lib/go/thrift/thttp_client_test.go Sun Feb 20 02:39:19 2011
@@ -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)
+}
Added: thrift/trunk/lib/go/thrift/tiostream_transport.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tiostream_transport.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tiostream_transport.go (added)
+++ thrift/trunk/lib/go/thrift/tiostream_transport.go Sun Feb 20 02:39:19 2011
@@ -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
+}
Added: thrift/trunk/lib/go/thrift/tiostream_transport_test.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tiostream_transport_test.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tiostream_transport_test.go (added)
+++ thrift/trunk/lib/go/thrift/tiostream_transport_test.go Sun Feb 20 02:39:19 2011
@@ -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)
+}
Added: thrift/trunk/lib/go/thrift/tjson_protocol.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tjson_protocol.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tjson_protocol.go (added)
+++ thrift/trunk/lib/go/thrift/tjson_protocol.go Sun Feb 20 02:39:19 2011
@@ -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)
+}
Added: thrift/trunk/lib/go/thrift/tjson_protocol_test.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tjson_protocol_test.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tjson_protocol_test.go (added)
+++ thrift/trunk/lib/go/thrift/tjson_protocol_test.go Sun Feb 20 02:39:19 2011
@@ -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())
+}
Added: thrift/trunk/lib/go/thrift/tlist.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tlist.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tlist.go (added)
+++ thrift/trunk/lib/go/thrift/tlist.go Sun Feb 20 02:39:19 2011
@@ -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)
+}
Added: thrift/trunk/lib/go/thrift/tmap.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tmap.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tmap.go (added)
+++ thrift/trunk/lib/go/thrift/tmap.go Sun Feb 20 02:39:19 2011
@@ -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
+}
Added: thrift/trunk/lib/go/thrift/tmemory_buffer.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tmemory_buffer.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tmemory_buffer.go (added)
+++ thrift/trunk/lib/go/thrift/tmemory_buffer.go Sun Feb 20 02:39:19 2011
@@ -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()
+}
Added: thrift/trunk/lib/go/thrift/tmemory_buffer_test.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tmemory_buffer_test.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tmemory_buffer_test.go (added)
+++ thrift/trunk/lib/go/thrift/tmemory_buffer_test.go Sun Feb 20 02:39:19 2011
@@ -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)
+}
Added: thrift/trunk/lib/go/thrift/tmessage.go
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/go/thrift/tmessage.go?rev=1072478&view=auto
==============================================================================
--- thrift/trunk/lib/go/thrift/tmessage.go (added)
+++ thrift/trunk/lib/go/thrift/tmessage.go Sun Feb 20 02:39:19 2011
@@ -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()
+}