25 #ifndef INCLUDED_SerializationTraits_h_GUID_DF0CDFE0_097F_41B2_2DAE_7D4033D28D43
26 #define INCLUDED_SerializationTraits_h_GUID_DF0CDFE0_097F_41B2_2DAE_7D4033D28D43
38 #include <boost/call_traits.hpp>
39 #include <boost/noncopyable.hpp>
44 #include <type_traits>
49 namespace serialization {
53 template <
typename Tag>
54 using MissingSerializationTraitsForTagOrType =
55 std::integral_constant<bool, std::is_same<Tag, Tag>::value>;
85 template <
typename Tag,
typename Dummy =
void>
99 static_assert(!MissingSerializationTraitsForTagOrType<Tag>::value,
100 "You must implement a SerializationTraits "
101 "specialization for this type/tag, or at least a "
102 "SimpleStructSerialization!");
107 template <
typename T,
typename BufferType,
109 inline void serializeRaw(BufferType &buf, T
const &v,
110 Tag
const &tag = Tag()) {
116 template <
typename T,
typename BufferReaderType,
117 typename Tag = DefaultSerializationTag<T> >
118 inline void deserializeRaw(BufferReaderType &reader, T &v,
119 Tag
const &tag = Tag()) {
125 template <
typename T,
typename Tag = DefaultSerializationTag<T> >
126 inline size_t getBufferSpaceRequiredRaw(
size_t existingBufferSize,
128 Tag
const &tag = Tag()) {
129 return SerializationTraits<Tag>::spaceRequired(existingBufferSize,
136 typedef typename boost::call_traits<type>::param_type param_type;
137 typedef typename boost::call_traits<type>::value_type value_type;
138 typedef typename boost::call_traits<type>::reference reference_type;
159 typedef void is_specialized;
173 template <
typename T>
186 template <
typename BufferType>
188 typename Base::param_type val,
190 StructSerializeFunctor<BufferType> f(buf);
194 template <
typename BufferReaderType>
196 typename Base::reference_type val,
198 StructDeserializeFunctor<BufferReaderType> f(buf);
202 static size_t spaceRequired(
size_t existingBytes,
203 typename Base::param_type val,
205 StructSpaceRequirementFunctor f(existingBytes);
213 template <
typename BufferType>
214 class StructSerializeFunctor : boost::noncopyable {
217 StructSerializeFunctor(BufferType &buf) : m_buf(buf) {}
221 template <
typename U>
void operator()(U
const &val) {
222 serializeRaw(m_buf, val);
227 template <
typename U,
typename Tag>
228 void operator()(U
const &val, Tag &t) {
229 serializeRaw(m_buf, val, t);
238 template <
typename BufferReaderType>
239 class StructDeserializeFunctor : boost::noncopyable {
242 StructDeserializeFunctor(BufferReaderType &buf) : m_buf(buf) {}
246 template <
typename U>
void operator()(U &val) {
247 deserializeRaw(m_buf, val);
252 template <
typename U,
typename Tag>
253 void operator()(U &val, Tag &t) {
254 deserializeRaw(m_buf, val, t);
258 BufferReaderType &m_buf;
264 class StructSpaceRequirementFunctor : boost::noncopyable {
267 StructSpaceRequirementFunctor(
size_t existingBytes)
268 : m_initialBytes(existingBytes), m_bytes(existingBytes) {}
272 template <
typename U>
void operator()(U
const &val) {
273 m_bytes += getBufferSpaceRequiredRaw(m_bytes, val);
278 template <
typename U,
typename Tag>
279 void operator()(U
const &val, Tag &t) {
280 m_bytes += getBufferSpaceRequiredRaw(m_bytes, val, t);
284 size_t get()
const {
return m_bytes - m_initialBytes; }
287 size_t m_initialBytes;
295 template <
typename T,
size_t Alignment>
300 template <
typename BufferType,
typename Tag>
302 typename Base::param_type val, Tag
const &) {
303 buf.appendAligned(hton(val), Alignment);
307 template <
typename BufferReaderType,
typename Tag>
309 typename Base::reference_type val,
311 buf.readAligned(val, Alignment);
318 template <
typename Tag>
320 typename Base::param_type,
329 template <
typename T>
332 typename
std::enable_if<std::is_arithmetic<T>::value &&
333 !std::is_same<bool, T>::value>::type>
336 static_assert(std::alignment_of<T>::value ==
sizeof(T),
337 "Arithmetic types are assumed to have an alignment "
338 "equal to their size");
353 template <
typename BufferType>
354 static void serialize(BufferType &buf, Base::param_type val,
359 template <
typename BufferReaderType>
361 Base::reference_type val,
364 deserializeRaw(reader, cVal);
368 template <
typename EnumType,
typename IntegerType>
374 template <
typename BufferType>
376 typename Base::param_type val,
378 serializeRaw(buf, static_cast<IntegerType>(val));
381 template <
typename BufferReaderType>
383 typename Base::reference_type val,
386 deserializeRaw(reader, intVal);
387 val =
static_cast<EnumType
>(intVal);
399 typedef uint32_t length_type;
401 template <
typename BufferType>
402 static void serialize(BufferType &buf, Base::param_type val,
404 length_type len = val.length();
405 serializeRaw(buf, len);
406 buf.append(val.c_str(), len);
410 template <
typename BufferReaderType>
412 Base::reference_type val,
415 deserializeRaw(reader, len);
416 auto iter = reader.readBytes(len);
417 val.assign(iter, iter + len);
424 Base::param_type val,
426 return getBufferSpaceRequiredRaw(existingBytes, length_type()) +
440 template <
typename BufferType>
441 static void serialize(BufferType &buf, Base::param_type val,
443 buf.append(val.c_str(), val.length());
446 template <
typename BufferReaderType>
448 Base::reference_type val,
450 auto len = reader.bytesRemaining();
451 auto iter = reader.readBytes(len);
452 val.assign(iter, iter + len);
469 template <
typename BufferType,
typename DataType>
470 static void serialize(BufferType &buf, DataType
const *val,
471 tag_type
const &tag) {
473 reinterpret_cast<typename BufferType::ElementType
const *
>(
475 buf.appendAligned(dataPtr, tag.length(), tag.alignment());
478 template <
typename BufferReaderType,
typename DataType>
479 static void deserialize(BufferReaderType &reader, DataType *val,
480 tag_type
const &tag) {
481 auto len = tag.length();
482 auto iter = reader.readBytesAligned(len, tag.alignment());
483 std::copy(iter, iter + len, val);
489 template <
typename DataType>
491 tag_type
const &tag) {
497 template <
typename ValueType>
501 using value_type = std::vector<ValueType>;
502 using param_type = value_type
const &;
503 using reference_type = value_type &;
507 template <
typename BufferType>
508 static void serialize(BufferType &buf, param_type val,
510 serializeRaw(buf, static_cast<uint32_t>(val.size()));
511 for (
auto &elt : val) {
512 serializeRaw(buf, elt);
516 template <
typename BufferReaderType>
517 static void deserialize(BufferReaderType &buf, reference_type val,
520 deserializeRaw(buf, n);
523 for (uint32_t i = 0; i < n; ++i) {
525 deserializeRaw(buf, elt);
530 static size_t spaceRequired(
size_t existingBytes, param_type val,
532 size_t bytes = existingBytes;
533 bytes += getBufferSpaceRequiredRaw(
534 bytes, static_cast<uint32_t>(val.size()));
535 for (
auto &elt : val) {
536 bytes += getBufferSpaceRequiredRaw(bytes, elt);
538 return bytes - existingBytes;
545 template <
typename F,
typename T>
static void apply(F &f, T &val) {
554 template <
typename F,
typename T>
static void apply(F &f, T &val) {
561 template <
typename Tag>
564 template <
typename F,
typename T>
static void apply(F &f, T &val) {
573 #endif // INCLUDED_SerializationTraits_h_GUID_DF0CDFE0_097F_41B2_2DAE_7D4033D28D43
static void serialize(BufferType &buf, typename Base::param_type val, Tag const &)
Buffers an object of this type.
Base of serialization traits, containing useful typedefs.
uint8_t OSVR_CBool
A pre-C99-safe bool type. Canonical values for true and false are provided. Interpretation of other v...
An alternate, simpler method of serializing things that are effectively structs is to explicitly spec...
#define OSVR_FALSE
Canonical "false" value for OSVR_CBool.
A tag for use for raw data (bytestream), optionally aligned.
void deserialize(BufferReaderType &reader, MessageClass &msg)
Deserializes a message from a buffer, using a MessageClass
Header providing a C-safe "bool" type, because we can't depend on Visual Studio providing proper C99 ...
A tag for use when the only field in a message is a string so the length prefix is unnecessary...
A structure defining a 3D vector, often a position/translation.
void serialize(BufferType &buf, MessageClass &msg)
Serializes a message into a buffer, using a MessageClass
static size_t spaceRequired(size_t, Base::param_type val, tag_type const &)
Returns the number of bytes required for this type (and alignment padding if applicable) to be append...
static void deserialize(BufferReaderType &reader, Base::reference_type val, tag_type const &)
Reads an object of this type from a buffer.
#define OSVR_TRUE
Canonical "true" value for OSVR_CBool.
static size_t spaceRequired(size_t existingBytes, typename Base::param_type, Tag const &)
Returns the number of bytes required for this type (and alignment padding if applicable) to be append...
size_t computeAlignmentPadding(size_t alignment, size_t currentSize)
Given an alignment in bytes, and a current size of a buffer, return the number of bytes of padding re...
typename F::template apply< Args...> apply
Apply an alias class.
Serialization traits for a given arithmetic type (that is, a number type that has a network byte orde...
Used to indicate the kind of integer that should back the serialization of the enum provided...
static size_t spaceRequired(size_t existingBytes, DataType *, tag_type const &tag)
Returns the number of bytes required for this type (and alignment padding if applicable) to be append...
static void deserialize(BufferReaderType &buf, typename Base::reference_type val, Tag const &)
Reads an object of this type from a buffer.
SimpleStructSerialization< T > SimpleSerialization
the SimpleStructSerialization specialization that will take each of our functors and apply them to ev...
A structure defining a 2D vector, which represents position.
The default "type tag" for specifying serialization behavior.
static size_t spaceRequired(size_t existingBytes, Base::param_type val, tag_type const &)
Returns the number of bytes required for this type (and alignment padding if applicable) to be append...
Mandatory base class for SimpleStructSerialization specializations: allows detection of specializatio...
Traits class indicating how to serialize a type with a given tag. The default tag for a type T is Def...