complete motor

Dependencies:   BufferedSerial motor_sn7544

Revision:
11:2228e8931266
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ros/serialization.h	Thu Jul 11 13:30:27 2019 +0000
@@ -0,0 +1,887 @@
+/*
+ * Copyright (C) 2009, Willow Garage, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the names of Willow Garage, Inc. nor the names of its
+ *     contributors may be used to endorse or promote products derived from
+ *     this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ROSCPP_SERIALIZATION_H
+#define ROSCPP_SERIALIZATION_H
+
+#include "roscpp_serialization_macros.h"
+
+#include <ros/types.h>
+#include <ros/time.h>
+
+#include "serialized_message.h"
+#include "ros/message_traits.h"
+#include "ros/builtin_message_traits.h"
+#include "ros/exception.h"
+#include "ros/datatypes.h"
+
+#include <vector>
+#include <map>
+
+#include <boost/array.hpp>
+#include <boost/call_traits.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/not.hpp>
+
+#include <cstring>
+
+#define ROS_NEW_SERIALIZATION_API 1
+
+/**
+ * \brief Declare your serializer to use an allInOne member instead of requiring 3 different serialization
+ * functions.
+ *
+ * The allinone method has the form:
+\verbatim
+template<typename Stream, typename T>
+inline static void allInOne(Stream& stream, T t)
+{
+  stream.next(t.a);
+  stream.next(t.b);
+  ...
+}
+\endverbatim
+ *
+ * The only guarantee given is that Stream::next(T) is defined.
+ */
+#define ROS_DECLARE_ALLINONE_SERIALIZER \
+  template<typename Stream, typename T> \
+  inline static void write(Stream& stream, const T& t) \
+  { \
+    allInOne<Stream, const T&>(stream, t); \
+  } \
+  \
+  template<typename Stream, typename T> \
+  inline static void read(Stream& stream, T& t) \
+  { \
+    allInOne<Stream, T&>(stream, t); \
+  } \
+  \
+  template<typename T> \
+  inline static uint32_t serializedLength(const T& t) \
+  { \
+    LStream stream; \
+    allInOne<LStream, const T&>(stream, t); \
+    return stream.getLength(); \
+  }
+
+namespace ros
+{
+namespace serialization
+{
+namespace mt = message_traits;
+namespace mpl = boost::mpl;
+
+class ROSCPP_SERIALIZATION_DECL StreamOverrunException : public ros::Exception
+{
+public:
+  StreamOverrunException(const std::string& what)
+  : Exception(what)
+  {}
+};
+
+ROSCPP_SERIALIZATION_DECL void throwStreamOverrun();
+
+/**
+ * \brief Templated serialization class.  Default implementation provides backwards compatibility with
+ * old message types.
+ *
+ * Specializing the Serializer class is the only thing you need to do to get the ROS serialization system
+ * to work with a type.
+ */
+template<typename T>
+struct Serializer
+{
+  /**
+   * \brief Write an object to the stream.  Normally the stream passed in here will be a ros::serialization::OStream
+   */
+  template<typename Stream>
+  inline static void write(Stream& stream, typename boost::call_traits<T>::param_type t)
+  {
+    t.serialize(stream.getData(), 0);
+  }
+
+  /**
+   * \brief Read an object from the stream.  Normally the stream passed in here will be a ros::serialization::IStream
+   */
+  template<typename Stream>
+  inline static void read(Stream& stream, typename boost::call_traits<T>::reference t)
+  {
+    t.deserialize(stream.getData());
+  }
+
+  /**
+   * \brief Determine the serialized length of an object.
+   */
+  inline static uint32_t serializedLength(typename boost::call_traits<T>::param_type t)
+  {
+    return t.serializationLength();
+  }
+};
+
+/**
+ * \brief Serialize an object.  Stream here should normally be a ros::serialization::OStream
+ */
+template<typename T, typename Stream>
+inline void serialize(Stream& stream, const T& t)
+{
+  Serializer<T>::write(stream, t);
+}
+
+/**
+ * \brief Deserialize an object.  Stream here should normally be a ros::serialization::IStream
+ */
+template<typename T, typename Stream>
+inline void deserialize(Stream& stream, T& t)
+{
+  Serializer<T>::read(stream, t);
+}
+
+/**
+ * \brief Determine the serialized length of an object
+ */
+template<typename T>
+inline uint32_t serializationLength(const T& t)
+{
+  return Serializer<T>::serializedLength(t);
+}
+
+#define ROS_CREATE_SIMPLE_SERIALIZER(Type) \
+  template<> struct Serializer<Type> \
+  { \
+    template<typename Stream> inline static void write(Stream& stream, const Type v) \
+    { \
+      memcpy(stream.advance(sizeof(v)), &v, sizeof(v) ); \
+    } \
+    \
+    template<typename Stream> inline static void read(Stream& stream, Type& v) \
+    { \
+      memcpy(&v, stream.advance(sizeof(v)), sizeof(v) ); \
+    } \
+    \
+    inline static uint32_t serializedLength(const Type&) \
+      { \
+      return sizeof(Type); \
+    } \
+};
+
+ROS_CREATE_SIMPLE_SERIALIZER(uint8_t)
+ROS_CREATE_SIMPLE_SERIALIZER(int8_t)
+ROS_CREATE_SIMPLE_SERIALIZER(uint16_t)
+ROS_CREATE_SIMPLE_SERIALIZER(int16_t)
+ROS_CREATE_SIMPLE_SERIALIZER(uint32_t)
+ROS_CREATE_SIMPLE_SERIALIZER(int32_t)
+ROS_CREATE_SIMPLE_SERIALIZER(uint64_t)
+ROS_CREATE_SIMPLE_SERIALIZER(int64_t)
+ROS_CREATE_SIMPLE_SERIALIZER(float)
+ROS_CREATE_SIMPLE_SERIALIZER(double)
+
+/**
+ * \brief Serializer specialized for bool (serialized as uint8)
+ */
+template<> struct Serializer<bool>
+{
+  template<typename Stream> inline static void write(Stream& stream, const bool v)
+  {
+    uint8_t b = (uint8_t)v;
+    memcpy(stream.advance(1), &b, 1 );
+  }
+
+  template<typename Stream> inline static void read(Stream& stream, bool& v)
+  {
+    uint8_t b;
+    memcpy(&b, stream.advance(1), 1 );
+    v = (bool)b;
+  }
+
+  inline static uint32_t serializedLength(bool)
+  {
+    return 1;
+  }
+};
+
+/**
+ * \brief  Serializer specialized for std::string
+ */
+template<class ContainerAllocator>
+struct Serializer<std::basic_string<char, std::char_traits<char>, ContainerAllocator> >
+{
+  typedef std::basic_string<char, std::char_traits<char>, ContainerAllocator> StringType;
+
+  template<typename Stream>
+  inline static void write(Stream& stream, const StringType& str)
+  {
+    size_t len = str.size();
+    stream.next((uint32_t)len);
+
+    if (len > 0)
+    {
+      memcpy(stream.advance((uint32_t)len), str.data(), len);
+    }
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, StringType& str)
+  {
+    uint32_t len;
+    stream.next(len);
+    if (len > 0)
+    {
+      str = StringType((char*)stream.advance(len), len);
+    }
+    else
+    {
+      str.clear();
+    }
+  }
+
+  inline static uint32_t serializedLength(const StringType& str)
+  {
+    return 4 + (uint32_t)str.size();
+  }
+};
+
+/**
+ * \brief Serializer specialized for ros::Time
+ */
+template<>
+struct Serializer<ros::Time>
+{
+  template<typename Stream>
+  inline static void write(Stream& stream, const ros::Time& v)
+  {
+    stream.next(v.sec);
+    stream.next(v.nsec);
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, ros::Time& v)
+  {
+    stream.next(v.sec);
+    stream.next(v.nsec);
+  }
+
+  inline static uint32_t serializedLength(const ros::Time&)
+  {
+    return 8;
+  }
+};
+
+/**
+ * \brief Serializer specialized for ros::Duration
+ */
+template<>
+struct Serializer<ros::Duration>
+{
+  template<typename Stream>
+  inline static void write(Stream& stream, const ros::Duration& v)
+  {
+    stream.next(v.sec);
+    stream.next(v.nsec);
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, ros::Duration& v)
+  {
+    stream.next(v.sec);
+    stream.next(v.nsec);
+  }
+
+  inline static uint32_t serializedLength(const ros::Duration&)
+  {
+    return 8;
+  }
+};
+
+/**
+ * \brief Vector serializer.  Default implementation does nothing
+ */
+template<typename T, class ContainerAllocator, class Enabled = void>
+struct VectorSerializer
+{};
+
+/**
+ * \brief Vector serializer, specialized for non-fixed-size, non-simple types
+ */
+template<typename T, class ContainerAllocator>
+struct VectorSerializer<T, ContainerAllocator, typename boost::disable_if<mt::IsFixedSize<T> >::type >
+{
+  typedef std::vector<T, typename ContainerAllocator::template rebind<T>::other> VecType;
+  typedef typename VecType::iterator IteratorType;
+  typedef typename VecType::const_iterator ConstIteratorType;
+
+  template<typename Stream>
+  inline static void write(Stream& stream, const VecType& v)
+  {
+    stream.next((uint32_t)v.size());
+    ConstIteratorType it = v.begin();
+    ConstIteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, VecType& v)
+  {
+    uint32_t len;
+    stream.next(len);
+    v.resize(len);
+    IteratorType it = v.begin();
+    IteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  inline static uint32_t serializedLength(const VecType& v)
+  {
+    uint32_t size = 4;
+    ConstIteratorType it = v.begin();
+    ConstIteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      size += serializationLength(*it);
+    }
+
+    return size;
+  }
+};
+
+/**
+ * \brief Vector serializer, specialized for fixed-size simple types
+ */
+template<typename T, class ContainerAllocator>
+struct VectorSerializer<T, ContainerAllocator, typename boost::enable_if<mt::IsSimple<T> >::type >
+{
+  typedef std::vector<T, typename ContainerAllocator::template rebind<T>::other> VecType;
+  typedef typename VecType::iterator IteratorType;
+  typedef typename VecType::const_iterator ConstIteratorType;
+
+  template<typename Stream>
+  inline static void write(Stream& stream, const VecType& v)
+  {
+    uint32_t len = (uint32_t)v.size();
+    stream.next(len);
+    if (!v.empty())
+    {
+      const uint32_t data_len = len * (uint32_t)sizeof(T);
+      memcpy(stream.advance(data_len), &v.front(), data_len);
+    }
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, VecType& v)
+  {
+    uint32_t len;
+    stream.next(len);
+    v.resize(len);
+
+    if (len > 0)
+    {
+      const uint32_t data_len = (uint32_t)sizeof(T) * len;
+      memcpy(&v.front(), stream.advance(data_len), data_len);
+    }
+  }
+
+  inline static uint32_t serializedLength(const VecType& v)
+  {
+    return 4 + v.size() * (uint32_t)sizeof(T);
+  }
+};
+
+/**
+ * \brief Vector serializer, specialized for fixed-size non-simple types
+ */
+template<typename T, class ContainerAllocator>
+struct VectorSerializer<T, ContainerAllocator, typename boost::enable_if<mpl::and_<mt::IsFixedSize<T>, mpl::not_<mt::IsSimple<T> > > >::type >
+{
+  typedef std::vector<T, typename ContainerAllocator::template rebind<T>::other> VecType;
+  typedef typename VecType::iterator IteratorType;
+  typedef typename VecType::const_iterator ConstIteratorType;
+
+  template<typename Stream>
+  inline static void write(Stream& stream, const VecType& v)
+  {
+    stream.next((uint32_t)v.size());
+    ConstIteratorType it = v.begin();
+    ConstIteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, VecType& v)
+  {
+    uint32_t len;
+    stream.next(len);
+    v.resize(len);
+    IteratorType it = v.begin();
+    IteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  inline static uint32_t serializedLength(const VecType& v)
+  {
+    uint32_t size = 4;
+    if (!v.empty())
+    {
+      uint32_t len_each = serializationLength(v.front());
+      size += len_each * (uint32_t)v.size();
+    }
+
+    return size;
+  }
+};
+
+/**
+ * \brief serialize version for std::vector
+ */
+template<typename T, class ContainerAllocator, typename Stream>
+inline void serialize(Stream& stream, const std::vector<T, ContainerAllocator>& t)
+{
+  VectorSerializer<T, ContainerAllocator>::write(stream, t);
+}
+
+/**
+ * \brief deserialize version for std::vector
+ */
+template<typename T, class ContainerAllocator, typename Stream>
+inline void deserialize(Stream& stream, std::vector<T, ContainerAllocator>& t)
+{
+  VectorSerializer<T, ContainerAllocator>::read(stream, t);
+}
+
+/**
+ * \brief serializationLength version for std::vector
+ */
+template<typename T, class ContainerAllocator>
+inline uint32_t serializationLength(const std::vector<T, ContainerAllocator>& t)
+{
+  return VectorSerializer<T, ContainerAllocator>::serializedLength(t);
+}
+
+/**
+ * \brief Array serializer, default implementation does nothing
+ */
+template<typename T, size_t N, class Enabled = void>
+struct ArraySerializer
+{};
+
+/**
+ * \brief Array serializer, specialized for non-fixed-size, non-simple types
+ */
+template<typename T, size_t N>
+struct ArraySerializer<T, N, typename boost::disable_if<mt::IsFixedSize<T> >::type>
+{
+  typedef boost::array<T, N > ArrayType;
+  typedef typename ArrayType::iterator IteratorType;
+  typedef typename ArrayType::const_iterator ConstIteratorType;
+
+  template<typename Stream>
+  inline static void write(Stream& stream, const ArrayType& v)
+  {
+    ConstIteratorType it = v.begin();
+    ConstIteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, ArrayType& v)
+  {
+    IteratorType it = v.begin();
+    IteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  inline static uint32_t serializedLength(const ArrayType& v)
+  {
+    uint32_t size = 0;
+    ConstIteratorType it = v.begin();
+    ConstIteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      size += serializationLength(*it);
+    }
+
+    return size;
+  }
+};
+
+/**
+ * \brief Array serializer, specialized for fixed-size, simple types
+ */
+template<typename T, size_t N>
+struct ArraySerializer<T, N, typename boost::enable_if<mt::IsSimple<T> >::type>
+{
+  typedef boost::array<T, N > ArrayType;
+  typedef typename ArrayType::iterator IteratorType;
+  typedef typename ArrayType::const_iterator ConstIteratorType;
+
+  template<typename Stream>
+  inline static void write(Stream& stream, const ArrayType& v)
+  {
+    const uint32_t data_len = N * sizeof(T);
+    memcpy(stream.advance(data_len), &v.front(), data_len);
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, ArrayType& v)
+  {
+    const uint32_t data_len = N * sizeof(T);
+    memcpy(&v.front(), stream.advance(data_len), data_len);
+  }
+
+  inline static uint32_t serializedLength(const ArrayType&)
+  {
+    return N * sizeof(T);
+  }
+};
+
+/**
+ * \brief Array serializer, specialized for fixed-size, non-simple types
+ */
+template<typename T, size_t N>
+struct ArraySerializer<T, N, typename boost::enable_if<mpl::and_<mt::IsFixedSize<T>, mpl::not_<mt::IsSimple<T> > > >::type>
+{
+  typedef boost::array<T, N > ArrayType;
+  typedef typename ArrayType::iterator IteratorType;
+  typedef typename ArrayType::const_iterator ConstIteratorType;
+
+  template<typename Stream>
+  inline static void write(Stream& stream, const ArrayType& v)
+  {
+    ConstIteratorType it = v.begin();
+    ConstIteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  template<typename Stream>
+  inline static void read(Stream& stream, ArrayType& v)
+  {
+    IteratorType it = v.begin();
+    IteratorType end = v.end();
+    for (; it != end; ++it)
+    {
+      stream.next(*it);
+    }
+  }
+
+  inline static uint32_t serializedLength(const ArrayType& v)
+  {
+    return serializationLength(v.front()) * N;
+  }
+};
+
+/**
+ * \brief serialize version for boost::array
+ */
+template<typename T, size_t N, typename Stream>
+inline void serialize(Stream& stream, const boost::array<T, N>& t)
+{
+  ArraySerializer<T, N>::write(stream, t);
+}
+
+/**
+ * \brief deserialize version for boost::array
+ */
+template<typename T, size_t N, typename Stream>
+inline void deserialize(Stream& stream, boost::array<T, N>& t)
+{
+  ArraySerializer<T, N>::read(stream, t);
+}
+
+/**
+ * \brief serializationLength version for boost::array
+ */
+template<typename T, size_t N>
+inline uint32_t serializationLength(const boost::array<T, N>& t)
+{
+  return ArraySerializer<T, N>::serializedLength(t);
+}
+
+/**
+ * \brief Enum
+ */
+namespace stream_types
+{
+enum StreamType
+{
+  Input,
+  Output,
+  Length
+};
+}
+typedef stream_types::StreamType StreamType;
+
+/**
+ * \brief Stream base-class, provides common functionality for IStream and OStream
+ */
+struct ROSCPP_SERIALIZATION_DECL Stream
+{
+  /*
+   * \brief Returns a pointer to the current position of the stream
+   */
+  inline uint8_t* getData() { return data_; }
+  /**
+   * \brief Advances the stream, checking bounds, and returns a pointer to the position before it
+   * was advanced.
+   * \throws StreamOverrunException if len would take this stream past the end of its buffer
+   */
+  ROS_FORCE_INLINE uint8_t* advance(uint32_t len)
+  {
+    uint8_t* old_data = data_;
+    data_ += len;
+    if (data_ > end_)
+    {
+      // Throwing directly here causes a significant speed hit due to the extra code generated
+      // for the throw statement
+      throwStreamOverrun();
+    }
+    return old_data;
+  }
+
+  /**
+   * \brief Returns the amount of space left in the stream
+   */
+  inline uint32_t getLength() { return (uint32_t)(end_ - data_); }
+
+protected:
+  Stream(uint8_t* _data, uint32_t _count)
+  : data_(_data)
+  , end_(_data + _count)
+  {}
+
+private:
+  uint8_t* data_;
+  uint8_t* end_;
+};
+
+/**
+ * \brief Input stream
+ */
+struct ROSCPP_SERIALIZATION_DECL IStream : public Stream
+{
+  static const StreamType stream_type = stream_types::Input;
+
+  IStream(uint8_t* data, uint32_t count)
+  : Stream(data, count)
+  {}
+
+  /**
+   * \brief Deserialize an item from this input stream
+   */
+  template<typename T>
+  ROS_FORCE_INLINE void next(T& t)
+  {
+    deserialize(*this, t);
+  }
+
+  template<typename T>
+  ROS_FORCE_INLINE IStream& operator>>(T& t)
+  {
+    deserialize(*this, t);
+    return *this;
+  }
+};
+
+/**
+ * \brief Output stream
+ */
+struct ROSCPP_SERIALIZATION_DECL OStream : public Stream
+{
+  static const StreamType stream_type = stream_types::Output;
+
+  OStream(uint8_t* data, uint32_t count)
+  : Stream(data, count)
+  {}
+
+  /**
+   * \brief Serialize an item to this output stream
+   */
+  template<typename T>
+  ROS_FORCE_INLINE void next(const T& t)
+  {
+    serialize(*this, t);
+  }
+
+  template<typename T>
+  ROS_FORCE_INLINE OStream& operator<<(const T& t)
+  {
+    serialize(*this, t);
+    return *this;
+  }
+};
+
+
+/**
+ * \brief Length stream
+ *
+ * LStream is not what you would normally think of as a stream, but it is used in order to support
+ * allinone serializers.
+ */
+struct ROSCPP_SERIALIZATION_DECL LStream
+{
+  static const StreamType stream_type = stream_types::Length;
+
+  LStream()
+  : count_(0)
+  {}
+
+  /**
+   * \brief Add the length of an item to this length stream
+   */
+  template<typename T>
+  ROS_FORCE_INLINE void next(const T& t)
+  {
+    count_ += serializationLength(t);
+  }
+
+  /**
+   * \brief increment the length by len
+   */
+  ROS_FORCE_INLINE uint32_t advance(uint32_t len)
+  {
+    uint32_t old = count_;
+    count_ += len;
+    return old;
+  }
+
+  /**
+   * \brief Get the total length of this tream
+   */
+  inline uint32_t getLength() { return count_; }
+
+private:
+  uint32_t count_;
+};
+
+/**
+ * \brief Serialize a message
+ */
+template<typename M>
+inline SerializedMessage serializeMessage(const M& message)
+{
+  SerializedMessage m;
+  uint32_t len = serializationLength(message);
+  m.num_bytes = len + 4;
+  m.buf.reset(new uint8_t[m.num_bytes]);
+
+  OStream s(m.buf.get(), (uint32_t)m.num_bytes);
+  serialize(s, (uint32_t)m.num_bytes - 4);
+  m.message_start = s.getData();
+  serialize(s, message);
+
+  return m;
+}
+
+/**
+ * \brief Serialize a service response
+ */
+template<typename M>
+inline SerializedMessage serializeServiceResponse(bool ok, const M& message)
+{
+  SerializedMessage m;
+
+  if (ok)
+  {
+    uint32_t len = serializationLength(message);
+    m.num_bytes = len + 5;
+    m.buf.reset(new uint8_t[m.num_bytes]);
+
+    OStream s(m.buf.get(), (uint32_t)m.num_bytes);
+    serialize(s, (uint8_t)ok);
+    serialize(s, (uint32_t)m.num_bytes - 5);
+    serialize(s, message);
+  }
+  else
+  {
+    uint32_t len = serializationLength(message);
+    m.num_bytes = len + 1;
+    m.buf.reset(new uint8_t[m.num_bytes]);
+
+    OStream s(m.buf.get(), (uint32_t)m.num_bytes);
+    serialize(s, (uint8_t)ok);
+    serialize(s, message);
+  }
+
+  return m;
+}
+
+/**
+ * \brief Deserialize a message.  If includes_length is true, skips the first 4 bytes
+ */
+template<typename M>
+inline void deserializeMessage(const SerializedMessage& m, M& message)
+{
+  IStream s(m.message_start, m.num_bytes - (m.message_start - m.buf.get()));
+  deserialize(s, message);
+}
+
+
+// Additional serialization traits
+
+template<typename M>
+struct PreDeserializeParams
+{
+  boost::shared_ptr<M> message;
+  boost::shared_ptr<std::map<std::string, std::string> > connection_header;
+};
+
+/**
+ * \brief called by the SubscriptionCallbackHelper after a message is
+ * instantiated but before that message is deserialized
+ */
+template<typename M>
+struct PreDeserialize
+{
+  static void notify(const PreDeserializeParams<M>&) { }
+};
+
+} // namespace serialization
+
+} // namespace ros
+
+#endif // ROSCPP_SERIALIZATION_H
\ No newline at end of file