You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2015/03/13 22:36:06 UTC
[1/2] qpid-proton git commit: PROTON-827: go binding - send.go,
listen.go examples with implementation stubs.
Repository: qpid-proton
Updated Branches:
refs/heads/master faf925c4a -> 695f8e5b9
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/unmarshal.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/unmarshal.go b/proton-c/bindings/go/src/qpid.apache.org/proton/unmarshal.go
new file mode 100644
index 0000000..fb09d0f
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/unmarshal.go
@@ -0,0 +1,517 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+oor 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 proton
+
+// #include <proton/codec.h>
+import "C"
+
+import (
+ "bytes"
+ "io"
+ "reflect"
+ "unsafe"
+)
+
+const minDecode = 256
+
+//
+// Decoding from a pn_data_t
+//
+// NOTE: we use panic() to signal a decoding error, simplifies decoding logic.
+// We recover() at the highest possible level - i.e. in the exported Unmarshal or Decode.
+//
+
+// Decoder decodes AMQP values from an io.Reader.
+//
+type Decoder struct {
+ reader io.Reader
+ buffer bytes.Buffer
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder has it's own buffer and may read more data than required for the
+// AMQP values requested. Use Buffered to see if there is data left in the
+// buffer.
+//
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{r, bytes.Buffer{}}
+}
+
+// Buffered returns a reader of the data remaining in the Decoder's buffer. The
+// reader is valid until the next call to Decode.
+//
+func (d *Decoder) Buffered() io.Reader {
+ return bytes.NewReader(d.buffer.Bytes())
+}
+
+// Decode reads the next AMQP value from the Reader and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the conversion of AMQP into a Go value.
+//
+func (d *Decoder) Decode(v interface{}) (err error) {
+ defer doRecover(&err)
+ data := C.pn_data(0)
+ defer C.pn_data_free(data)
+ var n int
+ for n == 0 && err == nil {
+ n = unmarshal(data, d.buffer.Bytes(), v)
+ if n == 0 { // n == 0 means not enough data, read more
+ err = d.more()
+ if err != nil {
+ return
+ }
+ }
+ }
+ d.buffer.Next(n)
+ return
+}
+
+/*
+Unmarshal decodes AMQP-encoded bytes and stores the result in the value pointed to by v.
+Types are converted as follows:
+
+ +---------------------------+----------------------------------------------------------------------+
+ |To Go types |From AMQP types |
+ +===========================+======================================================================+
+ |bool |bool |
+ +---------------------------+----------------------------------------------------------------------+
+ |int, int8, int16, |Equivalent or smaller signed integer type: char, byte, short, int, |
+ |int32, int64 |long. |
+ +---------------------------+----------------------------------------------------------------------+
+ |uint, uint8, uint16, |Equivalent or smaller unsigned integer type: char, ubyte, ushort, |
+ |uint32, uint64 types |uint, ulong |
+ +---------------------------+----------------------------------------------------------------------+
+ |float32, float64 |Equivalent or smaller float or double. |
+ +---------------------------+----------------------------------------------------------------------+
+ |string, []byte |string, symbol or binary. |
+ +---------------------------+----------------------------------------------------------------------+
+ |map[K]T |map, provided all keys and values can unmarshal to types K, T |
+ +---------------------------+----------------------------------------------------------------------+
+ |Map|map, any AMQP map |
+ +---------------------------+----------------------------------------------------------------------+
+ |interface{} |Any AMQP value can be unmarshaled to an interface{} as follows: |
+ | +------------------------+---------------------------------------------+
+ | |AMQP Type |Go Type in interface{} |
+ | +========================+=============================================+
+ | |bool |bool |
+ | +------------------------+---------------------------------------------+
+ | |char |unint8 |
+ | +------------------------+---------------------------------------------+
+ | |byte,short,int,long |int8,int16,int32,int64 |
+ | +------------------------+---------------------------------------------+
+ | |ubyte,ushort,uint,ulong |uint8,uint16,uint32,uint64 |
+ | +------------------------+---------------------------------------------+
+ | |float, double |float32, float64 |
+ | +------------------------+---------------------------------------------+
+ | |string, symbol |string |
+ | +------------------------+---------------------------------------------+
+ | |binary |byte[] |
+ | +------------------------+---------------------------------------------+
+ | |map |Map |
+ | +------------------------+---------------------------------------------+
+ | |list |List |
+ +---------------------------+------------------------+---------------------------------------------+
+
+The following Go types cannot be unmarshaled: complex64/128, uintptr, function, interface, channel.
+
+TODO types
+
+AMQP: null, timestamp, decimal32/64/128, uuid, described, array.
+
+Go: array, struct.
+
+*/
+func Unmarshal(bytes []byte, v interface{}) (n int, err error) {
+ defer doRecover(&err)
+ data := C.pn_data(0)
+ defer C.pn_data_free(data)
+ n = unmarshal(data, bytes, v)
+ if n == 0 {
+ err = errorf("not enough data")
+ }
+ return
+}
+
+// more reads more data when we can't parse a complete AMQP type
+func (d *Decoder) more() error {
+ var readSize int64 = minDecode
+ if int64(d.buffer.Len()) > readSize { // Grow by doubling
+ readSize = int64(d.buffer.Len())
+ }
+ var n int64
+ n, err := d.buffer.ReadFrom(io.LimitReader(d.reader, readSize))
+ if n == 0 && err == nil { // ReadFrom won't report io.EOF, just returns 0
+ err = io.EOF
+ }
+ return err
+}
+
+// unmarshal decodes from bytes and converts into the value pointed to by v.
+// Used by Unmarshal and Decode
+//
+// Returns the number of bytes decoded or 0 if not enough data.
+//
+func unmarshal(data *C.pn_data_t, bytes []byte, v interface{}) (n int) {
+ n = decode(data, bytes)
+ if n == 0 {
+ return 0
+ }
+ get(data, v)
+ return
+}
+
+// Get value v from data
+func get(data *C.pn_data_t, v interface{}) {
+
+ pnType := C.pn_data_type(data)
+
+ switch v := v.(type) {
+ case *bool:
+ switch pnType {
+ case C.PN_BOOL:
+ *v = bool(C.pn_data_get_bool(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+ case *int8:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int8(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int8(C.pn_data_get_byte(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+ case *uint8:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint8(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint8(C.pn_data_get_ubyte(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+ case *int16:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int16(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int16(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int16(C.pn_data_get_short(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+ case *uint16:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint16(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint16(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint16(C.pn_data_get_ushort(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+ case *int32:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int32(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int32(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int32(C.pn_data_get_short(data))
+ case C.PN_INT:
+ *v = int32(C.pn_data_get_int(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+ case *uint32:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint32(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint32(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint32(C.pn_data_get_ushort(data))
+ case C.PN_UINT:
+ *v = uint32(C.pn_data_get_uint(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *int64:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int64(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int64(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int64(C.pn_data_get_short(data))
+ case C.PN_INT:
+ *v = int64(C.pn_data_get_int(data))
+ case C.PN_LONG:
+ *v = int64(C.pn_data_get_long(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *uint64:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint64(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint64(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint64(C.pn_data_get_ushort(data))
+ case C.PN_ULONG:
+ *v = uint64(C.pn_data_get_ulong(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *int:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int(C.pn_data_get_short(data))
+ case C.PN_INT:
+ *v = int(C.pn_data_get_int(data))
+ case C.PN_LONG:
+ if unsafe.Sizeof(0) == 8 {
+ *v = int(C.pn_data_get_long(data))
+ } else {
+ panic(newBadUnmarshal(pnType, v))
+ }
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *uint:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint(C.pn_data_get_ushort(data))
+ case C.PN_UINT:
+ *v = uint(C.pn_data_get_uint(data))
+ case C.PN_ULONG:
+ if unsafe.Sizeof(0) == 8 {
+ *v = uint(C.pn_data_get_ulong(data))
+ } else {
+ panic(newBadUnmarshal(pnType, v))
+ }
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *float32:
+ switch pnType {
+ case C.PN_FLOAT:
+ *v = float32(C.pn_data_get_float(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *float64:
+ switch pnType {
+ case C.PN_FLOAT:
+ *v = float64(C.pn_data_get_float(data))
+ case C.PN_DOUBLE:
+ *v = float64(C.pn_data_get_double(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *string:
+ switch pnType {
+ case C.PN_STRING:
+ *v = goString(C.pn_data_get_string(data))
+ case C.PN_SYMBOL:
+ *v = goString(C.pn_data_get_symbol(data))
+ case C.PN_BINARY:
+ *v = goString(C.pn_data_get_binary(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *[]byte:
+ switch pnType {
+ case C.PN_STRING:
+ *v = goBytes(C.pn_data_get_string(data))
+ case C.PN_SYMBOL:
+ *v = goBytes(C.pn_data_get_symbol(data))
+ case C.PN_BINARY:
+ *v = goBytes(C.pn_data_get_binary(data))
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+
+ case *interface{}:
+ getInterface(data, v)
+
+ default:
+ if reflect.TypeOf(v).Kind() != reflect.Ptr {
+ panic(newBadUnmarshal(pnType, v))
+ }
+ switch reflect.TypeOf(v).Elem().Kind() {
+ case reflect.Map:
+ getMap(data, v)
+ case reflect.Slice:
+ getList(data, v)
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+ }
+ err := pnDataError(data)
+ if err != "" {
+ panic(errorf("unmarshal %s", err))
+ }
+ return
+}
+
+// Getting into an interface is driven completely by the AMQP type, since the interface{}
+// target is type-neutral.
+func getInterface(data *C.pn_data_t, v *interface{}) {
+ pnType := C.pn_data_type(data)
+ switch pnType {
+ case C.PN_BOOL:
+ *v = bool(C.pn_data_get_bool(data))
+ case C.PN_UBYTE:
+ *v = uint8(C.pn_data_get_ubyte(data))
+ case C.PN_BYTE:
+ *v = int8(C.pn_data_get_byte(data))
+ case C.PN_USHORT:
+ *v = uint16(C.pn_data_get_ushort(data))
+ case C.PN_SHORT:
+ *v = int16(C.pn_data_get_short(data))
+ case C.PN_UINT:
+ *v = uint32(C.pn_data_get_uint(data))
+ case C.PN_INT:
+ *v = int32(C.pn_data_get_int(data))
+ case C.PN_CHAR:
+ *v = uint8(C.pn_data_get_char(data))
+ case C.PN_ULONG:
+ *v = uint64(C.pn_data_get_ulong(data))
+ case C.PN_LONG:
+ *v = int64(C.pn_data_get_long(data))
+ case C.PN_FLOAT:
+ *v = float32(C.pn_data_get_float(data))
+ case C.PN_DOUBLE:
+ *v = float64(C.pn_data_get_double(data))
+ case C.PN_BINARY:
+ *v = goBytes(C.pn_data_get_binary(data))
+ case C.PN_STRING:
+ *v = goString(C.pn_data_get_string(data))
+ case C.PN_SYMBOL:
+ *v = goString(C.pn_data_get_symbol(data))
+ case C.PN_MAP:
+ m := make(Map)
+ get(data, &m)
+ *v = m // FIXME aconway 2015-03-13: avoid the copy?
+ case C.PN_LIST:
+ l := make(List, 0)
+ get(data, &l)
+ *v = l
+ default:
+ panic(newBadUnmarshal(pnType, v))
+ }
+}
+
+func getMap(data *C.pn_data_t, v interface{}) {
+ pnType := C.pn_data_type(data)
+ if pnType != C.PN_MAP {
+ panic(newBadUnmarshal(pnType, v))
+ }
+ mapValue := reflect.ValueOf(v).Elem()
+ mapValue.Set(reflect.MakeMap(mapValue.Type())) // Clear the map
+ count := int(C.pn_data_get_map(data))
+ if bool(C.pn_data_enter(data)) {
+ for i := 0; i < count/2; i++ {
+ if bool(C.pn_data_next(data)) {
+ key := reflect.New(mapValue.Type().Key())
+ get(data, key.Interface())
+ if bool(C.pn_data_next(data)) {
+ val := reflect.New(mapValue.Type().Elem())
+ get(data, val.Interface())
+ mapValue.SetMapIndex(key.Elem(), val.Elem())
+ }
+ }
+ }
+ C.pn_data_exit(data)
+ }
+}
+
+func getList(data *C.pn_data_t, v interface{}) {
+ pnType := C.pn_data_type(data)
+ if pnType != C.PN_LIST {
+ panic(newBadUnmarshal(pnType, v))
+ }
+ count := int(C.pn_data_get_list(data))
+ listValue := reflect.MakeSlice(reflect.TypeOf(v).Elem(), count, count)
+ if bool(C.pn_data_enter(data)) {
+ for i := 0; i < count; i++ {
+ if bool(C.pn_data_next(data)) {
+ val := reflect.New(listValue.Type().Elem())
+ get(data, val.Interface())
+ listValue.Index(i).Set(val.Elem())
+ }
+ }
+ C.pn_data_exit(data)
+ }
+ reflect.ValueOf(v).Elem().Set(listValue)
+}
+
+// decode from bytes.
+// Return bytes decoded or 0 if we could not decode a complete object.
+//
+func decode(data *C.pn_data_t, bytes []byte) int {
+ if len(bytes) == 0 {
+ return 0
+ }
+ cBuf := (*C.char)(unsafe.Pointer(&bytes[0]))
+ n := int(C.pn_data_decode(data, cBuf, C.size_t(len(bytes))))
+ if n == int(C.PN_EOS) {
+ return 0
+ } else if n <= 0 {
+ panic(errorf("unmarshal %s", pnErrorName(n)))
+ }
+ return n
+}
+
+func goBytes(cBytes C.pn_bytes_t) (bytes []byte) {
+ if cBytes.start != nil {
+ bytes = C.GoBytes(unsafe.Pointer(cBytes.start), C.int(cBytes.size))
+ }
+ return
+}
+
+func goString(cBytes C.pn_bytes_t) (str string) {
+ if cBytes.start != nil {
+ str = C.GoStringN(cBytes.start, C.int(cBytes.size))
+ }
+ return
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/url.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/url.go b/proton-c/bindings/go/src/qpid.apache.org/proton/url.go
new file mode 100644
index 0000000..079dfb2
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/url.go
@@ -0,0 +1,96 @@
+/*
+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 proton
+
+/*
+#cgo LDFLAGS: -lqpid-proton
+#include <stdlib.h>
+#include <string.h>
+#include <proton/url.h>
+
+// Helper function for setting URL fields.
+typedef void (*setter_fn)(pn_url_t* url, const char* value);
+inline void set(pn_url_t *url, setter_fn s, const char* value) {
+ s(url, value);
+}
+*/
+import "C"
+
+import (
+ "net"
+ "net/url"
+ "unsafe"
+)
+
+const (
+ amqp string = "amqp"
+ amqps = "amqps"
+)
+
+// ParseUrl parses an AMQP URL string and returns a net/url.Url.
+//
+// It is more forgiving than net/url.Parse and allows most of the parts of the
+// URL to be missing, assuming AMQP defaults.
+//
+func ParseURL(s string) (u *url.URL, err error) {
+ cstr := C.CString(s)
+ defer C.free(unsafe.Pointer(cstr))
+ pnUrl := C.pn_url_parse(cstr)
+ if pnUrl == nil {
+ return nil, errorf("bad URL %#v", s)
+ }
+ defer C.pn_url_free(pnUrl)
+
+ scheme := C.GoString(C.pn_url_get_scheme(pnUrl))
+ username := C.GoString(C.pn_url_get_username(pnUrl))
+ password := C.GoString(C.pn_url_get_password(pnUrl))
+ host := C.GoString(C.pn_url_get_host(pnUrl))
+ port := C.GoString(C.pn_url_get_port(pnUrl))
+ path := C.GoString(C.pn_url_get_path(pnUrl))
+
+ if err != nil {
+ return nil, errorf("bad URL %#v: %s", s, err)
+ }
+ if scheme == "" {
+ scheme = amqp
+ }
+ if port == "" {
+ if scheme == amqps {
+ port = amqps
+ } else {
+ port = amqp
+ }
+ }
+ var user *url.Userinfo
+ if password != "" {
+ user = url.UserPassword(username, password)
+ } else if username != "" {
+ user = url.User(username)
+ }
+
+ u = &url.URL{
+ Scheme: scheme,
+ User: user,
+ Host: net.JoinHostPort(host, port),
+ Path: path,
+ }
+
+ return u, nil
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/url_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/url_test.go b/proton-c/bindings/go/src/qpid.apache.org/proton/url_test.go
new file mode 100644
index 0000000..7315511
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/url_test.go
@@ -0,0 +1,51 @@
+/*
+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 proton
+
+import (
+ "fmt"
+)
+
+func ExampleParseURL() {
+ for _, s := range []string{
+ "amqp://username:password@host:1234/path",
+ "host:1234",
+ "host",
+ ":1234",
+ "host/path",
+ "amqps://host",
+ "",
+ } {
+ u, err := ParseURL(s)
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Println(u)
+ }
+ }
+ // Output:
+ // amqp://username:password@host:1234/path
+ // amqp://host:1234
+ // amqp://host:amqp
+ // amqp://:1234
+ // amqp://host:amqp/path
+ // amqps://host:amqps
+ // proton: bad URL ""
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[2/2] qpid-proton git commit: PROTON-827: go binding - send.go,
listen.go examples with implementation stubs.
Posted by ac...@apache.org.
PROTON-827: go binding - send.go, listen.go examples with implementation stubs.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/695f8e5b
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/695f8e5b
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/695f8e5b
Branch: refs/heads/master
Commit: 695f8e5b96c75640bcf10fb12252a0130b70d0a0
Parents: faf925c
Author: Alan Conway <ac...@redhat.com>
Authored: Fri Mar 13 15:36:44 2015 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Fri Mar 13 17:35:10 2015 -0400
----------------------------------------------------------------------
examples/go/README.md | 17 +
examples/go/listen.go | 64 +++
examples/go/send.go | 77 +++
proton-c/bindings/go/README.md | 3 +-
.../bindings/go/src/apache.org/proton/doc.go | 33 --
.../bindings/go/src/apache.org/proton/error.go | 96 ----
.../go/src/apache.org/proton/interop_test.go | 290 -----------
.../go/src/apache.org/proton/marshal.go | 206 --------
.../bindings/go/src/apache.org/proton/types.go | 137 -----
.../go/src/apache.org/proton/unmarshal.go | 515 ------------------
.../bindings/go/src/apache.org/proton/url.go | 96 ----
.../go/src/apache.org/proton/url_test.go | 51 --
.../go/src/qpid.apache.org/proton/doc.go | 33 ++
.../go/src/qpid.apache.org/proton/error.go | 96 ++++
.../src/qpid.apache.org/proton/interop_test.go | 290 +++++++++++
.../go/src/qpid.apache.org/proton/marshal.go | 210 ++++++++
.../go/src/qpid.apache.org/proton/types.go | 151 ++++++
.../go/src/qpid.apache.org/proton/unfinished.go | 53 ++
.../go/src/qpid.apache.org/proton/unmarshal.go | 517 +++++++++++++++++++
.../go/src/qpid.apache.org/proton/url.go | 96 ++++
.../go/src/qpid.apache.org/proton/url_test.go | 51 ++
21 files changed, 1656 insertions(+), 1426 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/examples/go/README.md
----------------------------------------------------------------------
diff --git a/examples/go/README.md b/examples/go/README.md
new file mode 100644
index 0000000..0d86a62
--- /dev/null
+++ b/examples/go/README.md
@@ -0,0 +1,17 @@
+# *EXPERIMENTAL* Go examples for proton.
+
+See ../../proton-c/bindings/go/README.md
+
+These are sketches of examples for the experimental Go binding.
+
+They don't have sufficient error handling.
+
+They compile and run but do nothing as the binding implementation is just stubs right now.
+
+- listen.go: listens on a port, prints any messages it receives.
+- send.go: sends command-line arguments as messages with string bodies.
+
+You can use the two together, e.g. to listen/send on port 1234:
+
+go run listen.go -addr :1234
+go run send.go -addr :1234 foo bar
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/examples/go/listen.go
----------------------------------------------------------------------
diff --git a/examples/go/listen.go b/examples/go/listen.go
new file mode 100644
index 0000000..95285dd
--- /dev/null
+++ b/examples/go/listen.go
@@ -0,0 +1,64 @@
+/*
+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 main
+
+import (
+ "flag"
+ "fmt"
+ "net"
+ "os"
+ "qpid.apache.org/proton"
+)
+
+// A message handler type
+type Receiver struct{}
+
+// OnMessage is called when an AMQP message is received.
+func (r *Receiver) OnMessage(e *proton.Event) {
+ fmt.Printf("%#v\n", e.Message)
+}
+
+var addr = flag.String("addr", ":amqp", "Listening address, e.g. localhost:1234")
+
+func main() {
+ flag.Usage = func() {
+ fmt.Fprintln(os.Stderr, "Listen for AMQP messages and print them to stdout until killed.")
+ flag.PrintDefaults()
+ }
+ flag.Parse()
+
+ // Listen for and accept connections using the standard Go net package.
+ listener, err := net.Listen("tcp", *addr)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Listen error: %s\n", err)
+ os.Exit(1)
+ }
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Accept error: %s\n", err)
+ continue
+ }
+ fmt.Printf("Accepted connection %s<-%s\n", conn.LocalAddr(), conn.RemoteAddr())
+ // Run processes an AMQP connection and invokes the supplied handler.
+ // In this case it will call (*Receiver) OnMessage when a message is received.
+ go proton.Run(conn, &Receiver{})
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/examples/go/send.go
----------------------------------------------------------------------
diff --git a/examples/go/send.go b/examples/go/send.go
new file mode 100644
index 0000000..13d749d
--- /dev/null
+++ b/examples/go/send.go
@@ -0,0 +1,77 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "net"
+ "os"
+ "qpid.apache.org/proton"
+)
+
+// A message handler type
+type Sender struct {
+ Messages []string
+ Sent, Accepted int
+ Sender *proton.Sender
+}
+
+// Called when proton.Run is first called on a connection.
+func (s *Sender) OnStart(e *proton.Event) {
+ // Create a sender
+ // FIXME aconway 2015-03-13: Creating sendders on other connections?
+ s.Sender = e.Connection().NewSender("sender")
+}
+
+// Called when a sender has credit to send messages. Send all of flag.Args()
+func (s *Sender) OnSendable(e *proton.Event) {
+ for e.Sender().Credit() > 0 && s.Sent < len(flag.Args()) {
+ // FIXME aconway 2015-03-13: error handling
+ e.Sender().Send(&proton.Message{Body: s.Messages[s.Sent]})
+ s.Sent++
+ }
+}
+
+func (s *Sender) OnAccepted(e *proton.Event) {
+ s.Accepted++
+ if s.Accepted == len(flag.Args()) {
+ e.Connection().Close()
+ }
+}
+
+var addr = flag.String("addr", ":amqp", "Listening address, e.g. localhost:1234")
+
+func main() {
+ flag.Usage = func() {
+ fmt.Fprintln(os.Stderr, "Send AMQP messages with string bodies, one for each argument.")
+ flag.PrintDefaults()
+ }
+ flag.Parse()
+
+ conn, err := net.Dial("tcp", *addr)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Dial error: %s\n", err)
+ os.Exit(1)
+ }
+ // Run processes an AMQP connection and invokes the supplied handler.
+ // In this case it will call OnStart.
+ proton.Run(conn, &Sender{Messages: flag.Args()})
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/README.md
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/README.md b/proton-c/bindings/go/README.md
index 8ffa700..8f31b54 100644
--- a/proton-c/bindings/go/README.md
+++ b/proton-c/bindings/go/README.md
@@ -35,8 +35,7 @@ cross-language developers but idiomatic Go is the overriding consideration.
## Status
-So just a simple Go `Url` type using `pn_url_t`. This establishes the basics of
-using cgo to call into proton code.
+Marshal and unmarshal most of the AMQP types (TODO: described, array)
## Layout
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/doc.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/doc.go b/proton-c/bindings/go/src/apache.org/proton/doc.go
deleted file mode 100644
index 34f85fe..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/doc.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-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 proton is a Go binding for the proton AMQP protocol engine.
-
-It alows you to construct and parse AMQP messages, and to implement AMQP
-clients, servers and intermediaries that can exchange messages with any
-AMQP 1.0 compliant endpoint.
-
-Encoding and decoding AMQP data follows the pattern of the standard
-encoding/json and encoding/xml packages.The mapping between AMQP and Go types is
-described in the documentation of the Marshal and Unmarshal functions.
-*/
-package proton
-
-// This file is just for the package comment.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/error.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/error.go b/proton-c/bindings/go/src/apache.org/proton/error.go
deleted file mode 100644
index f9cc948..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/error.go
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-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 proton
-
-// #include <proton/error.h>
-// #include <proton/codec.h>
-import "C"
-
-import (
- "fmt"
- "reflect"
- "runtime"
-)
-
-var pnErrorNames = map[int]string{
- C.PN_EOS: "end of data",
- C.PN_ERR: "error",
- C.PN_OVERFLOW: "overflow",
- C.PN_UNDERFLOW: "underflow",
- C.PN_STATE_ERR: "bad state",
- C.PN_ARG_ERR: "invalid argument",
- C.PN_TIMEOUT: "timeout",
- C.PN_INTR: "interrupted",
- C.PN_INPROGRESS: "in progress",
-}
-
-func pnErrorName(code int) string {
- name := pnErrorNames[code]
- if name != "" {
- return name
- } else {
- return "unknown error code"
- }
-}
-
-type BadUnmarshal struct {
- AMQPType C.pn_type_t
- GoType reflect.Type
-}
-
-func newBadUnmarshal(pnType C.pn_type_t, v interface{}) *BadUnmarshal {
- return &BadUnmarshal{pnType, reflect.TypeOf(v)}
-}
-
-func (e BadUnmarshal) Error() string {
- if e.GoType.Kind() != reflect.Ptr {
- return fmt.Sprintf("proton: cannot unmarshal to type %s, not a pointer", e.GoType)
- } else {
- return fmt.Sprintf("proton: cannot unmarshal AMQP %s to %s", getPnType(e.AMQPType), e.GoType)
- }
-}
-
-// errorf creates an error with a formatted message
-func errorf(format string, a ...interface{}) error {
- return fmt.Errorf("proton: %s", fmt.Sprintf(format, a...))
-}
-
-func pnDataError(data *C.pn_data_t) string {
- err := C.pn_data_error(data)
- if err != nil && int(C.pn_error_code(err)) != 0 {
- return C.GoString(C.pn_error_text(err))
- }
- return ""
-}
-
-// doRecover is called to recover from internal panics
-func doRecover(err *error) {
- r := recover()
- switch r := r.(type) {
- case nil:
- return
- case runtime.Error:
- panic(r)
- case error:
- *err = r
- default:
- panic(r)
- }
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/interop_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/interop_test.go b/proton-c/bindings/go/src/apache.org/proton/interop_test.go
deleted file mode 100644
index c51d74a..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/interop_test.go
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
-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.
-*/
-
-// Test that conversion of Go type to/from AMQP is compatible with other
-// bindings.
-//
-package proton
-
-import (
- "bytes"
- "io"
- "io/ioutil"
- "os"
- "reflect"
- "strings"
- "testing"
-)
-
-func assertEqual(want interface{}, got interface{}) {
- if !reflect.DeepEqual(want, got) {
- panic(errorf("%#v != %#v", want, got))
- }
-}
-
-func assertNil(err interface{}) {
- if err != nil {
- panic(err)
- }
-}
-
-func getReader(name string) (r io.Reader) {
- r, err := os.Open("../../../../../../tests/interop/" + name + ".amqp")
- if err != nil {
- panic(errorf("Can't open %#v: %v", name, err))
- }
- return
-}
-
-func remaining(d *Decoder) string {
- remainder, _ := ioutil.ReadAll(io.MultiReader(d.Buffered(), d.reader))
- return string(remainder)
-}
-
-// assertDecode: want is the expected value, gotPtr is a pointer to a
-// instance of the same type for Decode.
-func assertDecode(d *Decoder, want interface{}, gotPtr interface{}) {
-
- assertNil(d.Decode(gotPtr))
-
- got := reflect.ValueOf(gotPtr).Elem().Interface()
- assertEqual(want, got)
-
- // Try round trip encoding
- bytes, err := Marshal(want)
- assertNil(err)
- n, err := Unmarshal(bytes, gotPtr)
- assertNil(err)
- assertEqual(n, len(bytes))
- got = reflect.ValueOf(gotPtr).Elem().Interface()
- assertEqual(want, got)
-}
-
-func TestUnmarshal(t *testing.T) {
- bytes, err := ioutil.ReadAll(getReader("strings"))
- if err != nil {
- t.Error(err)
- }
- for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} {
- var got string
- n, err := Unmarshal(bytes, &got)
- if err != nil {
- t.Error(err)
- }
- if want != got {
- t.Errorf("%#v != %#v", want, got)
- }
- bytes = bytes[n:]
- }
-}
-
-func TestPrimitivesExact(t *testing.T) {
- d := NewDecoder(getReader("primitives"))
- // Decoding into exact types
- var b bool
- assertDecode(d, true, &b)
- assertDecode(d, false, &b)
- var u8 uint8
- assertDecode(d, uint8(42), &u8)
- var u16 uint16
- assertDecode(d, uint16(42), &u16)
- var i16 int16
- assertDecode(d, int16(-42), &i16)
- var u32 uint32
- assertDecode(d, uint32(12345), &u32)
- var i32 int32
- assertDecode(d, int32(-12345), &i32)
- var u64 uint64
- assertDecode(d, uint64(12345), &u64)
- var i64 int64
- assertDecode(d, int64(-12345), &i64)
- var f32 float32
- assertDecode(d, float32(0.125), &f32)
- var f64 float64
- assertDecode(d, float64(0.125), &f64)
-}
-
-func TestPrimitivesCompatible(t *testing.T) {
- d := NewDecoder(getReader("primitives"))
- // Decoding into compatible types
- var b bool
- var i int
- var u uint
- var f float64
- assertDecode(d, true, &b)
- assertDecode(d, false, &b)
- assertDecode(d, uint(42), &u)
- assertDecode(d, uint(42), &u)
- assertDecode(d, -42, &i)
- assertDecode(d, uint(12345), &u)
- assertDecode(d, -12345, &i)
- assertDecode(d, uint(12345), &u)
- assertDecode(d, -12345, &i)
- assertDecode(d, 0.125, &f)
- assertDecode(d, 0.125, &f)
-}
-
-// assertDecodeValue: want is the expected value, decode into a reflect.Value
-func assertDecodeInterface(d *Decoder, want interface{}) {
-
- var got, got2 interface{}
- assertNil(d.Decode(&got))
-
- assertEqual(want, got)
-
- // Try round trip encoding
- bytes, err := Marshal(got)
- assertNil(err)
- n, err := Unmarshal(bytes, &got2)
- assertNil(err)
- assertEqual(n, len(bytes))
- assertEqual(want, got2)
-}
-
-func TestPrimitivesInterface(t *testing.T) {
- d := NewDecoder(getReader("primitives"))
- assertDecodeInterface(d, true)
- assertDecodeInterface(d, false)
- assertDecodeInterface(d, uint8(42))
- assertDecodeInterface(d, uint16(42))
- assertDecodeInterface(d, int16(-42))
- assertDecodeInterface(d, uint32(12345))
- assertDecodeInterface(d, int32(-12345))
- assertDecodeInterface(d, uint64(12345))
- assertDecodeInterface(d, int64(-12345))
- assertDecodeInterface(d, float32(0.125))
- assertDecodeInterface(d, float64(0.125))
-}
-
-func TestStrings(t *testing.T) {
- d := NewDecoder(getReader("strings"))
- // Test decoding as plain Go strings
- for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} {
- var got string
- assertDecode(d, want, &got)
- }
- remains := remaining(d)
- if remains != "" {
- t.Errorf("leftover: %s", remains)
- }
-
- // Test decoding as specific string types
- d = NewDecoder(getReader("strings"))
- var bytes []byte
- var str, sym string
- assertDecode(d, []byte("abc\000defg"), &bytes)
- assertDecode(d, "abcdefg", &str)
- assertDecode(d, "abcdefg", &sym)
- assertDecode(d, make([]byte, 0), &bytes)
- assertDecode(d, "", &str)
- assertDecode(d, "", &sym)
- remains = remaining(d)
- if remains != "" {
- panic(errorf("leftover: %s", remains))
- }
-
- // Test some error handling
- d = NewDecoder(getReader("strings"))
- var s string
- err := d.Decode(s)
- if err == nil {
- t.Fatal("Expected error")
- }
- if !strings.Contains(err.Error(), "not a pointer") {
- t.Error(err)
- }
- var i int
- err = d.Decode(&i)
- if !strings.Contains(err.Error(), "cannot unmarshal") {
- t.Error(err)
- }
- _, err = Unmarshal([]byte{}, nil)
- if !strings.Contains(err.Error(), "not enough data") {
- t.Error(err)
- }
- _, err = Unmarshal([]byte("foobar"), nil)
- if !strings.Contains(err.Error(), "invalid argument") {
- t.Error(err)
- }
-}
-
-func TestEncodeDecode(t *testing.T) {
- type data struct {
- s string
- i int
- u8 uint8
- b bool
- f float32
- v interface{}
- }
-
- in := data{"foo", 42, 9, true, 1.234, "thing"}
-
- buf := bytes.Buffer{}
- e := NewEncoder(&buf)
- e.Encode(in.s)
- e.Encode(in.i)
- e.Encode(in.u8)
- e.Encode(in.b)
- e.Encode(in.f)
- e.Encode(in.v)
-
- var out data
- d := NewDecoder(&buf)
- d.Decode(&out.s)
- d.Decode(&out.i)
- d.Decode(&out.u8)
- d.Decode(&out.b)
- d.Decode(&out.f)
- d.Decode(&out.v)
-
- assertEqual(in, out)
-}
-
-func TestMap(t *testing.T) {
- d := NewDecoder(getReader("maps"))
-
- // Generic map
- var m Map
- assertDecode(d, Map{"one": int32(1), "two": int32(2), "three": int32(3)}, &m)
-
- // Interface as map
- var i interface{}
- assertDecode(d, Map{int32(1): "one", int32(2): "two", int32(3): "three"}, &i)
-
- d = NewDecoder(getReader("maps"))
- // Specific typed map
- var m2 map[string]int
- assertDecode(d, map[string]int{"one": 1, "two": 2, "three": 3}, &m2)
-
- // Round trip a nested map
- m = Map{int64(1): "one", "two": int32(2), true: Map{uint8(1): true, uint8(2): false}}
- bytes, err := Marshal(m)
- assertNil(err)
- _, err = Unmarshal(bytes, &i)
- assertNil(err)
- assertEqual(m, i)
-}
-
-func TestList(t *testing.T) {
- d := NewDecoder(getReader("lists"))
- var l List
- assertDecode(d, List{int32(32), "foo", true}, &l)
- assertDecode(d, List{}, &l)
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/marshal.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/marshal.go b/proton-c/bindings/go/src/apache.org/proton/marshal.go
deleted file mode 100644
index 674a25f..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/marshal.go
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-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 proton
-
-// #include <proton/codec.h>
-import "C"
-
-import (
- "io"
- "reflect"
- "unsafe"
-)
-
-const minEncode = 256
-
-/*
-Marshal encodes a value as AMQP.
-
-Go types are encoded as follows
-
- +-------------------------------------+--------------------------------------------+
- |Go type |AMQP type |
- +-------------------------------------+--------------------------------------------+
- |bool |bool |
- +-------------------------------------+--------------------------------------------+
- |int8, int16, int32, int64 (int) |byte, short, int, long (int or long) |
- +-------------------------------------+--------------------------------------------+
- |uint8, uint16, uint32, uint64 (uint) |ubyte, ushort, uint, ulong (uint or ulong) |
- +-------------------------------------+--------------------------------------------+
- |float32, float64 |float, double. |
- +-------------------------------------+--------------------------------------------+
- |string |string |
- +-------------------------------------+--------------------------------------------+
- |[]byte |binary |
- +-------------------------------------+--------------------------------------------+
- |interface{} |as to the contained type |
- +-------------------------------------+--------------------------------------------+
- |map[K]T |map with K and T converted as above |
- +-------------------------------------+--------------------------------------------+
- |Map |map may have mixed types for keys and values|
- +-------------------------------------+--------------------------------------------+
-
-TODO types
-
-Go: array, slice, struct
-
-Go types that cannot be marshaled
-
-complex64/128, uintptr, function, interface, channel
-
-*/
-func Marshal(v interface{}) (bytes []byte, err error) {
- return marshal(make([]byte, minEncode), v)
-}
-
-func marshal(bytesIn []byte, v interface{}) (bytes []byte, err error) {
- defer doRecover(&err)
- data := C.pn_data(0)
- defer C.pn_data_free(data)
- put(data, v)
- // FIXME aconway 2015-03-11: get size from proton.
- bytes = bytesIn
- for {
- n := int(C.pn_data_encode(data, (*C.char)(unsafe.Pointer(&bytes[0])), C.size_t(cap(bytes))))
- if n != int(C.PN_EOS) {
- if n < 0 {
- err = errorf(pnErrorName(n))
- } else {
- bytes = bytes[0:n]
- }
- return
- }
- bytes = make([]byte, cap(bytes)*2)
- }
- return
-}
-
-func put(data *C.pn_data_t, v interface{}) {
- switch v := v.(type) {
- case bool:
- C.pn_data_put_bool(data, C.bool(v))
- case int8:
- C.pn_data_put_byte(data, C.int8_t(v))
- case int16:
- C.pn_data_put_short(data, C.int16_t(v))
- case int32:
- C.pn_data_put_int(data, C.int32_t(v))
- case int64:
- C.pn_data_put_long(data, C.int64_t(v))
- case int:
- if unsafe.Sizeof(0) == 8 {
- C.pn_data_put_long(data, C.int64_t(v))
- } else {
- C.pn_data_put_int(data, C.int32_t(v))
- }
- case uint8:
- C.pn_data_put_ubyte(data, C.uint8_t(v))
- case uint16:
- C.pn_data_put_ushort(data, C.uint16_t(v))
- case uint32:
- C.pn_data_put_uint(data, C.uint32_t(v))
- case uint64:
- C.pn_data_put_ulong(data, C.uint64_t(v))
- case uint:
- if unsafe.Sizeof(0) == 8 {
- C.pn_data_put_ulong(data, C.uint64_t(v))
- } else {
- C.pn_data_put_uint(data, C.uint32_t(v))
- }
- case float32:
- C.pn_data_put_float(data, C.float(v))
- case float64:
- C.pn_data_put_double(data, C.double(v))
- case string:
- C.pn_data_put_string(data, toPnBytes([]byte(v)))
- case []byte:
- C.pn_data_put_binary(data, toPnBytes(v))
- case Map: // Special map type
- C.pn_data_put_map(data)
- C.pn_data_enter(data)
- for key, val := range v {
- put(data, key)
- put(data, val)
- }
- C.pn_data_exit(data)
- default:
- switch reflect.TypeOf(v).Kind() {
- case reflect.Map:
- putMap(data, v)
- case reflect.Slice:
- putList(data, v)
- default:
- panic(errorf("cannot marshal %s to AMQP", reflect.TypeOf(v)))
- }
- }
- err := pnDataError(data)
- if err != "" {
- panic(errorf("marshal %s", err))
- }
- return
-}
-
-func putMap(data *C.pn_data_t, v interface{}) {
- mapValue := reflect.ValueOf(v)
- C.pn_data_put_map(data)
- C.pn_data_enter(data)
- for _, key := range mapValue.MapKeys() {
- put(data, key.Interface())
- put(data, mapValue.MapIndex(key).Interface())
- }
- C.pn_data_exit(data)
-}
-
-func putList(data *C.pn_data_t, v interface{}) {
- listValue := reflect.ValueOf(v)
- C.pn_data_put_list(data)
- C.pn_data_enter(data)
- for i := 0; i < listValue.Len(); i++ {
- put(data, listValue.Index(i).Interface())
- }
- C.pn_data_exit(data)
-}
-
-// Encoder encodes AMQP values to an io.Writer
-type Encoder struct {
- writer io.Writer
- buffer []byte
-}
-
-// New encoder returns a new encoder that writes to w.
-func NewEncoder(w io.Writer) *Encoder {
- return &Encoder{w, make([]byte, minEncode)}
-}
-
-func (e *Encoder) Encode(v interface{}) (err error) {
- e.buffer, err = marshal(e.buffer, v)
- if err == nil {
- e.writer.Write(e.buffer)
- }
- return
-}
-
-func toPnBytes(b []byte) C.pn_bytes_t {
- if len(b) == 0 {
- return C.pn_bytes_t{0, nil}
- } else {
- return C.pn_bytes_t{C.size_t(len(b)), (*C.char)(unsafe.Pointer(&b[0]))}
- }
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/types.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/types.go b/proton-c/bindings/go/src/apache.org/proton/types.go
deleted file mode 100644
index f8c5560..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/types.go
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-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 proton
-
-// #include <proton/codec.h>
-import "C"
-
-import (
- "bytes"
- "fmt"
- "reflect"
-)
-
-type pnGet func(data *C.pn_data_t) reflect.Value
-type pnPut func(data *C.pn_data_t, v interface{})
-
-// Information about a proton type
-type pnType struct {
- code C.pn_type_t // AMQP type code
- name string // AMQP type name
-}
-
-func (pt *pnType) String() string { return pt.name }
-
-// pnType definitions for each proton type.
-var (
- pnNull = pnType{code: C.PN_NULL, name: "null"}
- pnBool = pnType{code: C.PN_BOOL, name: "bool"}
- pnUbyte = pnType{code: C.PN_UBYTE, name: "ubyte"}
- pnByte = pnType{code: C.PN_BYTE, name: "byte"}
- pnUshort = pnType{code: C.PN_USHORT, name: "ushort"}
- pnShort = pnType{code: C.PN_SHORT, name: "short"}
- pnChar = pnType{code: C.PN_CHAR, name: "char"}
- pnUint = pnType{code: C.PN_UINT, name: "uint"}
- pnInt = pnType{code: C.PN_INT, name: "int"}
- pnUlong = pnType{code: C.PN_ULONG, name: "ulong"}
- pnLong = pnType{code: C.PN_LONG, name: "long"}
- pnTimestamp = pnType{code: C.PN_TIMESTAMP, name: "timestamp"}
- pnFloat = pnType{code: C.PN_FLOAT, name: "float"}
- pnDouble = pnType{code: C.PN_DOUBLE, name: "double"}
- pnDecimal32 = pnType{code: C.PN_DECIMAL32, name: "decimal32"}
- pnDecimal64 = pnType{code: C.PN_DECIMAL64, name: "decimal64"}
- pnDecimal128 = pnType{code: C.PN_DECIMAL128, name: "decimal128"}
- pnUuid = pnType{code: C.PN_UUID, name: "uuid"}
- pnBinary = pnType{code: C.PN_BINARY, name: "binary"}
- pnString = pnType{code: C.PN_STRING, name: "string"}
- pnSymbol = pnType{code: C.PN_SYMBOL, name: "symbol"}
- pnDescribed = pnType{code: C.PN_DESCRIBED, name: "described"}
- pnArray = pnType{code: C.PN_ARRAY, name: "array"}
- pnList = pnType{code: C.PN_LIST, name: "list"}
- pnMap = pnType{code: C.PN_MAP, name: "map"}
-)
-
-// Map from pn_type_t codes to pnType structs
-var pnTypes = map[C.pn_type_t]*pnType{
- C.PN_NULL: &pnNull,
- C.PN_BOOL: &pnBool,
- C.PN_UBYTE: &pnUbyte,
- C.PN_BYTE: &pnByte,
- C.PN_USHORT: &pnUshort,
- C.PN_SHORT: &pnShort,
- C.PN_UINT: &pnUint,
- C.PN_INT: &pnInt,
- C.PN_CHAR: &pnChar,
- C.PN_ULONG: &pnUlong,
- C.PN_LONG: &pnLong,
- C.PN_TIMESTAMP: &pnTimestamp,
- C.PN_FLOAT: &pnFloat,
- C.PN_DOUBLE: &pnDouble,
- C.PN_DECIMAL32: &pnDecimal32,
- C.PN_DECIMAL64: &pnDecimal64,
- C.PN_DECIMAL128: &pnDecimal128,
- C.PN_UUID: &pnUuid,
- C.PN_BINARY: &pnBinary,
- C.PN_STRING: &pnString,
- C.PN_SYMBOL: &pnSymbol,
- C.PN_DESCRIBED: &pnDescribed,
- C.PN_ARRAY: &pnArray,
- C.PN_LIST: &pnList,
- C.PN_MAP: &pnMap,
-}
-
-// Get the pnType for a pn_type_t code, panic if unknown code.
-func getPnType(code C.pn_type_t) *pnType {
- pt, ok := pnTypes[code]
- if !ok {
- panic(errorf("unknown AMQP type code %v", code))
- }
- return pt
-}
-
-// Go types
-var (
- bytesType = reflect.TypeOf([]byte{})
- valueType = reflect.TypeOf(reflect.Value{})
-)
-
-// Map is a generic map that can have mixed key and value types and so can represent any AMQP map
-//
-type Map map[interface{}]interface{}
-
-// List is a generic list that can hold mixed values and can represent any AMQP list.
-//
-type List []interface{}
-
-// GoString for Map prints values with their types, useful for debugging.
-func (m Map) GoString() string {
- out := &bytes.Buffer{}
- fmt.Fprintf(out, "%s{", reflect.TypeOf(m))
- i := len(m)
- for k, v := range m {
- fmt.Fprintf(out, "%T(%#v): %T(%#v)", k, k, v, v)
- i--
- if i > 0 {
- fmt.Fprint(out, ", ")
- }
- }
- fmt.Fprint(out, "}")
- return out.String()
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/unmarshal.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/unmarshal.go b/proton-c/bindings/go/src/apache.org/proton/unmarshal.go
deleted file mode 100644
index a003019..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/unmarshal.go
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-oor 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 proton
-
-// #include <proton/codec.h>
-import "C"
-
-import (
- "bytes"
- "io"
- "reflect"
- "unsafe"
-)
-
-const minDecode = 256
-
-//
-// Decoding from a pn_data_t
-//
-// NOTE: we use panic() to signal a decoding error, simplifies decoding logic.
-// We recover() at the highest possible level - i.e. in the exported Unmarshal or Decode.
-//
-
-// Decoder decodes AMQP values from an io.Reader.
-//
-type Decoder struct {
- reader io.Reader
- buffer bytes.Buffer
-}
-
-// NewDecoder returns a new decoder that reads from r.
-//
-// The decoder has it's own buffer and may read more data than required for the
-// AMQP values requested. Use Buffered to see if there is data left in the
-// buffer.
-//
-func NewDecoder(r io.Reader) *Decoder {
- return &Decoder{r, bytes.Buffer{}}
-}
-
-// Buffered returns a reader of the data remaining in the Decoder's buffer. The
-// reader is valid until the next call to Decode.
-//
-func (d *Decoder) Buffered() io.Reader {
- return bytes.NewReader(d.buffer.Bytes())
-}
-
-// Decode reads the next AMQP value from the Reader and stores it in the value pointed to by v.
-//
-// See the documentation for Unmarshal for details about the conversion of AMQP into a Go value.
-//
-func (d *Decoder) Decode(v interface{}) (err error) {
- defer doRecover(&err)
- data := C.pn_data(0)
- defer C.pn_data_free(data)
- var n int
- for n == 0 && err == nil {
- n = unmarshal(data, d.buffer.Bytes(), v)
- if n == 0 { // n == 0 means not enough data, read more
- err = d.more()
- if err != nil {
- return
- }
- }
- }
- d.buffer.Next(n)
- return
-}
-
-/*
-Unmarshal decodes AMQP-encoded bytes and stores the result in the value pointed to by v.
-Types are converted as follows:
-
- +---------------------------+----------------------------------------------------------------------+
- |To Go types |From AMQP types |
- +===========================+======================================================================+
- |bool |bool |
- +---------------------------+----------------------------------------------------------------------+
- |int, int8, int16, |Equivalent or smaller signed integer type: char, byte, short, int, |
- |int32, int64 |long. |
- +---------------------------+----------------------------------------------------------------------+
- |uint, uint8, uint16, |Equivalent or smaller unsigned integer type: char, ubyte, ushort, |
- |uint32, uint64 types |uint, ulong |
- +---------------------------+----------------------------------------------------------------------+
- |float32, float64 |Equivalent or smaller float or double. |
- +---------------------------+----------------------------------------------------------------------+
- |string, []byte |string, symbol or binary. |
- +---------------------------+----------------------------------------------------------------------+
- |map[K]T |map, provided all keys and values can unmarshal to types K, T |
- +---------------------------+----------------------------------------------------------------------+
- |Map|map, any AMQP map |
- +---------------------------+----------------------------------------------------------------------+
- |interface{} |Any AMQP value can be unmarshaled to an interface{} as follows: |
- | +------------------------+---------------------------------------------+
- | |AMQP Type |Go Type in interface{} |
- | +========================+=============================================+
- | |bool |bool |
- | +------------------------+---------------------------------------------+
- | |char |unint8 |
- | +------------------------+---------------------------------------------+
- | |byte,short,int,long |int8,int16,int32,int64 |
- | +------------------------+---------------------------------------------+
- | |ubyte,ushort,uint,ulong |uint8,uint16,uint32,uint64 |
- | +------------------------+---------------------------------------------+
- | |float, double |float32, float64 |
- | +------------------------+---------------------------------------------+
- | |string, symbol |string |
- | +------------------------+---------------------------------------------+
- | |binary |byte[] |
- | +------------------------+---------------------------------------------+
- | |map |Map |
- +---------------------------+------------------------+---------------------------------------------+
-
-The following Go types cannot be unmarshaled: complex64/128, uintptr, function, interface, channel.
-
-ODO types
-
-AMQP: null, timestamp, decimal32/64/128, uuid, described, array, list.
-
-Go: array, slice, struct.
-
-*/
-func Unmarshal(bytes []byte, v interface{}) (n int, err error) {
- defer doRecover(&err)
- data := C.pn_data(0)
- defer C.pn_data_free(data)
- n = unmarshal(data, bytes, v)
- if n == 0 {
- err = errorf("not enough data")
- }
- return
-}
-
-// more reads more data when we can't parse a complete AMQP type
-func (d *Decoder) more() error {
- var readSize int64 = minDecode
- if int64(d.buffer.Len()) > readSize { // Grow by doubling
- readSize = int64(d.buffer.Len())
- }
- var n int64
- n, err := d.buffer.ReadFrom(io.LimitReader(d.reader, readSize))
- if n == 0 && err == nil { // ReadFrom won't report io.EOF, just returns 0
- err = io.EOF
- }
- return err
-}
-
-// unmarshal decodes from bytes and converts into the value pointed to by v.
-// Used by Unmarshal and Decode
-//
-// Returns the number of bytes decoded or 0 if not enough data.
-//
-func unmarshal(data *C.pn_data_t, bytes []byte, v interface{}) (n int) {
- n = decode(data, bytes)
- if n == 0 {
- return 0
- }
- get(data, v)
- return
-}
-
-// Get value v from data
-func get(data *C.pn_data_t, v interface{}) {
-
- pnType := C.pn_data_type(data)
-
- switch v := v.(type) {
- case *bool:
- switch pnType {
- case C.PN_BOOL:
- *v = bool(C.pn_data_get_bool(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
- case *int8:
- switch pnType {
- case C.PN_CHAR:
- *v = int8(C.pn_data_get_char(data))
- case C.PN_BYTE:
- *v = int8(C.pn_data_get_byte(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
- case *uint8:
- switch pnType {
- case C.PN_CHAR:
- *v = uint8(C.pn_data_get_char(data))
- case C.PN_UBYTE:
- *v = uint8(C.pn_data_get_ubyte(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
- case *int16:
- switch pnType {
- case C.PN_CHAR:
- *v = int16(C.pn_data_get_char(data))
- case C.PN_BYTE:
- *v = int16(C.pn_data_get_byte(data))
- case C.PN_SHORT:
- *v = int16(C.pn_data_get_short(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
- case *uint16:
- switch pnType {
- case C.PN_CHAR:
- *v = uint16(C.pn_data_get_char(data))
- case C.PN_UBYTE:
- *v = uint16(C.pn_data_get_ubyte(data))
- case C.PN_USHORT:
- *v = uint16(C.pn_data_get_ushort(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
- case *int32:
- switch pnType {
- case C.PN_CHAR:
- *v = int32(C.pn_data_get_char(data))
- case C.PN_BYTE:
- *v = int32(C.pn_data_get_byte(data))
- case C.PN_SHORT:
- *v = int32(C.pn_data_get_short(data))
- case C.PN_INT:
- *v = int32(C.pn_data_get_int(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
- case *uint32:
- switch pnType {
- case C.PN_CHAR:
- *v = uint32(C.pn_data_get_char(data))
- case C.PN_UBYTE:
- *v = uint32(C.pn_data_get_ubyte(data))
- case C.PN_USHORT:
- *v = uint32(C.pn_data_get_ushort(data))
- case C.PN_UINT:
- *v = uint32(C.pn_data_get_uint(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *int64:
- switch pnType {
- case C.PN_CHAR:
- *v = int64(C.pn_data_get_char(data))
- case C.PN_BYTE:
- *v = int64(C.pn_data_get_byte(data))
- case C.PN_SHORT:
- *v = int64(C.pn_data_get_short(data))
- case C.PN_INT:
- *v = int64(C.pn_data_get_int(data))
- case C.PN_LONG:
- *v = int64(C.pn_data_get_long(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *uint64:
- switch pnType {
- case C.PN_CHAR:
- *v = uint64(C.pn_data_get_char(data))
- case C.PN_UBYTE:
- *v = uint64(C.pn_data_get_ubyte(data))
- case C.PN_USHORT:
- *v = uint64(C.pn_data_get_ushort(data))
- case C.PN_ULONG:
- *v = uint64(C.pn_data_get_ulong(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *int:
- switch pnType {
- case C.PN_CHAR:
- *v = int(C.pn_data_get_char(data))
- case C.PN_BYTE:
- *v = int(C.pn_data_get_byte(data))
- case C.PN_SHORT:
- *v = int(C.pn_data_get_short(data))
- case C.PN_INT:
- *v = int(C.pn_data_get_int(data))
- case C.PN_LONG:
- if unsafe.Sizeof(0) == 8 {
- *v = int(C.pn_data_get_long(data))
- } else {
- panic(newBadUnmarshal(pnType, v))
- }
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *uint:
- switch pnType {
- case C.PN_CHAR:
- *v = uint(C.pn_data_get_char(data))
- case C.PN_UBYTE:
- *v = uint(C.pn_data_get_ubyte(data))
- case C.PN_USHORT:
- *v = uint(C.pn_data_get_ushort(data))
- case C.PN_UINT:
- *v = uint(C.pn_data_get_uint(data))
- case C.PN_ULONG:
- if unsafe.Sizeof(0) == 8 {
- *v = uint(C.pn_data_get_ulong(data))
- } else {
- panic(newBadUnmarshal(pnType, v))
- }
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *float32:
- switch pnType {
- case C.PN_FLOAT:
- *v = float32(C.pn_data_get_float(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *float64:
- switch pnType {
- case C.PN_FLOAT:
- *v = float64(C.pn_data_get_float(data))
- case C.PN_DOUBLE:
- *v = float64(C.pn_data_get_double(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *string:
- switch pnType {
- case C.PN_STRING:
- *v = goString(C.pn_data_get_string(data))
- case C.PN_SYMBOL:
- *v = goString(C.pn_data_get_symbol(data))
- case C.PN_BINARY:
- *v = goString(C.pn_data_get_binary(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *[]byte:
- switch pnType {
- case C.PN_STRING:
- *v = goBytes(C.pn_data_get_string(data))
- case C.PN_SYMBOL:
- *v = goBytes(C.pn_data_get_symbol(data))
- case C.PN_BINARY:
- *v = goBytes(C.pn_data_get_binary(data))
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-
- case *interface{}:
- getInterface(data, v)
-
- default:
- if reflect.TypeOf(v).Kind() != reflect.Ptr {
- panic(newBadUnmarshal(pnType, v))
- }
- switch reflect.TypeOf(v).Elem().Kind() {
- case reflect.Map:
- getMap(data, v)
- case reflect.Slice:
- getList(data, v)
- default:
- panic(newBadUnmarshal(pnType, v))
- }
- }
- err := pnDataError(data)
- if err != "" {
- panic(errorf("unmarshal %s", err))
- }
- return
-}
-
-// Getting into an interface is driven completely by the AMQP type, since the interface{}
-// target is type-neutral.
-func getInterface(data *C.pn_data_t, v *interface{}) {
- pnType := C.pn_data_type(data)
- switch pnType {
- case C.PN_BOOL:
- *v = bool(C.pn_data_get_bool(data))
- case C.PN_UBYTE:
- *v = uint8(C.pn_data_get_ubyte(data))
- case C.PN_BYTE:
- *v = int8(C.pn_data_get_byte(data))
- case C.PN_USHORT:
- *v = uint16(C.pn_data_get_ushort(data))
- case C.PN_SHORT:
- *v = int16(C.pn_data_get_short(data))
- case C.PN_UINT:
- *v = uint32(C.pn_data_get_uint(data))
- case C.PN_INT:
- *v = int32(C.pn_data_get_int(data))
- case C.PN_CHAR:
- *v = uint8(C.pn_data_get_char(data))
- case C.PN_ULONG:
- *v = uint64(C.pn_data_get_ulong(data))
- case C.PN_LONG:
- *v = int64(C.pn_data_get_long(data))
- case C.PN_FLOAT:
- *v = float32(C.pn_data_get_float(data))
- case C.PN_DOUBLE:
- *v = float64(C.pn_data_get_double(data))
- case C.PN_BINARY:
- *v = goBytes(C.pn_data_get_binary(data))
- case C.PN_STRING:
- *v = goString(C.pn_data_get_string(data))
- case C.PN_SYMBOL:
- *v = goString(C.pn_data_get_symbol(data))
- case C.PN_MAP:
- m := make(Map)
- get(data, &m)
- *v = m // FIXME aconway 2015-03-13: avoid the copy?
- case C.PN_LIST:
- l := make(List, 0)
- get(data, &l)
- *v = l
- default:
- panic(newBadUnmarshal(pnType, v))
- }
-}
-
-func getMap(data *C.pn_data_t, v interface{}) {
- pnType := C.pn_data_type(data)
- if pnType != C.PN_MAP {
- panic(newBadUnmarshal(pnType, v))
- }
- mapValue := reflect.ValueOf(v).Elem()
- mapValue.Set(reflect.MakeMap(mapValue.Type())) // Clear the map
- count := int(C.pn_data_get_map(data))
- if bool(C.pn_data_enter(data)) {
- for i := 0; i < count/2; i++ {
- if bool(C.pn_data_next(data)) {
- key := reflect.New(mapValue.Type().Key())
- get(data, key.Interface())
- if bool(C.pn_data_next(data)) {
- val := reflect.New(mapValue.Type().Elem())
- get(data, val.Interface())
- mapValue.SetMapIndex(key.Elem(), val.Elem())
- }
- }
- }
- C.pn_data_exit(data)
- }
-}
-
-func getList(data *C.pn_data_t, v interface{}) {
- pnType := C.pn_data_type(data)
- if pnType != C.PN_LIST {
- panic(newBadUnmarshal(pnType, v))
- }
- count := int(C.pn_data_get_list(data))
- listValue := reflect.MakeSlice(reflect.TypeOf(v).Elem(), count, count)
- if bool(C.pn_data_enter(data)) {
- for i := 0; i < count; i++ {
- if bool(C.pn_data_next(data)) {
- val := reflect.New(listValue.Type().Elem())
- get(data, val.Interface())
- listValue.Index(i).Set(val.Elem())
- }
- }
- C.pn_data_exit(data)
- }
- reflect.ValueOf(v).Elem().Set(listValue)
-}
-
-// decode from bytes.
-// Return bytes decoded or 0 if we could not decode a complete object.
-//
-func decode(data *C.pn_data_t, bytes []byte) int {
- if len(bytes) == 0 {
- return 0
- }
- cBuf := (*C.char)(unsafe.Pointer(&bytes[0]))
- n := int(C.pn_data_decode(data, cBuf, C.size_t(len(bytes))))
- if n == int(C.PN_EOS) {
- return 0
- } else if n <= 0 {
- panic(errorf("unmarshal %s", pnErrorName(n)))
- }
- return n
-}
-
-func goBytes(cBytes C.pn_bytes_t) (bytes []byte) {
- if cBytes.start != nil {
- bytes = C.GoBytes(unsafe.Pointer(cBytes.start), C.int(cBytes.size))
- }
- return
-}
-
-func goString(cBytes C.pn_bytes_t) (str string) {
- if cBytes.start != nil {
- str = C.GoStringN(cBytes.start, C.int(cBytes.size))
- }
- return
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/url.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/url.go b/proton-c/bindings/go/src/apache.org/proton/url.go
deleted file mode 100644
index 079dfb2..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/url.go
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-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 proton
-
-/*
-#cgo LDFLAGS: -lqpid-proton
-#include <stdlib.h>
-#include <string.h>
-#include <proton/url.h>
-
-// Helper function for setting URL fields.
-typedef void (*setter_fn)(pn_url_t* url, const char* value);
-inline void set(pn_url_t *url, setter_fn s, const char* value) {
- s(url, value);
-}
-*/
-import "C"
-
-import (
- "net"
- "net/url"
- "unsafe"
-)
-
-const (
- amqp string = "amqp"
- amqps = "amqps"
-)
-
-// ParseUrl parses an AMQP URL string and returns a net/url.Url.
-//
-// It is more forgiving than net/url.Parse and allows most of the parts of the
-// URL to be missing, assuming AMQP defaults.
-//
-func ParseURL(s string) (u *url.URL, err error) {
- cstr := C.CString(s)
- defer C.free(unsafe.Pointer(cstr))
- pnUrl := C.pn_url_parse(cstr)
- if pnUrl == nil {
- return nil, errorf("bad URL %#v", s)
- }
- defer C.pn_url_free(pnUrl)
-
- scheme := C.GoString(C.pn_url_get_scheme(pnUrl))
- username := C.GoString(C.pn_url_get_username(pnUrl))
- password := C.GoString(C.pn_url_get_password(pnUrl))
- host := C.GoString(C.pn_url_get_host(pnUrl))
- port := C.GoString(C.pn_url_get_port(pnUrl))
- path := C.GoString(C.pn_url_get_path(pnUrl))
-
- if err != nil {
- return nil, errorf("bad URL %#v: %s", s, err)
- }
- if scheme == "" {
- scheme = amqp
- }
- if port == "" {
- if scheme == amqps {
- port = amqps
- } else {
- port = amqp
- }
- }
- var user *url.Userinfo
- if password != "" {
- user = url.UserPassword(username, password)
- } else if username != "" {
- user = url.User(username)
- }
-
- u = &url.URL{
- Scheme: scheme,
- User: user,
- Host: net.JoinHostPort(host, port),
- Path: path,
- }
-
- return u, nil
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/apache.org/proton/url_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/apache.org/proton/url_test.go b/proton-c/bindings/go/src/apache.org/proton/url_test.go
deleted file mode 100644
index 7315511..0000000
--- a/proton-c/bindings/go/src/apache.org/proton/url_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-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 proton
-
-import (
- "fmt"
-)
-
-func ExampleParseURL() {
- for _, s := range []string{
- "amqp://username:password@host:1234/path",
- "host:1234",
- "host",
- ":1234",
- "host/path",
- "amqps://host",
- "",
- } {
- u, err := ParseURL(s)
- if err != nil {
- fmt.Println(err)
- } else {
- fmt.Println(u)
- }
- }
- // Output:
- // amqp://username:password@host:1234/path
- // amqp://host:1234
- // amqp://host:amqp
- // amqp://:1234
- // amqp://host:amqp/path
- // amqps://host:amqps
- // proton: bad URL ""
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/doc.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/doc.go b/proton-c/bindings/go/src/qpid.apache.org/proton/doc.go
new file mode 100644
index 0000000..34f85fe
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/doc.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 proton is a Go binding for the proton AMQP protocol engine.
+
+It alows you to construct and parse AMQP messages, and to implement AMQP
+clients, servers and intermediaries that can exchange messages with any
+AMQP 1.0 compliant endpoint.
+
+Encoding and decoding AMQP data follows the pattern of the standard
+encoding/json and encoding/xml packages.The mapping between AMQP and Go types is
+described in the documentation of the Marshal and Unmarshal functions.
+*/
+package proton
+
+// This file is just for the package comment.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/error.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/error.go b/proton-c/bindings/go/src/qpid.apache.org/proton/error.go
new file mode 100644
index 0000000..f9cc948
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/error.go
@@ -0,0 +1,96 @@
+/*
+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 proton
+
+// #include <proton/error.h>
+// #include <proton/codec.h>
+import "C"
+
+import (
+ "fmt"
+ "reflect"
+ "runtime"
+)
+
+var pnErrorNames = map[int]string{
+ C.PN_EOS: "end of data",
+ C.PN_ERR: "error",
+ C.PN_OVERFLOW: "overflow",
+ C.PN_UNDERFLOW: "underflow",
+ C.PN_STATE_ERR: "bad state",
+ C.PN_ARG_ERR: "invalid argument",
+ C.PN_TIMEOUT: "timeout",
+ C.PN_INTR: "interrupted",
+ C.PN_INPROGRESS: "in progress",
+}
+
+func pnErrorName(code int) string {
+ name := pnErrorNames[code]
+ if name != "" {
+ return name
+ } else {
+ return "unknown error code"
+ }
+}
+
+type BadUnmarshal struct {
+ AMQPType C.pn_type_t
+ GoType reflect.Type
+}
+
+func newBadUnmarshal(pnType C.pn_type_t, v interface{}) *BadUnmarshal {
+ return &BadUnmarshal{pnType, reflect.TypeOf(v)}
+}
+
+func (e BadUnmarshal) Error() string {
+ if e.GoType.Kind() != reflect.Ptr {
+ return fmt.Sprintf("proton: cannot unmarshal to type %s, not a pointer", e.GoType)
+ } else {
+ return fmt.Sprintf("proton: cannot unmarshal AMQP %s to %s", getPnType(e.AMQPType), e.GoType)
+ }
+}
+
+// errorf creates an error with a formatted message
+func errorf(format string, a ...interface{}) error {
+ return fmt.Errorf("proton: %s", fmt.Sprintf(format, a...))
+}
+
+func pnDataError(data *C.pn_data_t) string {
+ err := C.pn_data_error(data)
+ if err != nil && int(C.pn_error_code(err)) != 0 {
+ return C.GoString(C.pn_error_text(err))
+ }
+ return ""
+}
+
+// doRecover is called to recover from internal panics
+func doRecover(err *error) {
+ r := recover()
+ switch r := r.(type) {
+ case nil:
+ return
+ case runtime.Error:
+ panic(r)
+ case error:
+ *err = r
+ default:
+ panic(r)
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/interop_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/interop_test.go b/proton-c/bindings/go/src/qpid.apache.org/proton/interop_test.go
new file mode 100644
index 0000000..c51d74a
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/interop_test.go
@@ -0,0 +1,290 @@
+/*
+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.
+*/
+
+// Test that conversion of Go type to/from AMQP is compatible with other
+// bindings.
+//
+package proton
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func assertEqual(want interface{}, got interface{}) {
+ if !reflect.DeepEqual(want, got) {
+ panic(errorf("%#v != %#v", want, got))
+ }
+}
+
+func assertNil(err interface{}) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+func getReader(name string) (r io.Reader) {
+ r, err := os.Open("../../../../../../tests/interop/" + name + ".amqp")
+ if err != nil {
+ panic(errorf("Can't open %#v: %v", name, err))
+ }
+ return
+}
+
+func remaining(d *Decoder) string {
+ remainder, _ := ioutil.ReadAll(io.MultiReader(d.Buffered(), d.reader))
+ return string(remainder)
+}
+
+// assertDecode: want is the expected value, gotPtr is a pointer to a
+// instance of the same type for Decode.
+func assertDecode(d *Decoder, want interface{}, gotPtr interface{}) {
+
+ assertNil(d.Decode(gotPtr))
+
+ got := reflect.ValueOf(gotPtr).Elem().Interface()
+ assertEqual(want, got)
+
+ // Try round trip encoding
+ bytes, err := Marshal(want)
+ assertNil(err)
+ n, err := Unmarshal(bytes, gotPtr)
+ assertNil(err)
+ assertEqual(n, len(bytes))
+ got = reflect.ValueOf(gotPtr).Elem().Interface()
+ assertEqual(want, got)
+}
+
+func TestUnmarshal(t *testing.T) {
+ bytes, err := ioutil.ReadAll(getReader("strings"))
+ if err != nil {
+ t.Error(err)
+ }
+ for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} {
+ var got string
+ n, err := Unmarshal(bytes, &got)
+ if err != nil {
+ t.Error(err)
+ }
+ if want != got {
+ t.Errorf("%#v != %#v", want, got)
+ }
+ bytes = bytes[n:]
+ }
+}
+
+func TestPrimitivesExact(t *testing.T) {
+ d := NewDecoder(getReader("primitives"))
+ // Decoding into exact types
+ var b bool
+ assertDecode(d, true, &b)
+ assertDecode(d, false, &b)
+ var u8 uint8
+ assertDecode(d, uint8(42), &u8)
+ var u16 uint16
+ assertDecode(d, uint16(42), &u16)
+ var i16 int16
+ assertDecode(d, int16(-42), &i16)
+ var u32 uint32
+ assertDecode(d, uint32(12345), &u32)
+ var i32 int32
+ assertDecode(d, int32(-12345), &i32)
+ var u64 uint64
+ assertDecode(d, uint64(12345), &u64)
+ var i64 int64
+ assertDecode(d, int64(-12345), &i64)
+ var f32 float32
+ assertDecode(d, float32(0.125), &f32)
+ var f64 float64
+ assertDecode(d, float64(0.125), &f64)
+}
+
+func TestPrimitivesCompatible(t *testing.T) {
+ d := NewDecoder(getReader("primitives"))
+ // Decoding into compatible types
+ var b bool
+ var i int
+ var u uint
+ var f float64
+ assertDecode(d, true, &b)
+ assertDecode(d, false, &b)
+ assertDecode(d, uint(42), &u)
+ assertDecode(d, uint(42), &u)
+ assertDecode(d, -42, &i)
+ assertDecode(d, uint(12345), &u)
+ assertDecode(d, -12345, &i)
+ assertDecode(d, uint(12345), &u)
+ assertDecode(d, -12345, &i)
+ assertDecode(d, 0.125, &f)
+ assertDecode(d, 0.125, &f)
+}
+
+// assertDecodeValue: want is the expected value, decode into a reflect.Value
+func assertDecodeInterface(d *Decoder, want interface{}) {
+
+ var got, got2 interface{}
+ assertNil(d.Decode(&got))
+
+ assertEqual(want, got)
+
+ // Try round trip encoding
+ bytes, err := Marshal(got)
+ assertNil(err)
+ n, err := Unmarshal(bytes, &got2)
+ assertNil(err)
+ assertEqual(n, len(bytes))
+ assertEqual(want, got2)
+}
+
+func TestPrimitivesInterface(t *testing.T) {
+ d := NewDecoder(getReader("primitives"))
+ assertDecodeInterface(d, true)
+ assertDecodeInterface(d, false)
+ assertDecodeInterface(d, uint8(42))
+ assertDecodeInterface(d, uint16(42))
+ assertDecodeInterface(d, int16(-42))
+ assertDecodeInterface(d, uint32(12345))
+ assertDecodeInterface(d, int32(-12345))
+ assertDecodeInterface(d, uint64(12345))
+ assertDecodeInterface(d, int64(-12345))
+ assertDecodeInterface(d, float32(0.125))
+ assertDecodeInterface(d, float64(0.125))
+}
+
+func TestStrings(t *testing.T) {
+ d := NewDecoder(getReader("strings"))
+ // Test decoding as plain Go strings
+ for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} {
+ var got string
+ assertDecode(d, want, &got)
+ }
+ remains := remaining(d)
+ if remains != "" {
+ t.Errorf("leftover: %s", remains)
+ }
+
+ // Test decoding as specific string types
+ d = NewDecoder(getReader("strings"))
+ var bytes []byte
+ var str, sym string
+ assertDecode(d, []byte("abc\000defg"), &bytes)
+ assertDecode(d, "abcdefg", &str)
+ assertDecode(d, "abcdefg", &sym)
+ assertDecode(d, make([]byte, 0), &bytes)
+ assertDecode(d, "", &str)
+ assertDecode(d, "", &sym)
+ remains = remaining(d)
+ if remains != "" {
+ panic(errorf("leftover: %s", remains))
+ }
+
+ // Test some error handling
+ d = NewDecoder(getReader("strings"))
+ var s string
+ err := d.Decode(s)
+ if err == nil {
+ t.Fatal("Expected error")
+ }
+ if !strings.Contains(err.Error(), "not a pointer") {
+ t.Error(err)
+ }
+ var i int
+ err = d.Decode(&i)
+ if !strings.Contains(err.Error(), "cannot unmarshal") {
+ t.Error(err)
+ }
+ _, err = Unmarshal([]byte{}, nil)
+ if !strings.Contains(err.Error(), "not enough data") {
+ t.Error(err)
+ }
+ _, err = Unmarshal([]byte("foobar"), nil)
+ if !strings.Contains(err.Error(), "invalid argument") {
+ t.Error(err)
+ }
+}
+
+func TestEncodeDecode(t *testing.T) {
+ type data struct {
+ s string
+ i int
+ u8 uint8
+ b bool
+ f float32
+ v interface{}
+ }
+
+ in := data{"foo", 42, 9, true, 1.234, "thing"}
+
+ buf := bytes.Buffer{}
+ e := NewEncoder(&buf)
+ e.Encode(in.s)
+ e.Encode(in.i)
+ e.Encode(in.u8)
+ e.Encode(in.b)
+ e.Encode(in.f)
+ e.Encode(in.v)
+
+ var out data
+ d := NewDecoder(&buf)
+ d.Decode(&out.s)
+ d.Decode(&out.i)
+ d.Decode(&out.u8)
+ d.Decode(&out.b)
+ d.Decode(&out.f)
+ d.Decode(&out.v)
+
+ assertEqual(in, out)
+}
+
+func TestMap(t *testing.T) {
+ d := NewDecoder(getReader("maps"))
+
+ // Generic map
+ var m Map
+ assertDecode(d, Map{"one": int32(1), "two": int32(2), "three": int32(3)}, &m)
+
+ // Interface as map
+ var i interface{}
+ assertDecode(d, Map{int32(1): "one", int32(2): "two", int32(3): "three"}, &i)
+
+ d = NewDecoder(getReader("maps"))
+ // Specific typed map
+ var m2 map[string]int
+ assertDecode(d, map[string]int{"one": 1, "two": 2, "three": 3}, &m2)
+
+ // Round trip a nested map
+ m = Map{int64(1): "one", "two": int32(2), true: Map{uint8(1): true, uint8(2): false}}
+ bytes, err := Marshal(m)
+ assertNil(err)
+ _, err = Unmarshal(bytes, &i)
+ assertNil(err)
+ assertEqual(m, i)
+}
+
+func TestList(t *testing.T) {
+ d := NewDecoder(getReader("lists"))
+ var l List
+ assertDecode(d, List{int32(32), "foo", true}, &l)
+ assertDecode(d, List{}, &l)
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/marshal.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/marshal.go b/proton-c/bindings/go/src/qpid.apache.org/proton/marshal.go
new file mode 100644
index 0000000..fcd414c
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/marshal.go
@@ -0,0 +1,210 @@
+/*
+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 proton
+
+// #include <proton/codec.h>
+import "C"
+
+import (
+ "io"
+ "reflect"
+ "unsafe"
+)
+
+const minEncode = 256
+
+/*
+Marshal encodes a value as AMQP.
+
+Go types are encoded as follows
+
+ +-------------------------------------+--------------------------------------------+
+ |Go type |AMQP type |
+ +-------------------------------------+--------------------------------------------+
+ |bool |bool |
+ +-------------------------------------+--------------------------------------------+
+ |int8, int16, int32, int64 (int) |byte, short, int, long (int or long) |
+ +-------------------------------------+--------------------------------------------+
+ |uint8, uint16, uint32, uint64 (uint) |ubyte, ushort, uint, ulong (uint or ulong) |
+ +-------------------------------------+--------------------------------------------+
+ |float32, float64 |float, double. |
+ +-------------------------------------+--------------------------------------------+
+ |string |string |
+ +-------------------------------------+--------------------------------------------+
+ |[]byte |binary |
+ +-------------------------------------+--------------------------------------------+
+ |interface{} |as to the contained type |
+ +-------------------------------------+--------------------------------------------+
+ |map[K]T |map with K and T converted as above |
+ +-------------------------------------+--------------------------------------------+
+ |Map |map, may have mixed types for keys, values |
+ +-------------------------------------+--------------------------------------------+
+ |[]T |list with T converted as above |
+ +-------------------------------------+--------------------------------------------+
+ |List |list, may have mixed types values |
+ +-------------------------------------+--------------------------------------------+
+
+TODO types
+
+Go: array, slice, struct
+
+Go types that cannot be marshaled
+
+complex64/128, uintptr, function, interface, channel
+
+*/
+func Marshal(v interface{}) (bytes []byte, err error) {
+ return marshal(make([]byte, minEncode), v)
+}
+
+func marshal(bytesIn []byte, v interface{}) (bytes []byte, err error) {
+ defer doRecover(&err)
+ data := C.pn_data(0)
+ defer C.pn_data_free(data)
+ put(data, v)
+ // FIXME aconway 2015-03-11: get size from proton.
+ bytes = bytesIn
+ for {
+ n := int(C.pn_data_encode(data, (*C.char)(unsafe.Pointer(&bytes[0])), C.size_t(cap(bytes))))
+ if n != int(C.PN_EOS) {
+ if n < 0 {
+ err = errorf(pnErrorName(n))
+ } else {
+ bytes = bytes[0:n]
+ }
+ return
+ }
+ bytes = make([]byte, cap(bytes)*2)
+ }
+ return
+}
+
+func put(data *C.pn_data_t, v interface{}) {
+ switch v := v.(type) {
+ case bool:
+ C.pn_data_put_bool(data, C.bool(v))
+ case int8:
+ C.pn_data_put_byte(data, C.int8_t(v))
+ case int16:
+ C.pn_data_put_short(data, C.int16_t(v))
+ case int32:
+ C.pn_data_put_int(data, C.int32_t(v))
+ case int64:
+ C.pn_data_put_long(data, C.int64_t(v))
+ case int:
+ if unsafe.Sizeof(0) == 8 {
+ C.pn_data_put_long(data, C.int64_t(v))
+ } else {
+ C.pn_data_put_int(data, C.int32_t(v))
+ }
+ case uint8:
+ C.pn_data_put_ubyte(data, C.uint8_t(v))
+ case uint16:
+ C.pn_data_put_ushort(data, C.uint16_t(v))
+ case uint32:
+ C.pn_data_put_uint(data, C.uint32_t(v))
+ case uint64:
+ C.pn_data_put_ulong(data, C.uint64_t(v))
+ case uint:
+ if unsafe.Sizeof(0) == 8 {
+ C.pn_data_put_ulong(data, C.uint64_t(v))
+ } else {
+ C.pn_data_put_uint(data, C.uint32_t(v))
+ }
+ case float32:
+ C.pn_data_put_float(data, C.float(v))
+ case float64:
+ C.pn_data_put_double(data, C.double(v))
+ case string:
+ C.pn_data_put_string(data, toPnBytes([]byte(v)))
+ case []byte:
+ C.pn_data_put_binary(data, toPnBytes(v))
+ case Map: // Special map type
+ C.pn_data_put_map(data)
+ C.pn_data_enter(data)
+ for key, val := range v {
+ put(data, key)
+ put(data, val)
+ }
+ C.pn_data_exit(data)
+ default:
+ switch reflect.TypeOf(v).Kind() {
+ case reflect.Map:
+ putMap(data, v)
+ case reflect.Slice:
+ putList(data, v)
+ default:
+ panic(errorf("cannot marshal %s to AMQP", reflect.TypeOf(v)))
+ }
+ }
+ err := pnDataError(data)
+ if err != "" {
+ panic(errorf("marshal %s", err))
+ }
+ return
+}
+
+func putMap(data *C.pn_data_t, v interface{}) {
+ mapValue := reflect.ValueOf(v)
+ C.pn_data_put_map(data)
+ C.pn_data_enter(data)
+ for _, key := range mapValue.MapKeys() {
+ put(data, key.Interface())
+ put(data, mapValue.MapIndex(key).Interface())
+ }
+ C.pn_data_exit(data)
+}
+
+func putList(data *C.pn_data_t, v interface{}) {
+ listValue := reflect.ValueOf(v)
+ C.pn_data_put_list(data)
+ C.pn_data_enter(data)
+ for i := 0; i < listValue.Len(); i++ {
+ put(data, listValue.Index(i).Interface())
+ }
+ C.pn_data_exit(data)
+}
+
+// Encoder encodes AMQP values to an io.Writer
+type Encoder struct {
+ writer io.Writer
+ buffer []byte
+}
+
+// New encoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{w, make([]byte, minEncode)}
+}
+
+func (e *Encoder) Encode(v interface{}) (err error) {
+ e.buffer, err = marshal(e.buffer, v)
+ if err == nil {
+ e.writer.Write(e.buffer)
+ }
+ return
+}
+
+func toPnBytes(b []byte) C.pn_bytes_t {
+ if len(b) == 0 {
+ return C.pn_bytes_t{0, nil}
+ } else {
+ return C.pn_bytes_t{C.size_t(len(b)), (*C.char)(unsafe.Pointer(&b[0]))}
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/types.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/types.go b/proton-c/bindings/go/src/qpid.apache.org/proton/types.go
new file mode 100644
index 0000000..561ac9a
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/types.go
@@ -0,0 +1,151 @@
+/*
+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 proton
+
+// #include <proton/codec.h>
+import "C"
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+)
+
+type pnGet func(data *C.pn_data_t) reflect.Value
+type pnPut func(data *C.pn_data_t, v interface{})
+
+// Information about a proton type
+type pnType struct {
+ code C.pn_type_t // AMQP type code
+ name string // AMQP type name
+}
+
+func (pt *pnType) String() string { return pt.name }
+
+// pnType definitions for each proton type.
+var (
+ pnNull = pnType{code: C.PN_NULL, name: "null"}
+ pnBool = pnType{code: C.PN_BOOL, name: "bool"}
+ pnUbyte = pnType{code: C.PN_UBYTE, name: "ubyte"}
+ pnByte = pnType{code: C.PN_BYTE, name: "byte"}
+ pnUshort = pnType{code: C.PN_USHORT, name: "ushort"}
+ pnShort = pnType{code: C.PN_SHORT, name: "short"}
+ pnChar = pnType{code: C.PN_CHAR, name: "char"}
+ pnUint = pnType{code: C.PN_UINT, name: "uint"}
+ pnInt = pnType{code: C.PN_INT, name: "int"}
+ pnUlong = pnType{code: C.PN_ULONG, name: "ulong"}
+ pnLong = pnType{code: C.PN_LONG, name: "long"}
+ pnTimestamp = pnType{code: C.PN_TIMESTAMP, name: "timestamp"}
+ pnFloat = pnType{code: C.PN_FLOAT, name: "float"}
+ pnDouble = pnType{code: C.PN_DOUBLE, name: "double"}
+ pnDecimal32 = pnType{code: C.PN_DECIMAL32, name: "decimal32"}
+ pnDecimal64 = pnType{code: C.PN_DECIMAL64, name: "decimal64"}
+ pnDecimal128 = pnType{code: C.PN_DECIMAL128, name: "decimal128"}
+ pnUuid = pnType{code: C.PN_UUID, name: "uuid"}
+ pnBinary = pnType{code: C.PN_BINARY, name: "binary"}
+ pnString = pnType{code: C.PN_STRING, name: "string"}
+ pnSymbol = pnType{code: C.PN_SYMBOL, name: "symbol"}
+ pnDescribed = pnType{code: C.PN_DESCRIBED, name: "described"}
+ pnArray = pnType{code: C.PN_ARRAY, name: "array"}
+ pnList = pnType{code: C.PN_LIST, name: "list"}
+ pnMap = pnType{code: C.PN_MAP, name: "map"}
+)
+
+// Map from pn_type_t codes to pnType structs
+var pnTypes = map[C.pn_type_t]*pnType{
+ C.PN_NULL: &pnNull,
+ C.PN_BOOL: &pnBool,
+ C.PN_UBYTE: &pnUbyte,
+ C.PN_BYTE: &pnByte,
+ C.PN_USHORT: &pnUshort,
+ C.PN_SHORT: &pnShort,
+ C.PN_UINT: &pnUint,
+ C.PN_INT: &pnInt,
+ C.PN_CHAR: &pnChar,
+ C.PN_ULONG: &pnUlong,
+ C.PN_LONG: &pnLong,
+ C.PN_TIMESTAMP: &pnTimestamp,
+ C.PN_FLOAT: &pnFloat,
+ C.PN_DOUBLE: &pnDouble,
+ C.PN_DECIMAL32: &pnDecimal32,
+ C.PN_DECIMAL64: &pnDecimal64,
+ C.PN_DECIMAL128: &pnDecimal128,
+ C.PN_UUID: &pnUuid,
+ C.PN_BINARY: &pnBinary,
+ C.PN_STRING: &pnString,
+ C.PN_SYMBOL: &pnSymbol,
+ C.PN_DESCRIBED: &pnDescribed,
+ C.PN_ARRAY: &pnArray,
+ C.PN_LIST: &pnList,
+ C.PN_MAP: &pnMap,
+}
+
+// Get the pnType for a pn_type_t code, panic if unknown code.
+func getPnType(code C.pn_type_t) *pnType {
+ pt, ok := pnTypes[code]
+ if !ok {
+ panic(errorf("unknown AMQP type code %v", code))
+ }
+ return pt
+}
+
+// Go types
+var (
+ bytesType = reflect.TypeOf([]byte{})
+ valueType = reflect.TypeOf(reflect.Value{})
+)
+
+// Map is a generic map that can have mixed key and value types and so can represent any AMQP map
+//
+type Map map[interface{}]interface{}
+
+// List is a generic list that can hold mixed values and can represent any AMQP list.
+//
+type List []interface{}
+
+// GoString for Map prints values with their types, useful for debugging.
+func (m Map) GoString() string {
+ out := &bytes.Buffer{}
+ fmt.Fprintf(out, "%T{", m)
+ i := len(m)
+ for k, v := range m {
+ fmt.Fprintf(out, "%T(%#v): %T(%#v)", k, k, v, v)
+ i--
+ if i > 0 {
+ fmt.Fprint(out, ", ")
+ }
+ }
+ fmt.Fprint(out, "}")
+ return out.String()
+}
+
+// GoString for List prints values with their types, useful for debugging.
+func (l List) GoString() string {
+ out := &bytes.Buffer{}
+ fmt.Fprintf(out, "%T{", l)
+ for i := 0; i < len(l); i++ {
+ fmt.Fprintf(out, "%T(%#v)", l[i], l[i])
+ if i == len(l)-1 {
+ fmt.Fprint(out, ", ")
+ }
+ }
+ fmt.Fprint(out, "}")
+ return out.String()
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/695f8e5b/proton-c/bindings/go/src/qpid.apache.org/proton/unfinished.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/unfinished.go b/proton-c/bindings/go/src/qpid.apache.org/proton/unfinished.go
new file mode 100644
index 0000000..f9ba50a
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/unfinished.go
@@ -0,0 +1,53 @@
+/*
+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 proton
+
+import (
+ "net"
+)
+
+type Acceptor struct{}
+
+type Event struct {
+ Container *Container
+ Message *Message
+}
+
+type Connection struct{}
+
+func (e *Event) Connection() *Connection { return nil }
+
+func (e *Event) Sender() *Sender { return nil }
+
+func (c *Connection) NewSender(name string) *Sender { return nil }
+
+func (c *Connection) Close() {}
+
+type Container struct{}
+
+type Sender struct{}
+
+func (s *Sender) Credit() int { return 0 }
+
+func (s *Sender) Send(m *Message) {}
+
+func Run(connection net.Conn, handler interface{}) error { return nil }
+
+type Message struct{ Body interface{} }
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org