AutobahnCpp Custom Types

#1

Now that I am trying to use this library for more meaningful problems I just found out that custom types are not easy to support. For example, here is how we pack types from boost::any. How would one go about adding support for a custom types?

template<typename IStream, typename OStream>

void session<IStream, OStream>::pack_any(const boost::any& value)

{

if (value.empty()) {

m_packer.pack_nil();

} else if (value.type() == typeid(anyvec)) {

anyvec v = boost::any_cast(value);

m_packer.pack_array(v.size());

anyvec::iterator it = v.begin();

while (it != v.end()) {

pack_any(*it);

++it;

}

} else if (value.type() == typeid(anymap)) {

anymap m = boost::any_cast(value);

m_packer.pack_map(m.size());

anymap::iterator it = m.begin();

while (it != m.end()) {

m_packer.pack(it->first); // std::string

pack_any(it->second);

++it;

}

} else if (value.type() == typeid(int)) {

int val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(uint64_t)) {

uint64_t val = boost::any_cast<uint64_t>(value);

m_packer.pack(val);

} else if (value.type() == typeid(bool)) {

bool val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(float)) {

float val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(double)) {

double val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(std::string)) {

std::string val = boost::any_caststd::string(value);

m_packer.pack(val);

} else {

// TODO: Revisit this as I suspect that we should be asserting

// here or throwing some kind of exception.

std::cerr << "Warning: don’t know how to pack type " << value.type().name() << std::endl;

}

}

``

0 Likes

#2

Just giving this a bit more thought, even if there was some way to extend this chain of typeid comparisons the performance of this is pretty terrible. The typeid comparisons are pretty expensive. Imagine if we had a 100+ custom types to deal with. Ideally we would use a templated functor to deal with this just like say std::hash does but unfortunately this doesn’t seem possible to do with boost::any as the variant type.

···

On Wednesday, 6 May 2015 17:55:52 UTC-4, David Chappelle wrote:

Now that I am trying to use this library for more meaningful problems I just found out that custom types are not easy to support. For example, here is how we pack types from boost::any. How would one go about adding support for a custom types?

template<typename IStream, typename OStream>

void session<IStream, OStream>::pack_any(const boost::any& value)

{

if (value.empty()) {

m_packer.pack_nil();

} else if (value.type() == typeid(anyvec)) {

anyvec v = boost::any_cast(value);

m_packer.pack_array(v.size());

anyvec::iterator it = v.begin();

while (it != v.end()) {

pack_any(*it);

++it;

}

} else if (value.type() == typeid(anymap)) {

anymap m = boost::any_cast(value);

m_packer.pack_map(m.size());

anymap::iterator it = m.begin();

while (it != m.end()) {

m_packer.pack(it->first); // std::string

pack_any(it->second);

++it;

}

} else if (value.type() == typeid(int)) {

int val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(uint64_t)) {

uint64_t val = boost::any_cast<uint64_t>(value);

m_packer.pack(val);

} else if (value.type() == typeid(bool)) {

bool val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(float)) {

float val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(double)) {

double val = boost::any_cast(value);

m_packer.pack(val);

} else if (value.type() == typeid(std::string)) {

std::string val = boost::any_caststd::string(value);

m_packer.pack(val);

} else {

// TODO: Revisit this as I suspect that we should be asserting

// here or throwing some kind of exception.

std::cerr << "Warning: don’t know how to pack type " << value.type().name() << std::endl;

}

}

``

0 Likes

#3

I don’t know if this will help, but C++11 added std::type_info::hash_code, as well as std::type_index. Both are intended to make the result of typeid be usable in associative containers.

Also, I think session<I,O>::pack_any is the wrong layer to be adding custom types. This layer should only be concerned with the “fundamental” JSON types (bool, number, string, array, object). Encoding/decoding custom types should be done at a higher, app-level layer.

I find Boost.Serialization to be a nice source of inspiration for implementing app-level serialization. http://uscilab.github.io/cereal/ is a more modern incarnation that handles XML and JSON.

Hope this helps,

Emile

···

On Wednesday, May 6, 2015 at 7:13:07 PM UTC-3, David Chappelle wrote:

Just giving this a bit more thought, even if there was some way to extend this chain of typeid comparisons the performance of this is pretty terrible. The typeid comparisons are pretty expensive. Imagine if we had a 100+ custom types to deal with. Ideally we would use a templated functor to deal with this just like say std::hash does but unfortunately this doesn’t seem possible to do with boost::any as the variant type.

0 Likes

#4

I forgot to mention that if you’re going to consider an approach similar to Boost.Serialization, you can think of boost::any as being the “archive”.

···

On Thursday, May 14, 2015 at 6:08:10 PM UTC-3, Emile Cormier wrote:

I find Boost.Serialization to be a nice source of inspiration for implementing app-level serialization. http://uscilab.github.io/cereal/ is a more modern incarnation that handles XML and JSON.

0 Likes

#5

I decided to go with msgpack::object as the variant type. It has all of the support one needs for adding custom types. It is also trivial to convert between msgpack and json if needed. It is actually not too dissimilar to the variant type you defined for cppwamp.

···

On Thu, May 14, 2015 at 6:05 PM, Emile Cormier emile.co...@gmail.com wrote:

On Thursday, May 14, 2015 at 6:08:10 PM UTC-3, Emile Cormier wrote:

I find Boost.Serialization to be a nice source of inspiration for implementing app-level serialization. http://uscilab.github.io/cereal/ is a more modern incarnation that handles XML and JSON.

I forgot to mention that if you’re going to consider an approach similar to Boost.Serialization, you can think of boost::any as being the “archive”.

You received this message because you are subscribed to a topic in the Google Groups “Autobahn” group.

To unsubscribe from this topic, visit https://groups.google.com/d/topic/autobahnws/jkj1HcCIXCo/unsubscribe.

To unsubscribe from this group and all its topics, send an email to autobahnws+...@googlegroups.com.

To post to this group, send email to autob...@googlegroups.com.

To view this discussion on the web visit https://groups.google.com/d/msgid/autobahnws/3183ab2b-b4a3-4d37-81f9-c7bf19c76112%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

0 Likes