12 #ifdef MICROSTRAIN_HAS_OPTIONAL
16 #if __cpp_lib_apply >= 201603L
54 SerializerBase(uint8_t* ptr,
size_t capacity,
size_t offset=0) : m_ptr(ptr), m_size(capacity), m_offset(offset) {}
55 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) {}
58 size_t capacity()
const {
return m_size; }
59 size_t offset()
const {
return m_offset; }
60 size_t usedLength()
const {
return offset(); }
61 int remaining()
const {
return int(m_size - m_offset); }
63 bool isOverrun()
const {
return m_offset > m_size; }
64 bool isOk()
const {
return !isOverrun(); }
65 bool isFinished()
const {
return m_offset == m_size; }
66 bool hasRemaining(
size_t count=1)
const {
return m_offset+count <= m_size; }
68 uint8_t* basePointer() {
return m_ptr; }
69 const uint8_t* basePointer()
const {
return m_ptr; }
75 uint8_t*
getPointer(
size_t required_size) {
return hasRemaining(required_size) ? (m_ptr+m_offset) :
nullptr; }
76 const uint8_t*
getPointer(
size_t required_size)
const {
return hasRemaining(required_size) ? (m_ptr+m_offset) :
nullptr; }
88 uint8_t*
getPtrAndAdvance(
size_t size) { uint8_t* ptr = hasRemaining(size) ? (m_ptr+m_offset) :
nullptr; m_offset += size;
return ptr; }
99 size_t setOffset(
size_t offset) { std::swap(m_offset, offset);
return offset; }
102 uint8_t* m_ptr =
nullptr;
124 template<serialization::Endian E>
132 template<
typename... Ts>
bool insert (
const Ts&... values);
133 template<
typename... Ts>
bool extract(Ts&... values);
135 template<
class T,
class S>
bool extract_count(T& count, S max_count);
170 template<serialization::Endian E,
class T>
171 typename std::enable_if<std::is_arithmetic<T>::value,
size_t>::type
175 serialization::write<E>(ptr, value);
191 template<serialization::Endian E,
class T>
192 typename std::enable_if<std::is_arithmetic<T>::value,
size_t>::type
196 serialization::read<E>(ptr, value);
219 template<serialization::Endian E,
class T>
220 typename std::enable_if<std::is_enum<T>::value,
size_t>::type
223 using BaseType =
typename std::underlying_type<T>::type;
226 serialization::write<E>(ptr,
static_cast<BaseType
>(value));
228 return sizeof(BaseType);
244 template<serialization::Endian E,
class T>
245 typename std::enable_if<std::is_enum<T>::value,
size_t>::type
248 using BaseType =
typename std::underlying_type<T>::type;
253 serialization::read<E>(ptr, base);
254 value =
static_cast<T
>(base);
257 return sizeof(BaseType);
297 template<serialization::Endian E,
class T, decltype(&T::insert) =
nullptr>
298 typename std::enable_if<std::is_class<T>::value ,
size_t>::type
301 size_t offset = serializer.offset();
302 object.
insert(serializer);
303 return serializer.offset() - offset;
338 template<serialization::Endian E,
class T, decltype(&T::extract) =
nullptr>
339 typename std::enable_if<std::is_class<T>::value ,
size_t>::type
342 size_t offset = serializer.offset();
344 return serializer.offset() - offset;
357 #if __cpp_lib_apply >= 201603L
373 size_t insert(Serializer<E>& serializer,
const std::tuple<Ts...>& values)
375 auto lambda = [&serializer](
const Ts&... args) {
376 return insert(serializer, args...);
379 return std::apply(lambda, values);
396 size_t extract(Serializer<E>& serializer,
const std::tuple<std::reference_wrapper<Ts>...>& values)
398 auto lambda = [&serializer](
auto&... args) {
399 return extract(serializer, args...);
402 return std::apply(lambda, values);
425 template<serialization::Endian E,
class T>
431 const size_t size =
sizeof(T)*count;
434 for(
size_t i=0; i<count; i++)
435 serialization::write<E>(ptr+i*
sizeof(T), values[i]);
441 size_t offset = serializer.offset();
442 for(
size_t i=0; i<count; i++)
443 serializer.
insert(values[i]);
444 return serializer.offset() - offset;
460 template<serialization::Endian E,
class T>
466 const size_t size =
sizeof(T)*count;
469 for(
size_t i=0; i<count; i++)
470 serialization::read<E>(ptr+i*
sizeof(T), values[i]);
476 size_t offset = serializer.offset();
477 for(
size_t i=0; i<count; i++)
479 return serializer.offset() - offset;
494 template<serialization::Endian E,
class T>
511 template<serialization::Endian E,
class T>
533 template<serialization::Endian E,
class T,
size_t N>
536 return insert(serializer, values, N);
550 template<serialization::Endian E,
class T,
size_t N>
553 return extract(serializer, values, N);
569 template<serialization::Endian E,
class T,
size_t N>
572 return insert(serializer, values.data(), values.size());
586 template<serialization::Endian E,
class T,
size_t N>
589 return extract(serializer, values.data(), values.size());
612 #if __cpp_fold_expressions >= 201603L && __cpp_if_constexpr >= 201606L
614 typename std::enable_if<(
sizeof...(Ts) > 1),
size_t>::type
615 insert(Serializer<E>& serializer, Ts... values)
617 if constexpr( (std::is_arithmetic<Ts>::value && ...) )
619 const size_t size = ( ... +
sizeof(Ts) );
621 if(uint8_t* ptr = serializer.getPtrAndAdvance(size))
624 ( ..., (offset += serialization::write<E>(ptr+offset, values)) );
631 return ( ... +
insert(serializer, values) );
637 return insert(serializer, value0) +
insert(serializer, value1, values...);
658 #if __cpp_fold_expressions >= 201603L && __cpp_if_constexpr >= 201606L
660 typename std::enable_if<(
sizeof...(Ts) > 1),
size_t>::type
661 extract(Serializer<E>& serializer, Ts&... values)
663 if constexpr( (std::is_arithmetic<Ts>::value && ...) )
665 const size_t size = ( ... +
sizeof(Ts) );
667 if(uint8_t* ptr = serializer.getPtrAndAdvance(size))
670 ( ..., (offset += serialization::read<E>(ptr+offset, values)) );
677 return ( ... +
extract(serializer, values) );
683 return extract(serializer, value0) +
extract(serializer, value1, values...);
721 template<serialization::Endian E,
class T>
722 bool insert(
const T& value, uint8_t* buffer,
size_t buffer_length,
size_t offset=0,
bool exact_size=
false)
726 return exact_size ? serializer.isFinished() : serializer.isOk();
759 template<serialization::Endian E,
class T>
760 bool extract(T& value,
const uint8_t* buffer,
size_t buffer_length,
size_t offset=0,
bool exact_size=
false)
764 return exact_size ? serializer.isFinished() : serializer.isOk();
790 template<serialization::Endian E,
class T>
793 return insert<E,T>(value, buffer.
data(), buffer.
size(), offset, exact_size);
814 template<serialization::Endian E,
class T>
817 return extract<E,T>(value, buffer.
data(), buffer.
size(), offset, exact_size);
824 #ifdef MICROSTRAIN_HAS_OPTIONAL
825 template<
class T, serialization::Endian E>
838 std::optional<T>
extract(Serializer<E>& serializer)
841 if(extract<E,T>(serializer, value))
864 template<
class T, serialization::Endian E>
865 std::optional<T>
extract(
const uint8_t* buffer,
size_t length,
size_t offset,
bool exact_size=
false)
868 if(extract<E,T>(value, buffer, length, offset, exact_size))
890 template<
class T, serialization::Endian E>
894 if(extract<E,T>(value, buffer.
data(), buffer.
size(), offset, exact_size))
921 template<serialization::Endian E>
922 template<
typename... Ts>
947 template<serialization::Endian E>
948 template<
typename... Ts>
978 template<serialization::Endian E>
979 template<
class T,
class S>
984 if( count <= max_count )