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/06/18 23:58:16 UTC

[38/50] [abbrv] qpid-proton git commit: PROTON-865: Stream like Encoder/Decoder and AMQP Value type for C++ binding.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/ContainerImpl.h
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/ContainerImpl.h b/proton-c/bindings/cpp/src/ContainerImpl.h
index 65a6651..c0d2d12 100644
--- a/proton-c/bindings/cpp/src/ContainerImpl.h
+++ b/proton-c/bindings/cpp/src/ContainerImpl.h
@@ -41,20 +41,20 @@ class Acceptor;
 class ContainerImpl
 {
   public:
-    PROTON_CPP_EXTERN ContainerImpl(Handler &h);
-    PROTON_CPP_EXTERN ContainerImpl();
-    PROTON_CPP_EXTERN ~ContainerImpl();
-    PROTON_CPP_EXTERN Connection connect(std::string &host, Handler *h);
-    PROTON_CPP_EXTERN void run();
-    PROTON_CPP_EXTERN pn_reactor_t *getReactor();
-    PROTON_CPP_EXTERN Sender createSender(Connection &connection, std::string &addr, Handler *h);
-    PROTON_CPP_EXTERN Sender createSender(std::string &url);
-    PROTON_CPP_EXTERN Receiver createReceiver(Connection &connection, std::string &addr);
-    PROTON_CPP_EXTERN Receiver createReceiver(const std::string &url);
-    PROTON_CPP_EXTERN Acceptor listen(const std::string &url);
-    PROTON_CPP_EXTERN std::string getContainerId();
-    PROTON_CPP_EXTERN Duration getTimeout();
-    PROTON_CPP_EXTERN void setTimeout(Duration timeout);
+    PN_CPP_EXTERN ContainerImpl(Handler &h);
+    PN_CPP_EXTERN ContainerImpl();
+    PN_CPP_EXTERN ~ContainerImpl();
+    PN_CPP_EXTERN Connection connect(std::string &host, Handler *h);
+    PN_CPP_EXTERN void run();
+    PN_CPP_EXTERN pn_reactor_t *getReactor();
+    PN_CPP_EXTERN Sender createSender(Connection &connection, std::string &addr, Handler *h);
+    PN_CPP_EXTERN Sender createSender(std::string &url);
+    PN_CPP_EXTERN Receiver createReceiver(Connection &connection, std::string &addr);
+    PN_CPP_EXTERN Receiver createReceiver(const std::string &url);
+    PN_CPP_EXTERN Acceptor listen(const std::string &url);
+    PN_CPP_EXTERN std::string getContainerId();
+    PN_CPP_EXTERN Duration getTimeout();
+    PN_CPP_EXTERN void setTimeout(Duration timeout);
     void start();
     bool process();
     void stop();

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/Data.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/Data.cpp b/proton-c/bindings/cpp/src/Data.cpp
new file mode 100644
index 0000000..6cfc09b
--- /dev/null
+++ b/proton-c/bindings/cpp/src/Data.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#include "proton/cpp/Data.h"
+#include <proton/codec.h>
+#include "proton_bits.h"
+
+namespace proton {
+namespace reactor {
+
+Data::Data(pn_data_t* p) : data(p ? p : pn_data(0)) {}
+
+Data::~Data() { if (data) pn_data_free(data); }
+
+Data& Data::operator=(const Data& x) {
+    if (this != &x) {
+        pn_data_free(data);
+        data = pn_data(pn_data_size(x.data));
+        pn_data_copy(data, x.data);
+    }
+    return *this;
+}
+
+void Data::clear() { pn_data_clear(data); }
+
+bool Data::empty() const { return pn_data_size(data) == 0; }
+
+std::ostream& operator<<(std::ostream& o, const Data& d) {
+    o << Object(d.data);
+}
+
+}} // namespace proton::reactor

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/Decoder.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/Decoder.cpp b/proton-c/bindings/cpp/src/Decoder.cpp
new file mode 100644
index 0000000..4170378
--- /dev/null
+++ b/proton-c/bindings/cpp/src/Decoder.cpp
@@ -0,0 +1,265 @@
+/*
+ * 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.
+ */
+
+#include "proton/cpp/Decoder.h"
+#include <proton/codec.h>
+#include "proton_bits.h"
+
+namespace proton {
+namespace reactor {
+
+
+/**@file
+ *
+ * Note the pn_data_t "current" node is always pointing *before* the next value
+ * to be returned by the Decoder.
+ *
+ */
+Decoder::Decoder() {}
+Decoder::Decoder(const char* buffer, size_t size) { decode(buffer, size); }
+Decoder::Decoder(const std::string& buffer) { decode(buffer); }
+Decoder::~Decoder() {}
+
+namespace {
+struct SaveState {
+    pn_data_t* data;
+    pn_handle_t handle;
+    SaveState(pn_data_t* d) : data(d), handle(pn_data_point(d)) {}
+    ~SaveState() { if (data) pn_data_restore(data, handle); }
+    void cancel() { data = 0; }
+};
+}
+
+void Decoder::decode(const char* i, size_t size) {
+    SaveState ss(data);
+    const char* end = i + size;
+    while (i < end) {
+        int result = pn_data_decode(data, i, end - i);
+        if (result < 0) throw Decoder::Error("decode: " + errorStr(result));
+        i += result;
+    }
+}
+
+void Decoder::decode(const std::string& buffer) {
+    decode(buffer.data(), buffer.size());
+}
+
+bool Decoder::more() const {
+    SaveState ss(data);
+    return pn_data_next(data);
+}
+
+namespace {
+
+void badType(TypeId want, TypeId got) {
+    if (want != got)
+        throw Decoder::Error("decode: expected "+typeName(want)+" found "+typeName(got));
+}
+
+TypeId preGet(pn_data_t* data) {
+    if (!pn_data_next(data)) throw Decoder::Error("decode: no more data");
+    TypeId t = TypeId(pn_data_type(data));
+    if (t < 0) throw Decoder::Error("decode: invalid data");
+    return t;
+}
+
+// Simple extract with no type conversion.
+template <class T, class U> void extract(pn_data_t* data, T& value, U (*get)(pn_data_t*)) {
+    SaveState ss(data);
+    badType(TypeIdOf<T>::value, preGet(data));
+    value = get(data);
+    ss.cancel();                // No error, no rewind
+}
+
+}
+
+TypeId Decoder::type() const {
+    SaveState ss(data);
+    return preGet(data);
+}
+
+Decoder& operator>>(Decoder& d, Bool& value) {
+    extract(d.data, value, pn_data_get_bool);
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Ubyte& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case UBYTE: value = pn_data_get_ubyte(d.data); break;
+      default: badType(UBYTE, TypeId(TypeId(pn_data_type(d.data))));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Byte& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case BYTE: value = pn_data_get_ubyte(d.data); break;
+      default: badType(BYTE, TypeId(TypeId(pn_data_type(d.data))));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Ushort& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case UBYTE: value = pn_data_get_ubyte(d.data); break;
+      case USHORT: value = pn_data_get_ushort(d.data); break;
+      default: badType(USHORT, TypeId(TypeId(pn_data_type(d.data))));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Short& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case BYTE: value = pn_data_get_byte(d.data); break;
+      case SHORT: value = pn_data_get_short(d.data); break;
+      default: badType(SHORT, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Uint& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case UBYTE: value = pn_data_get_ubyte(d.data); break;
+      case USHORT: value = pn_data_get_ushort(d.data); break;
+      case UINT: value = pn_data_get_uint(d.data); break;
+      default: badType(UINT, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Int& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case BYTE: value = pn_data_get_byte(d.data); break;
+      case SHORT: value = pn_data_get_short(d.data); break;
+      case INT: value = pn_data_get_int(d.data); break;
+      default: badType(INT, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Ulong& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case UBYTE: value = pn_data_get_ubyte(d.data); break;
+      case USHORT: value = pn_data_get_ushort(d.data); break;
+      case UINT: value = pn_data_get_uint(d.data); break;
+      case ULONG: value = pn_data_get_ulong(d.data); break;
+      default: badType(ULONG, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Long& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case BYTE: value = pn_data_get_byte(d.data); break;
+      case SHORT: value = pn_data_get_short(d.data); break;
+      case INT: value = pn_data_get_int(d.data); break;
+      case LONG: value = pn_data_get_long(d.data); break;
+      default: badType(LONG, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Char& value) {
+    extract(d.data, value, pn_data_get_char);
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Timestamp& value) {
+    extract(d.data, value, pn_data_get_timestamp);
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Float& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case FLOAT: value = pn_data_get_float(d.data); break;
+      case DOUBLE: value = pn_data_get_double(d.data); break;
+      default: badType(FLOAT, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Double& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case FLOAT: value = pn_data_get_float(d.data); break;
+      case DOUBLE: value = pn_data_get_double(d.data); break;
+      default: badType(DOUBLE, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+// TODO aconway 2015-06-11: decimal conversions.
+Decoder& operator>>(Decoder& d, Decimal32& value) {
+    extract(d.data, value, pn_data_get_decimal32);
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Decimal64& value) {
+    extract(d.data, value, pn_data_get_decimal64);
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Decimal128& value)  {
+    extract(d.data, value, pn_data_get_decimal128);
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, Uuid& value)  {
+    extract(d.data, value, pn_data_get_uuid);
+    return d;
+}
+
+Decoder& operator>>(Decoder& d, std::string& value) {
+    SaveState ss(d.data);
+    switch (preGet(d.data)) {
+      case STRING: value = str(pn_data_get_string(d.data)); break;
+      case BINARY: value = str(pn_data_get_binary(d.data)); break;
+      case SYMBOL: value = str(pn_data_get_symbol(d.data)); break;
+      default: badType(STRING, TypeId(pn_data_type(d.data)));
+    }
+    ss.cancel();
+    return d;
+}
+
+void Decoder::checkType(TypeId want) {
+    TypeId got = type();
+    if (want != got) badType(want, got);
+}
+
+
+}} // namespace proton::reactor

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/Encoder.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/Encoder.cpp b/proton-c/bindings/cpp/src/Encoder.cpp
new file mode 100644
index 0000000..81fa365
--- /dev/null
+++ b/proton-c/bindings/cpp/src/Encoder.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#include "proton/cpp/Encoder.h"
+#include <proton/codec.h>
+#include "proton_bits.h"
+
+namespace proton {
+namespace reactor {
+
+Encoder::Encoder() {}
+Encoder::~Encoder() {}
+
+namespace {
+struct SaveState {
+    pn_data_t* data;
+    pn_handle_t handle;
+    SaveState(pn_data_t* d) : data(d), handle(pn_data_point(d)) {}
+    ~SaveState() { if (data) pn_data_restore(data, handle); }
+};
+
+template <class T> T check(T result) {
+    if (result < 0)
+        throw Encoder::Error("encode: " + errorStr(result));
+    return result;
+}
+}
+
+bool Encoder::encode(char* buffer, size_t& size) {
+    SaveState ss(data);               // In case of error
+    pn_data_rewind(data);
+    ssize_t result = pn_data_encode(data, buffer, size);
+    if (result == PN_OVERFLOW) {
+        size = pn_data_encoded_size(data);
+        return false;
+    }
+    check(result);
+    size = result;
+    ss.data = 0;                // Don't restore state, all is well.
+    pn_data_clear(data);
+}
+
+void Encoder::encode(std::string& s) {
+    size_t size = s.size();
+    if (!encode(&s[0], size)) {
+        s.resize(size);
+        encode(&s[0], size);
+    }
+}
+
+std::string Encoder::encode() {
+    std::string s;
+    encode(s);
+    return s;
+}
+
+namespace {
+template <class T, class U>
+Encoder& insert(Encoder& e, pn_data_t* data, T& value, int (*put)(pn_data_t*, U)) {
+    SaveState ss(data);         // Save state in case of error.
+    check(put(data, value));
+    ss.data = 0;                // Don't restore state, all is good.
+    return e;
+}
+}
+
+Encoder& operator<<(Encoder& e, Bool value) { return insert(e, e.data, value, pn_data_put_bool); }
+Encoder& operator<<(Encoder& e, Ubyte value) { return insert(e, e.data, value, pn_data_put_ubyte); }
+Encoder& operator<<(Encoder& e, Byte value) { return insert(e, e.data, value, pn_data_put_byte); }
+Encoder& operator<<(Encoder& e, Ushort value) { return insert(e, e.data, value, pn_data_put_ushort); }
+Encoder& operator<<(Encoder& e, Short value) { return insert(e, e.data, value, pn_data_put_short); }
+Encoder& operator<<(Encoder& e, Uint value) { return insert(e, e.data, value, pn_data_put_uint); }
+Encoder& operator<<(Encoder& e, Int value) { return insert(e, e.data, value, pn_data_put_int); }
+Encoder& operator<<(Encoder& e, Char value) { return insert(e, e.data, value, pn_data_put_char); }
+Encoder& operator<<(Encoder& e, Ulong value) { return insert(e, e.data, value, pn_data_put_ulong); }
+Encoder& operator<<(Encoder& e, Long value) { return insert(e, e.data, value, pn_data_put_long); }
+Encoder& operator<<(Encoder& e, Timestamp value) { return insert(e, e.data, value, pn_data_put_timestamp); }
+Encoder& operator<<(Encoder& e, Float value) { return insert(e, e.data, value, pn_data_put_float); }
+Encoder& operator<<(Encoder& e, Double value) { return insert(e, e.data, value, pn_data_put_double); }
+Encoder& operator<<(Encoder& e, Decimal32 value) { return insert(e, e.data, value, pn_data_put_decimal32); }
+Encoder& operator<<(Encoder& e, Decimal64 value) { return insert(e, e.data, value, pn_data_put_decimal64); }
+Encoder& operator<<(Encoder& e, Decimal128 value) { return insert(e, e.data, value, pn_data_put_decimal128); }
+Encoder& operator<<(Encoder& e, Uuid value) { return insert(e, e.data, value, pn_data_put_uuid); }
+Encoder& operator<<(Encoder& e, String value) { return insert(e, e.data, value, pn_data_put_string); }
+Encoder& operator<<(Encoder& e, Symbol value) { return insert(e, e.data, value, pn_data_put_symbol); }
+Encoder& operator<<(Encoder& e, Binary value) { return insert(e, e.data, value, pn_data_put_binary); }
+
+}} // namespace proton::reactor

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/Msg.h
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/Msg.h b/proton-c/bindings/cpp/src/Msg.h
index 1168d35..cd8f9e8 100644
--- a/proton-c/bindings/cpp/src/Msg.h
+++ b/proton-c/bindings/cpp/src/Msg.h
@@ -72,7 +72,7 @@ inline std::ostream& operator<<(std::ostream& o, const Msg& m) {
 /** Construct a message using operator << and append (file:line) */
 #define QUOTE_(x) #x
 #define QUOTE(x) QUOTE_(x)
-#define MSG(message) (::proton::reactor::Msg() << message << " (" __FILE__ ":" QUOTE(__LINE__) ")")
+#define MSG(message) (::proton::reactor::Msg() << message)
 
 }} // namespace proton::reactor
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/Url.h
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/Url.h b/proton-c/bindings/cpp/src/Url.h
index 042ab45..d9651fc 100644
--- a/proton-c/bindings/cpp/src/Url.h
+++ b/proton-c/bindings/cpp/src/Url.h
@@ -32,13 +32,13 @@ namespace reactor {
 class Url : public ProtonHandle<pn_url_t>
 {
   public:
-    PROTON_CPP_EXTERN Url(const std::string &url);
-    PROTON_CPP_EXTERN ~Url();
-    PROTON_CPP_EXTERN Url(const Url&);
-    PROTON_CPP_EXTERN Url& operator=(const Url&);
-    PROTON_CPP_EXTERN std::string getHost();
-    PROTON_CPP_EXTERN std::string getPort();
-    PROTON_CPP_EXTERN std::string getPath();
+    PN_CPP_EXTERN Url(const std::string &url);
+    PN_CPP_EXTERN ~Url();
+    PN_CPP_EXTERN Url(const Url&);
+    PN_CPP_EXTERN Url& operator=(const Url&);
+    PN_CPP_EXTERN std::string getHost();
+    PN_CPP_EXTERN std::string getPort();
+    PN_CPP_EXTERN std::string getPath();
   private:
     friend class ProtonImplRef<Url>;
 };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/Value.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/Value.cpp b/proton-c/bindings/cpp/src/Value.cpp
new file mode 100644
index 0000000..8e1e38c
--- /dev/null
+++ b/proton-c/bindings/cpp/src/Value.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#include "proton/cpp/Value.h"
+#include "proton_bits.h"
+#include <proton/codec.h>
+#include <ostream>
+
+namespace proton {
+namespace reactor {
+
+Values::Values() {}
+Values::Values(const Values& v) { *this = v; }
+Values::~Values() {}
+Values& Values::operator=(const Values& v) { Data::operator=(v); }
+
+void Values::rewind() { pn_data_rewind(data); }
+
+Value::Value() {}
+Value::Value(const Value& v) { *this = v; }
+Value::~Value() {}
+Value& Value::operator=(const Value& v) { values = v.values; }
+
+TypeId Value::type() const {
+    const_cast<Values&>(values).rewind();
+    return values.type();
+}
+
+namespace {
+template <class T> T check(T result) {
+    if (result < 0)
+        throw Encoder::Error("encode: " + errorStr(result));
+    return result;
+}
+}
+
+Encoder& operator<<(Encoder& e, const Value& v) {
+    if (e.data == v.values.data) throw Encoder::Error("Values inserted into self");
+    pn_data_narrow(e.data);
+    int result = pn_data_appendn(e.data, v.values.data, 1);
+    pn_data_widen(e.data);
+    check(result);
+    return e;
+}
+
+Decoder& operator>>(Decoder& e, Value& v) {
+    if (e.data == v.values.data) throw Decoder::Error("Values extracted from self");
+    pn_data_narrow(e.data);
+    int result = pn_data_appendn(e.data, v.values.data, 1);
+    pn_data_widen(e.data);
+    check(result);
+    return e;
+}
+
+}}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h b/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h
index 5f263ab..6adb65e 100644
--- a/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h
+++ b/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h
@@ -39,12 +39,12 @@ class SslDomain;
  class BlockingConnectionImpl : public MessagingHandler
 {
   public:
-    PROTON_CPP_EXTERN BlockingConnectionImpl(std::string &url, Duration d, SslDomain *ssld, Container *c);
-    PROTON_CPP_EXTERN ~BlockingConnectionImpl();
-    PROTON_CPP_EXTERN void close();
-    PROTON_CPP_EXTERN void wait(WaitCondition &condition);
-    PROTON_CPP_EXTERN void wait(WaitCondition &condition, std::string &msg, Duration timeout);
-    PROTON_CPP_EXTERN pn_connection_t *getPnBlockingConnection();
+    PN_CPP_EXTERN BlockingConnectionImpl(std::string &url, Duration d, SslDomain *ssld, Container *c);
+    PN_CPP_EXTERN ~BlockingConnectionImpl();
+    PN_CPP_EXTERN void close();
+    PN_CPP_EXTERN void wait(WaitCondition &condition);
+    PN_CPP_EXTERN void wait(WaitCondition &condition, std::string &msg, Duration timeout);
+    PN_CPP_EXTERN pn_connection_t *getPnBlockingConnection();
     Duration getTimeout() { return timeout; }
     static void incref(BlockingConnectionImpl *);
     static void decref(BlockingConnectionImpl *);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/grep
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/grep b/proton-c/bindings/cpp/src/grep
new file mode 100644
index 0000000..a53cfb8
--- /dev/null
+++ b/proton-c/bindings/cpp/src/grep
@@ -0,0 +1,50 @@
+  /home/aconway/proton/proton-c/bindings/cpp/src:
+  total used in directory 256 available 122608224
+  drwxrwxr-x. 3 aconway aconway  4096 Jun 11 14:47 .
+  drwxrwxr-x. 4 aconway aconway  4096 Jun 11 14:48 ..
+  -rw-rw-r--. 1 aconway aconway  1478 Jun 10 08:40 Acceptor.cpp
+  -rw-rw-r--. 1 aconway aconway  1401 Jun 10 08:40 Acking.cpp
+  -rw-rw-r--. 1 aconway aconway  1295 Jun 11 14:45 proton_bits.cpp
+  -rw-rw-r--. 1 aconway aconway   915 Jun 11 14:44 proton_bits.h
+  drwxrwxr-x. 2 aconway aconway  4096 Jun 10 08:40 blocking
+  -rw-rw-r--. 1 aconway aconway  2390 Jun 10 08:40 Connection.cpp
+  -rw-rw-r--. 1 aconway aconway  4285 Jun 10 08:40 ConnectionImpl.cpp
+  -rw-rw-r--. 1 aconway aconway  2531 Jun 10 08:40 ConnectionImpl.h
+  -rw-rw-r--. 1 aconway aconway  2131 Jun 10 08:40 Connector.cpp
+  -rw-rw-r--. 1 aconway aconway  1624 Jun 10 08:40 Connector.h
+  -rw-rw-r--. 1 aconway aconway  3188 Jun 10 08:40 Container.cpp
+  -rw-rw-r--. 1 aconway aconway 12183 Jun 10 08:40 ContainerImpl.cpp
+  -rw-rw-r--. 1 aconway aconway  2689 Jun 10 08:40 ContainerImpl.h
+  -rw-rw-r--. 1 aconway aconway  2846 Jun 10 08:40 contexts.cpp
+  -rw-rw-r--. 1 aconway aconway  1764 Jun 10 08:40 contexts.h
+  -rw-rw-r--. 1 aconway aconway  4992 Jun 11 14:45 Data.cpp
+  -rw-rw-r--. 1 aconway aconway  4494 Jun 11 14:46 Decoder.cpp
+  -rw-rw-r--. 1 aconway aconway  1590 Jun 10 08:40 Delivery.cpp
+  -rw-rw-r--. 1 aconway aconway  1752 Jun 10 08:40 Duration.cpp
+  -rw-rw-r--. 1 aconway aconway  3933 Jun 11 14:47 Encoder.cpp
+  -rw-rw-r--. 1 aconway aconway  1125 Jun 10 08:40 Endpoint.cpp
+  -rw-rw-r--. 1 aconway aconway  1882 Jun 10 08:40 Event.cpp
+  -rw-rw-r--. 1 aconway aconway  1315 Jun 10 08:40 Handler.cpp
+  -rw-rw-r--. 1 aconway aconway  4220 Jun 11 11:13 interop_test.cpp
+  -rw-rw-r--. 1 aconway aconway  2821 Jun 10 08:40 Link.cpp
+  -rw-rw-r--. 1 aconway aconway 13358 Jun 10 08:40 Message.cpp
+  -rw-rw-r--. 1 aconway aconway 13424 Jun 10 08:40 MessagingAdapter.cpp
+  -rw-rw-r--. 1 aconway aconway  5864 Jun 10 08:40 MessagingEvent.cpp
+  -rw-rw-r--. 1 aconway aconway  5230 Jun 10 08:40 MessagingHandler.cpp
+  -rw-rw-r--. 1 aconway aconway  2587 Jun 10 08:40 Msg.h
+  -rw-rw-r--. 1 aconway aconway  2208 Jun 10 08:40 platform.cpp
+  -rw-rw-r--. 1 aconway aconway  1145 Jun 10 08:40 platform.h
+  -rw-rw-r--. 1 aconway aconway  1072 Jun 11 11:49 pn_data.h
+  -rw-rw-r--. 1 aconway aconway  3000 Jun 10 08:40 PrivateImplRef.h
+  -rw-rw-r--. 1 aconway aconway  6032 Jun 10 08:40 ProtonEvent.cpp
+  -rw-rw-r--. 1 aconway aconway  3818 Jun 10 08:40 ProtonHandler.cpp
+  -rw-rw-r--. 1 aconway aconway  2209 Jun 10 08:40 ProtonImplRef.h
+  -rw-rw-r--. 1 aconway aconway  1396 Jun 10 08:40 Receiver.cpp
+  -rw-rw-r--. 1 aconway aconway  2119 Jun 10 08:40 Sender.cpp
+  -rw-rw-r--. 1 aconway aconway  2031 Jun 10 08:40 Session.cpp
+  -rw-rw-r--. 1 aconway aconway  2850 Jun 10 08:40 Terminus.cpp
+  -rw-rw-r--. 1 aconway aconway  1234 Jun 10 08:40 Transport.cpp
+  -rw-rw-r--. 1 aconway aconway  6251 Jun 10 18:27 types.cpp
+  -rw-rw-r--. 1 aconway aconway  1942 Jun 10 08:40 Url.cpp
+  -rw-rw-r--. 1 aconway aconway  1469 Jun 10 08:40 Url.h
+  -rw-rw-r--. 1 aconway aconway  2211 Jun 11 14:47 Value.cpp

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/interop_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/interop_test.cpp b/proton-c/bindings/cpp/src/interop_test.cpp
new file mode 100644
index 0000000..b344553
--- /dev/null
+++ b/proton-c/bindings/cpp/src/interop_test.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+#include "proton/cpp/Decoder.h"
+#include "proton/cpp/Encoder.h"
+#include "proton/cpp/Value.h"
+#include "./Msg.h"
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <streambuf>
+#include <iosfwd>
+#include <unistd.h>
+
+using namespace std;
+using namespace proton::reactor;
+
+std::string testsDir;
+
+struct Fail : public logic_error { Fail(const string& what) : logic_error(what) {} };
+#define FAIL(WHAT) throw Fail(MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT))
+#define ASSERT(TEST) do { if (!(TEST)) FAIL("assert failed: " << #TEST); } while(false)
+#define ASSERT_EQUAL(WANT, GOT) if ((WANT) != (GOT)) \
+        FAIL(#WANT << " !=  " << #GOT << ": " << WANT << " != " << GOT)
+
+
+string read(string filename) {
+    filename = testsDir+"/interop/"+filename+".amqp";
+    ifstream ifs(filename.c_str());
+    if (!ifs.good()) FAIL("Can't open " << filename);
+    return string(istreambuf_iterator<char>(ifs), istreambuf_iterator<char>());
+}
+
+template <class T> T get(Decoder& d) {
+    T value;
+    d >> exact(value);
+    return value;
+}
+
+template <class T> std::string str(const T& value) {
+    ostringstream oss;
+    oss << value;
+    return oss.str();
+}
+
+// Test Data ostream operator
+void testDataOstream() {
+    Decoder d(read("primitives"));
+    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(d));
+}
+
+// Test extracting to exact AMQP types works corectly, extrating to invalid types fails.
+void testDecoderPrimitvesExact() {
+    Decoder d(read("primitives"));
+    ASSERT(d.more());
+    try { get<int8_t>(d); FAIL("got bool as byte"); } catch(Decoder::Error){}
+    ASSERT_EQUAL(true, get<bool>(d));
+    ASSERT_EQUAL(false, get<bool>(d));
+    try { get<int8_t>(d); FAIL("got ubyte as byte"); } catch(Decoder::Error){}
+    ASSERT_EQUAL(42, get<uint8_t>(d));
+    try { get<int32_t>(d); FAIL("got uint as ushort"); } catch(Decoder::Error){}
+    ASSERT_EQUAL(42, get<uint16_t>(d));
+    try { get<uint16_t>(d); FAIL("got short as ushort"); } catch(Decoder::Error){}
+    ASSERT_EQUAL(-42, get<int16_t>(d));
+    ASSERT_EQUAL(12345, get<uint32_t>(d));
+    ASSERT_EQUAL(-12345, get<int32_t>(d));
+    ASSERT_EQUAL(12345, get<uint64_t>(d));
+    ASSERT_EQUAL(-12345, get<int64_t>(d));
+    try { get<double>(d); FAIL("got float as double"); } catch(Decoder::Error){}
+    ASSERT_EQUAL(0.125, get<float>(d));
+    try { get<float>(d); FAIL("got double as float"); } catch(Decoder::Error){}
+    ASSERT_EQUAL(0.125, get<double>(d));
+    ASSERT(!d.more());
+}
+
+// Test inserting primitive sand encoding as AMQP.
+void testEncoderPrimitives() {
+    Encoder e;
+    e << true << false;
+    e << uint8_t(42);
+    e << uint16_t(42) << int16_t(-42);
+    e << uint32_t(12345) << int32_t(-12345);
+    e << uint64_t(12345) << int64_t(-12345);
+    e << float(0.125) << double(0.125);
+    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(e));
+    std::string data = e.encode();
+    ASSERT_EQUAL(read("primitives"), data);
+}
+
+// Test type conversions.
+void testValueConversions() {
+    Value v;
+    ASSERT_EQUAL(true, bool(v = true));
+    ASSERT_EQUAL(2, int(v=Byte(2)));
+    ASSERT_EQUAL(3, long(v=Byte(3)));
+    ASSERT_EQUAL(3, long(v=Byte(3)));
+    ASSERT_EQUAL(1.0, double(v=Float(1.0)));
+    ASSERT_EQUAL(1.0, float(v=Double(1.0)));
+    try { bool(v = Byte(1)); FAIL("got byte as bool"); } catch (Decoder::Error) {}
+    try { float(v = true); FAIL("got bool as float"); } catch (Decoder::Error) {}
+}
+
+int run_test(void (*testfn)(), const char* name) {
+    try {
+        testfn();
+        return 0;
+    } catch(const Fail& e) {
+        cout << "FAIL " << name << endl << e.what();
+    } catch(const std::exception& e) {
+        cout << "ERROR " << name << endl << e.what();
+    }
+    return 1;
+}
+
+// FIXME aconway 2015-06-11: not testing all types.
+
+#define RUN_TEST(T) run_test(&T, #T)
+
+int main(int argc, char** argv) {
+    int failed = 0;
+    char buf[1024];
+    if (argc != 2) FAIL("Usage: " << argv[0] << " tests-dir" << " IN " << getcwd(buf, sizeof(buf)));
+    testsDir = argv[1];
+
+    failed += RUN_TEST(testDataOstream);
+    failed += RUN_TEST(testDecoderPrimitvesExact);
+    failed += RUN_TEST(testEncoderPrimitives);
+    failed += RUN_TEST(testValueConversions);
+    return failed;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/platform.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/platform.cpp b/proton-c/bindings/cpp/src/platform.cpp
index 4eac408..80e3d51 100644
--- a/proton-c/bindings/cpp/src/platform.cpp
+++ b/proton-c/bindings/cpp/src/platform.cpp
@@ -22,6 +22,8 @@
 #include "platform.h"
 #include <string>
 
+// FIXME aconway 2015-06-09: probably don't need UUIDs in the binding.
+
 // Copy neccesary platform neutral functionality from Proton-C
 // TODO: make this sensibly maintainable (even though it is mostly static)
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/pn_data.h
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/pn_data.h b/proton-c/bindings/cpp/src/pn_data.h
new file mode 100644
index 0000000..371d82c
--- /dev/null
+++ b/proton-c/bindings/cpp/src/pn_data.h
@@ -0,0 +1,30 @@
+#ifndef PN_DATA_H
+#define PN_DATA_H
+/*
+ * 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.
+ */
+
+// Some routines for handling pn_data_t
+
+std::ostream& operator<<(std::ostream& o, const Value& v) {
+    pn_string_t* str = pn_string("");
+    pn_inspect(v.data, str);
+    return o << pn_string_get(str);
+}
+
+#endif // PN_DATA_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/proton_bits.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_bits.cpp b/proton-c/bindings/cpp/src/proton_bits.cpp
new file mode 100644
index 0000000..2e96430
--- /dev/null
+++ b/proton-c/bindings/cpp/src/proton_bits.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#include <string>
+#include <ostream>
+#include <proton/error.h>
+#include <proton/object.h>
+#include "proton_bits.h"
+
+std::string errorStr(int code) {
+  switch (code)
+  {
+  case 0: return "ok";
+  case PN_EOS: return "end of data stream";
+  case PN_ERR: return "error";
+  case PN_OVERFLOW: return "overflow";
+  case PN_UNDERFLOW: return "underflow";
+  case PN_STATE_ERR: return "invalid state";
+  case PN_ARG_ERR: return "invalud argument";
+  case PN_TIMEOUT: return "timeout";
+  case PN_INTR: return "interrupt";
+  default: return "unknown error code";
+  }
+}
+
+std::ostream& operator<<(std::ostream& o, const Object& object) {
+    pn_string_t* str = pn_string("");
+    pn_inspect(object.value, str);
+    o << pn_string_get(str);
+    pn_free(str);
+    return o;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/proton_bits.h
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_bits.h b/proton-c/bindings/cpp/src/proton_bits.h
new file mode 100644
index 0000000..a905172
--- /dev/null
+++ b/proton-c/bindings/cpp/src/proton_bits.h
@@ -0,0 +1,39 @@
+#ifndef ERROR_H
+#define ERROR_H
+/*
+ * 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.
+ */
+
+#include <iosfwd>
+
+/**@file
+ *
+ * Assorted internal proton utilities.
+ */
+std::string errorStr(int code);
+
+/** Wrapper for a proton object pointer. */
+struct Object { void* value; Object(void* o) : value(o) {} };
+
+/** Stream a proton object via pn_inspect. */
+std::ostream& operator<<(std::ostream& o, const Object& object);
+
+
+
+
+#endif // ERROR_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/cpp/src/types.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/types.cpp b/proton-c/bindings/cpp/src/types.cpp
new file mode 100644
index 0000000..127ee7d
--- /dev/null
+++ b/proton-c/bindings/cpp/src/types.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#include "proton/cpp/types.h"
+#include <proton/codec.h>
+
+namespace proton {
+namespace reactor {
+
+const TypeId TypeIdOf<Null>::value = NULL_;
+const TypeId TypeIdOf<Bool>::value = BOOL;
+const TypeId TypeIdOf<Ubyte>::value = UBYTE;
+const TypeId TypeIdOf<Byte>::value = BYTE;
+const TypeId TypeIdOf<Ushort>::value = USHORT;
+const TypeId TypeIdOf<Short>::value = SHORT;
+const TypeId TypeIdOf<Uint>::value = UINT;
+const TypeId TypeIdOf<Int>::value = INT;
+const TypeId TypeIdOf<Char>::value = CHAR;
+const TypeId TypeIdOf<Ulong>::value = ULONG;
+const TypeId TypeIdOf<Long>::value = LONG;
+const TypeId TypeIdOf<Timestamp>::value = TIMESTAMP;
+const TypeId TypeIdOf<Float>::value = FLOAT;
+const TypeId TypeIdOf<Double>::value = DOUBLE;
+const TypeId TypeIdOf<Decimal32>::value = DECIMAL32;
+const TypeId TypeIdOf<Decimal64>::value = DECIMAL64;
+const TypeId TypeIdOf<Decimal128>::value = DECIMAL128;
+const TypeId TypeIdOf<Uuid>::value = UUID;
+const TypeId TypeIdOf<Binary>::value = BINARY;
+const TypeId TypeIdOf<String>::value = STRING;
+const TypeId TypeIdOf<Symbol>::value = SYMBOL;
+
+std::string typeName(TypeId t) {
+    switch (t) {
+      case NULL_: return "null";
+      case BOOL: return "bool";
+      case UBYTE: return "ubyte";
+      case BYTE: return "byte";
+      case USHORT: return "ushort";
+      case SHORT: return "short";
+      case UINT: return "uint";
+      case INT: return "int";
+      case CHAR: return "char";
+      case ULONG: return "ulong";
+      case LONG: return "long";
+      case TIMESTAMP: return "timestamp";
+      case FLOAT: return "float";
+      case DOUBLE: return "double";
+      case DECIMAL32: return "decimal32";
+      case DECIMAL64: return "decimal64";
+      case DECIMAL128: return "decimal128";
+      case UUID: return "uuid";
+      case BINARY: return "binary";
+      case STRING: return "string";
+      case SYMBOL: return "symbol";
+      case DESCRIBED: return "described";
+      case ARRAY: return "array";
+      case LIST: return "list";
+      case  MAP: return "map";
+      default: return "unknown";
+    }
+}
+
+std::string str(const pn_bytes_t& b) { return std::string(b.start, b.size); }
+pn_bytes_t bytes(const std::string& s) { pn_bytes_t b; b.start = &s[0]; b.size = s.size(); return b; }
+
+}}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go b/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go
new file mode 100644
index 0000000..11049f7
--- /dev/null
+++ b/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go
@@ -0,0 +1,308 @@
+/*
+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 amqp
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func assertEqual(want interface{}, got interface{}) {
+	if !reflect.DeepEqual(want, got) {
+		panic(fmt.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("interop/" + name + ".amqp")
+	if err != nil {
+		panic(fmt.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, nil)
+	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, nil)
+	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 != "" {
+		t.Fatalf("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)
+	assertNil(e.Encode(in.s))
+	assertNil(e.Encode(in.i))
+	assertNil(e.Encode(in.u8))
+	assertNil(e.Encode(in.b))
+	assertNil(e.Encode(in.f))
+	assertNil(e.Encode(in.v))
+
+	var out data
+	d := NewDecoder(&buf)
+	assertNil(d.Decode(&out.s))
+	assertNil(d.Decode(&out.i))
+	assertNil(d.Decode(&out.u8))
+	assertNil(d.Decode(&out.b))
+	assertNil(d.Decode(&out.f))
+	assertNil(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, nil)
+	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)
+}
+
+func FIXMETestMessage(t *testing.T) {
+	// FIXME aconway 2015-04-09: integrate Message encoding under marshal/unmarshal API.
+	bytes, err := ioutil.ReadAll(getReader("message"))
+	assertNil(err)
+	m, err := DecodeMessage(bytes)
+	assertNil(err)
+	fmt.Printf("%+v\n", m)
+	assertEqual(m.Body(), "hello")
+
+	bytes2 := make([]byte, len(bytes))
+	bytes2, err = m.Encode(bytes2)
+	assertNil(err)
+	assertEqual(bytes, bytes2)
+}
+
+// FIXME aconway 2015-03-13: finish the full interop test


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org