OSVR-Core
SerializationTraits.h
Go to the documentation of this file.
1 
11 // Copyright 2015 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 #ifndef INCLUDED_SerializationTraits_h_GUID_DF0CDFE0_097F_41B2_2DAE_7D4033D28D43
26 #define INCLUDED_SerializationTraits_h_GUID_DF0CDFE0_097F_41B2_2DAE_7D4033D28D43
27 
28 // Internal Includes
30 #include <osvr/Common/Endianness.h>
32 #include <osvr/Util/BoolC.h>
33 #include <osvr/Util/Vec2C.h>
34 #include <osvr/Util/Vec3C.h>
35 #include <osvr/Util/TypeSafeId.h>
36 
37 // Library/third-party includes
38 #include <boost/call_traits.hpp>
39 #include <boost/noncopyable.hpp>
40 
41 // Standard includes
42 #include <string>
43 #include <vector>
44 #include <type_traits>
45 
46 namespace osvr {
47 namespace common {
48 
49  namespace serialization {
50 
53  template <typename Tag>
55  std::integral_constant<bool, std::is_same<Tag, Tag>::value>;
56 
85  template <typename Tag, typename Dummy = void>
100  "You must implement a SerializationTraits "
101  "specialization for this type/tag, or at least a "
102  "SimpleStructSerialization!");
103  };
104 
107  template <typename T, typename BufferType,
108  typename Tag = DefaultSerializationTag<T> >
109  inline void serializeRaw(BufferType &buf, T const &v,
110  Tag const &tag = Tag()) {
112  }
113 
116  template <typename T, typename BufferReaderType,
117  typename Tag = DefaultSerializationTag<T> >
118  inline void deserializeRaw(BufferReaderType &reader, T &v,
119  Tag const &tag = Tag()) {
121  }
122 
125  template <typename T, typename Tag = DefaultSerializationTag<T> >
126  inline size_t getBufferSpaceRequiredRaw(size_t existingBufferSize,
127  T const &v,
128  Tag const &tag = Tag()) {
129  return SerializationTraits<Tag>::spaceRequired(existingBufferSize,
130  v, tag);
131  }
132 
134  template <typename T> struct BaseSerializationTraits {
135  typedef T type;
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;
139  };
140 
153  template <typename T> struct SimpleStructSerialization;
154 
159  typedef void is_specialized;
160  };
161 
173  template <typename T>
176  typename SimpleStructSerialization<T>::is_specialized>
178 
181 
185 
186  template <typename BufferType>
187  static void serialize(BufferType &buf,
188  typename Base::param_type val,
189  tag_type const &) {
190  StructSerializeFunctor<BufferType> f(buf);
192  }
193 
194  template <typename BufferReaderType>
195  static void deserialize(BufferReaderType &buf,
196  typename Base::reference_type val,
197  tag_type const &) {
198  StructDeserializeFunctor<BufferReaderType> f(buf);
200  }
201 
202  static size_t spaceRequired(size_t existingBytes,
203  typename Base::param_type val,
204  tag_type const &) {
205  StructSpaceRequirementFunctor f(existingBytes);
207  return f.get();
208  }
209 
210  private:
213  template <typename BufferType>
214  class StructSerializeFunctor : boost::noncopyable {
215  public:
217  StructSerializeFunctor(BufferType &buf) : m_buf(buf) {}
218 
221  template <typename U> void operator()(U const &val) {
222  serializeRaw(m_buf, val);
223  }
224 
227  template <typename U, typename Tag>
228  void operator()(U const &val, Tag &t) {
229  serializeRaw(m_buf, val, t);
230  }
231 
232  private:
233  BufferType &m_buf;
234  };
235 
238  template <typename BufferReaderType>
239  class StructDeserializeFunctor : boost::noncopyable {
240  public:
242  StructDeserializeFunctor(BufferReaderType &buf) : m_buf(buf) {}
243 
246  template <typename U> void operator()(U &val) {
247  deserializeRaw(m_buf, val);
248  }
249 
252  template <typename U, typename Tag>
253  void operator()(U &val, Tag &t) {
254  deserializeRaw(m_buf, val, t);
255  }
256 
257  private:
258  BufferReaderType &m_buf;
259  };
260 
264  class StructSpaceRequirementFunctor : boost::noncopyable {
265  public:
267  StructSpaceRequirementFunctor(size_t existingBytes)
268  : m_initialBytes(existingBytes), m_bytes(existingBytes) {}
269 
272  template <typename U> void operator()(U const &val) {
273  m_bytes += getBufferSpaceRequiredRaw(m_bytes, val);
274  }
275 
278  template <typename U, typename Tag>
279  void operator()(U const &val, Tag &t) {
280  m_bytes += getBufferSpaceRequiredRaw(m_bytes, val, t);
281  }
282 
284  size_t get() const { return m_bytes - m_initialBytes; }
285 
286  private:
287  size_t m_initialBytes;
288  size_t m_bytes;
289  };
290  };
291 
295  template <typename T, size_t Alignment>
298  typedef T type;
300  template <typename BufferType, typename Tag>
301  static void serialize(BufferType &buf,
302  typename Base::param_type val, Tag const &) {
303  buf.appendAligned(hton(val), Alignment);
304  }
305 
307  template <typename BufferReaderType, typename Tag>
308  static void deserialize(BufferReaderType &buf,
309  typename Base::reference_type val,
310  Tag const &) {
311  buf.readAligned(val, Alignment);
312  val = ntoh(val);
313  }
314 
318  template <typename Tag>
319  static size_t spaceRequired(size_t existingBytes,
320  typename Base::param_type,
321  Tag const &) {
322  return computeAlignmentPadding(Alignment, existingBytes) +
323  sizeof(T);
324  }
325  };
326 
329  template <typename T>
332  typename std::enable_if<std::is_arithmetic<T>::value &&
333  !std::is_same<bool, T>::value>::type>
334  : ArithmeticSerializationTraits<T, sizeof(T)> {
335 
336  static_assert(std::alignment_of<T>::value == sizeof(T),
337  "Arithmetic types are assumed to have an alignment "
338  "equal to their size");
339  };
340 
346  template <>
348  : BaseSerializationTraits<bool> {
349 
352 
353  template <typename BufferType>
354  static void serialize(BufferType &buf, Base::param_type val,
355  tag_type const &) {
356  serializeRaw(
357  buf, static_cast<OSVR_CBool>(val ? OSVR_TRUE : OSVR_FALSE));
358  }
359  template <typename BufferReaderType>
360  static void deserialize(BufferReaderType &reader,
361  Base::reference_type val,
362  tag_type const &) {
363  OSVR_CBool cVal;
364  deserializeRaw(reader, cVal);
365  val = (cVal == OSVR_TRUE);
366  }
367  };
368  template <typename EnumType, typename IntegerType>
369  struct SerializationTraits<EnumAsIntegerTag<EnumType, IntegerType>,
370  void> : BaseSerializationTraits<EnumType> {
373 
374  template <typename BufferType>
375  static void serialize(BufferType &buf,
376  typename Base::param_type val,
377  tag_type const &) {
378  serializeRaw(buf, static_cast<IntegerType>(val));
379  }
380 
381  template <typename BufferReaderType>
382  static void deserialize(BufferReaderType &reader,
383  typename Base::reference_type val,
384  tag_type const &) {
385  IntegerType intVal;
386  deserializeRaw(reader, intVal);
387  val = static_cast<EnumType>(intVal);
388  }
389  };
390 
392  template <>
394  : BaseSerializationTraits<std::string> {
395 
398 
399  typedef uint32_t length_type;
400 
401  template <typename BufferType>
402  static void serialize(BufferType &buf, Base::param_type val,
403  tag_type const &) {
404  length_type len = val.length();
405  serializeRaw(buf, len);
406  buf.append(val.c_str(), len);
407  }
408 
410  template <typename BufferReaderType>
411  static void deserialize(BufferReaderType &reader,
412  Base::reference_type val,
413  tag_type const &) {
414  length_type len;
415  deserializeRaw(reader, len);
416  auto iter = reader.readBytes(len);
417  val.assign(iter, iter + len);
418  }
419 
423  static size_t spaceRequired(size_t existingBytes,
424  Base::param_type val,
425  tag_type const &) {
426  return getBufferSpaceRequiredRaw(existingBytes, length_type()) +
427  val.length();
428  }
429  };
430 
433  template <>
435  : BaseSerializationTraits<std::string> {
436 
439 
440  template <typename BufferType>
441  static void serialize(BufferType &buf, Base::param_type val,
442  tag_type const &) {
443  buf.append(val.c_str(), val.length());
444  }
445 
446  template <typename BufferReaderType>
447  static void deserialize(BufferReaderType &reader,
448  Base::reference_type val,
449  tag_type const &) {
450  auto len = reader.bytesRemaining();
451  auto iter = reader.readBytes(len);
452  val.assign(iter, iter + len);
453  }
454 
458  static size_t spaceRequired(size_t, Base::param_type val,
459  tag_type const &) {
460  return val.length();
461  }
462  };
463 
466  template <> struct SerializationTraits<AlignedDataBufferTag, void> {
468 
469  template <typename BufferType, typename DataType>
470  static void serialize(BufferType &buf, DataType const *val,
471  tag_type const &tag) {
472  auto dataPtr =
473  reinterpret_cast<typename BufferType::ElementType const *>(
474  val);
475  buf.appendAligned(dataPtr, tag.length(), tag.alignment());
476  }
477 
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);
484  }
485 
489  template <typename DataType>
490  static size_t spaceRequired(size_t existingBytes, DataType *,
491  tag_type const &tag) {
492  return computeAlignmentPadding(tag.alignment(), existingBytes) +
493  tag.length();
494  }
495  };
496 
497  template <typename ValueType>
499  DefaultSerializationTag<std::vector<ValueType>>, void>
500  : BaseSerializationTraits<std::vector<ValueType>> {
501  using value_type = std::vector<ValueType>;
502  using param_type = value_type const &;
503  using reference_type = value_type &;
506 
507  template <typename BufferType>
508  static void serialize(BufferType &buf, param_type val,
509  tag_type const &) {
510  serializeRaw(buf, static_cast<uint32_t>(val.size()));
511  for (auto &elt : val) {
512  serializeRaw(buf, elt);
513  }
514  }
515 
516  template <typename BufferReaderType>
517  static void deserialize(BufferReaderType &buf, reference_type val,
518  tag_type const &) {
519  uint32_t n;
520  deserializeRaw(buf, n);
521  val.clear();
522  val.reserve(n);
523  for (uint32_t i = 0; i < n; ++i) {
524  ValueType elt;
525  deserializeRaw(buf, elt);
526  val.push_back(elt);
527  }
528  }
529 
530  static size_t spaceRequired(size_t existingBytes, param_type val,
531  tag_type const &) {
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);
537  }
538  return bytes - existingBytes;
539  }
540  };
541 
542  template <>
545  template <typename F, typename T> static void apply(F &f, T &val) {
546  f(val.data[0]);
547  f(val.data[1]);
548  }
549  };
550 
551  template <>
554  template <typename F, typename T> static void apply(F &f, T &val) {
555  f(val.data[0]);
556  f(val.data[1]);
557  f(val.data[2]);
558  }
559  };
560 
561  template <typename Tag>
562  struct SimpleStructSerialization<util::TypeSafeId<Tag>>
564  template <typename F, typename T> static void apply(F &f, T &val) {
565  f(val.value());
566  }
567  };
568 
569  } // namespace serialization
570 
571 } // namespace common
572 } // namespace osvr
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.
Definition: SerializationTraits.h:301
Header.
Base of serialization traits, containing useful typedefs.
Definition: SerializationTraits.h:134
uint8_t OSVR_CBool
A pre-C99-safe bool type.
Definition: BoolC.h:50
Definition: RunLoopManager.h:42
Handles spatial transformations.
Definition: SerializationTraitExample_Complicated.h:40
An alternate, simpler method of serializing things that are effectively structs is to explicitly spec...
Definition: SerializationTraits.h:153
#define OSVR_FALSE
Canonical "false" value for OSVR_CBool.
Definition: BoolC.h:54
A tag for use for raw data (bytestream), optionally aligned.
Definition: SerializationTags.h:56
const Scalar & value() const
Definition: SparseUtil.h:164
void deserialize(BufferReaderType &reader, MessageClass &msg)
Deserializes a message from a buffer, using a MessageClass
Definition: Serialization.h:169
Header providing a C-safe "bool" type, because we can&#39;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...
Definition: SerializationTags.h:75
A structure defining a 3D vector, often a position/translation.
Definition: Vec3C.h:48
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
void serialize(BufferType &buf, MessageClass &msg)
Serializes a message into a buffer, using a MessageClass
Definition: Serialization.h:152
std::integral_constant< bool, std::is_same< Tag, Tag >::value > MissingSerializationTraitsForTagOrType
Dummy template for better error messages - inspired by http://stackoverflow.com/a/17917624/265522.
Definition: SerializationTraits.h:55
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...
Definition: SerializationTraits.h:458
static void deserialize(BufferReaderType &reader, Base::reference_type val, tag_type const &)
Reads an object of this type from a buffer.
Definition: SerializationTraits.h:411
Definition: TypeSafeIdHash.h:44
Header.
#define OSVR_TRUE
Canonical "true" value for OSVR_CBool.
Definition: BoolC.h:52
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...
Definition: SerializationTraits.h:319
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...
Definition: AlignmentPadding.h:49
T ntoh(T const v)
Convert network byte order (big endian) to host byte order.
Definition: Endianness.h:177
typename F::template apply< Args... > apply
Apply an alias class.
Definition: Apply.h:44
Serialization traits for a given arithmetic type (that is, a number type that has a network byte orde...
Definition: SerializationTraits.h:296
Used to indicate the kind of integer that should back the serialization of the enum provided...
Definition: SerializationTags.h:71
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...
Definition: SerializationTraits.h:490
static void deserialize(BufferReaderType &buf, typename Base::reference_type val, Tag const &)
Reads an object of this type from a buffer.
Definition: SerializationTraits.h:308
void deserializeRaw(BufferReaderType &reader, T &v, Tag const &tag=Tag())
Deserialize a value from a buffer, with optional tag to specify non-default traits.
Definition: SerializationTraits.h:118
SimpleStructSerialization< T > SimpleSerialization
the SimpleStructSerialization specialization that will take each of our functors and apply them to ev...
Definition: SerializationTraits.h:184
T hton(T const v)
Convert host byte order to network byte order (big endian)
Definition: Endianness.h:182
A structure defining a 2D vector, which represents position.
Definition: Vec2C.h:48
Header.
The default "type tag" for specifying serialization behavior.
Definition: SerializationTags.h:48
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...
Definition: SerializationTraits.h:423
size_t getBufferSpaceRequiredRaw(size_t existingBufferSize, T const &v, Tag const &tag=Tag())
Get the size a value from a buffer, with optional tag to specify non-default traits.
Definition: SerializationTraits.h:126
Mandatory base class for SimpleStructSerialization specializations: allows detection of specializatio...
Definition: SerializationTraits.h:158
Traits class indicating how to serialize a type with a given tag.
Definition: SerializationTraits.h:86
void serializeRaw(BufferType &buf, T const &v, Tag const &tag=Tag())
Serialize a value to a buffer, with optional tag to specify non-default traits.
Definition: SerializationTraits.h:109
Header.