12 #ifdef MICROSTRAIN_HAS_OPTIONAL
16 #if __cpp_lib_apply >= 201603L
64 SerializerBase(uint8_t* ptr,
size_t capacity,
size_t offset=0) : m_ptr(ptr), m_size(capacity), m_offset(offset) {}
65 SerializerBase(
const uint8_t* ptr,
size_t size,
size_t offset=0) : m_ptr(const_cast<uint8_t*>(ptr)), m_size(size), m_offset(offset) {}
68 size_t capacity()
const {
return m_size; }
69 size_t offset()
const {
return m_offset; }
70 size_t usedLength()
const {
return offset(); }
71 int remaining()
const {
return int(m_size - m_offset); }
73 bool isOverrun()
const {
return m_offset > m_size; }
74 bool isOk()
const {
return !isOverrun(); }
75 bool isFinished()
const {
return m_offset == m_size; }
76 bool hasRemaining(
size_t count=1)
const {
return m_offset+count <= m_size; }
78 uint8_t* basePointer() {
return m_ptr; }
79 const uint8_t* basePointer()
const {
return m_ptr; }
85 uint8_t*
getPointer(
size_t required_size) {
return hasRemaining(required_size) ? (m_ptr+m_offset) :
nullptr; }
86 const uint8_t*
getPointer(
size_t required_size)
const {
return hasRemaining(required_size) ? (m_ptr+m_offset) :
nullptr; }
98 uint8_t*
getPtrAndAdvance(
size_t size) { uint8_t* ptr = hasRemaining(size) ? (m_ptr+m_offset) :
nullptr; m_offset += size;
return ptr; }
109 size_t setOffset(
size_t offset) { std::swap(m_offset, offset);
return offset; }
112 uint8_t* m_ptr =
nullptr;
134 template<serialization::Endian E>
142 template<
typename... Ts>
bool insert (
const Ts&... values);
143 template<
typename... Ts>
bool extract(Ts&... values);
145 template<
class T,
class S>
bool extract_count(T& count, S max_count);
180 template<serialization::Endian E,
class T>
181 typename std::enable_if<std::is_arithmetic<T>::value,
size_t>::type
185 serialization::write<E>(ptr, value);
201 template<serialization::Endian E,
class T>
202 typename std::enable_if<std::is_arithmetic<T>::value,
size_t>::type
206 serialization::read<E>(ptr, value);
229 template<serialization::Endian E,
class T>
230 typename std::enable_if<std::is_enum<T>::value,
size_t>::type
233 using BaseType =
typename std::underlying_type<T>::type;
236 serialization::write<E>(ptr,
static_cast<BaseType
>(value));
238 return sizeof(BaseType);
254 template<serialization::Endian E,
class T>
255 typename std::enable_if<std::is_enum<T>::value,
size_t>::type
258 using BaseType =
typename std::underlying_type<T>::type;
263 serialization::read<E>(ptr, base);
264 value =
static_cast<T
>(base);
267 return sizeof(BaseType);
307 template<serialization::Endian E,
class T, decltype(&T::insert) =
nullptr>
308 typename std::enable_if<std::is_class<T>::value ,
size_t>::type
311 size_t offset = serializer.offset();
312 object.
insert(serializer);
313 return serializer.offset() - offset;
348 template<serialization::Endian E,
class T, decltype(&T::extract) =
nullptr>
349 typename std::enable_if<std::is_class<T>::value ,
size_t>::type
352 size_t offset = serializer.offset();
354 return serializer.offset() - offset;
367 #if __cpp_lib_apply >= 201603L
383 size_t insert(Serializer<E>& serializer,
const std::tuple<Ts...>& values)
385 auto lambda = [&serializer](
const Ts&... args) {
386 return insert(serializer, args...);
389 return std::apply(lambda, values);
406 size_t extract(Serializer<E>& serializer,
const std::tuple<std::reference_wrapper<Ts>...>& values)
408 auto lambda = [&serializer](
auto&... args) {
409 return extract(serializer, args...);
412 return std::apply(lambda, values);
435 template<serialization::Endian E,
class T>
441 const size_t size =
sizeof(T)*count;
444 for(
size_t i=0; i<count; i++)
445 serialization::write<E>(ptr+i*
sizeof(T), values[i]);
451 size_t offset = serializer.offset();
452 for(
size_t i=0; i<count; i++)
453 serializer.
insert(values[i]);
454 return serializer.offset() - offset;
470 template<serialization::Endian E,
class T>
476 const size_t size =
sizeof(T)*count;
479 for(
size_t i=0; i<count; i++)
480 serialization::read<E>(ptr+i*
sizeof(T), values[i]);
486 size_t offset = serializer.offset();
487 for(
size_t i=0; i<count; i++)
489 return serializer.offset() - offset;
504 template<serialization::Endian E,
class T>
521 template<serialization::Endian E,
class T>
543 template<serialization::Endian E,
class T,
size_t N>
546 return insert(serializer, values, N);
560 template<serialization::Endian E,
class T,
size_t N>
563 return extract(serializer, values, N);
579 template<serialization::Endian E,
class T,
size_t N>
582 return insert(serializer, values.data(), values.size());
596 template<serialization::Endian E,
class T,
size_t N>
599 return extract(serializer, values.data(), values.size());
622 #if __cpp_fold_expressions >= 201603L && __cpp_if_constexpr >= 201606L
624 typename std::enable_if<(
sizeof...(Ts) > 1),
size_t>::type
625 insert(Serializer<E>& serializer, Ts... values)
627 if constexpr( (std::is_arithmetic<Ts>::value && ...) )
629 const size_t size = ( ... +
sizeof(Ts) );
631 if(uint8_t* ptr = serializer.getPtrAndAdvance(size))
634 ( ..., (offset += serialization::write<E>(ptr+offset, values)) );
641 return ( ... +
insert(serializer, values) );
647 return insert(serializer, value0) +
insert(serializer, value1, values...);
668 #if __cpp_fold_expressions >= 201603L && __cpp_if_constexpr >= 201606L
670 typename std::enable_if<(
sizeof...(Ts) > 1),
size_t>::type
671 extract(Serializer<E>& serializer, Ts&... values)
673 if constexpr( (std::is_arithmetic<Ts>::value && ...) )
675 const size_t size = ( ... +
sizeof(Ts) );
677 if(uint8_t* ptr = serializer.getPtrAndAdvance(size))
680 ( ..., (offset += serialization::read<E>(ptr+offset, values)) );
687 return ( ... +
extract(serializer, values) );
693 return extract(serializer, value0) +
extract(serializer, value1, values...);
731 template<serialization::Endian E,
class T>
732 bool insert(
const T& value, uint8_t* buffer,
size_t buffer_length,
size_t offset=0,
bool exact_size=
false)
736 return exact_size ? serializer.isFinished() : serializer.isOk();
769 template<serialization::Endian E,
class T>
770 bool extract(T& value,
const uint8_t* buffer,
size_t buffer_length,
size_t offset=0,
bool exact_size=
false)
774 return exact_size ? serializer.isFinished() : serializer.isOk();
800 template<serialization::Endian E,
class T>
803 return insert<E,T>(value, buffer.
data(), buffer.
size(), offset, exact_size);
824 template<serialization::Endian E,
class T>
827 return extract<E,T>(value, buffer.
data(), buffer.
size(), offset, exact_size);
834 #ifdef MICROSTRAIN_HAS_OPTIONAL
835 template<
class T, serialization::Endian E>
848 std::optional<T>
extract(Serializer<E>& serializer)
851 if(extract<E,T>(serializer, value))
874 template<
class T, serialization::Endian E>
875 std::optional<T>
extract(
const uint8_t* buffer,
size_t length,
size_t offset,
bool exact_size=
false)
878 if(extract<E,T>(value, buffer, length, offset, exact_size))
900 template<
class T, serialization::Endian E>
904 if(extract<E,T>(value, buffer.
data(), buffer.
size(), offset, exact_size))
931 template<serialization::Endian E>
932 template<
typename... Ts>
957 template<serialization::Endian E>
958 template<
typename... Ts>
988 template<serialization::Endian E>
989 template<
class T,
class S>
994 if( count <= max_count )