emlabcpp
modern opinionated embedded C++ library
converter.h
Go to the documentation of this file.
1 
24 #pragma once
25 
26 #include "../algorithm.h"
27 #include "../assert.h"
28 #include "../visit.h"
29 #include "./serializer.h"
30 #include "./traits.h"
31 
32 namespace emlabcpp::protocol
33 {
34 
38 template < typename, std::endian >
39 struct converter;
40 
41 template < typename, std::endian >
43 
44 template < typename D, std::endian E >
46 {
47  if constexpr ( with_value_type< proto_traits< D > > )
48  return converter< D, E >{};
49  else
50  return backup_converter< D, E >{};
51 }
52 
53 template < typename D, std::endian E >
54 using converter_for = decltype( converter_for_impl< D, E >() );
55 
58 template < typename T >
60  { T::max_size } -> std::convertible_to< std::size_t >;
61  typename T::value_type;
62  requires bounded_derived< typename T::size_type >;
63 } && requires( std::span< std::byte, T::max_size > buff, typename T::value_type item ) {
64  { T::serialize_at( buff, item ) } -> std::same_as< typename T::size_type >;
65 } && requires( std::span< std::byte const > buff, typename T::value_type item ) {
66  T::deserialize( buff, item );
67 };
68 
69 template < base_type D, std::endian Endianess >
70 struct converter< D, Endianess >
71 {
73  static constexpr std::size_t max_size = traits_for< D >::max_size;
75 
76  static constexpr bool is_big_endian = Endianess == std::endian::big;
77 
78  static constexpr auto& bget( auto& buffer, std::size_t const i )
79  {
80  return buffer[is_big_endian ? i : max_size - 1 - i];
81  }
82 
83  static constexpr size_type
84  serialize_at( std::span< std::byte, max_size > buffer, value_type item )
85  {
87  return size_type{};
88  }
89 
90  static constexpr conversion_result
91  deserialize( std::span< std::byte const > const& buffer, value_type& value )
92  {
93  if ( buffer.size() < max_size )
94  return { 0, &SIZE_ERR };
95 
96  value =
98 
99  return conversion_result{ max_size };
100  }
101 };
102 
103 template < typename D, std::endian E, typename T >
104 std::size_t serialize_range( std::span< std::byte > const buffer, view< T const* > const& data )
105 {
106  auto iter = buffer.begin();
107  using sub_converter = converter_for< D, E >;
108  static constexpr std::size_t max_size = sub_converter::max_size;
109  for ( auto const& item : data ) {
110  std::span< std::byte, max_size > const sub_view{ iter, max_size };
111 
112  bounded const sub_bused = sub_converter::serialize_at( sub_view, item );
113 
114  std::advance( iter, *sub_bused );
115  }
116  auto const used = static_cast< std::size_t >( std::distance( buffer.begin(), iter ) );
117  return used;
118 }
119 
120 template < typename D, std::endian E, typename T >
121 conversion_result
122 deserialize_range( std::span< std::byte const > const& buffer, view< T* > const& data )
123 {
124  using sub_converter = converter_for< D, E >;
125 
126  std::size_t offset = 0;
127 
128  for ( std::size_t const i : range( data.size() ) ) {
129  if ( offset > buffer.size() )
130  return { offset, &SIZE_ERR };
131  std::span const subspan = buffer.subspan( offset );
132 
133  auto sres = sub_converter::deserialize( subspan, data[i] );
134  if ( sres.has_error() ) {
135  sres.used += offset;
136  return sres;
137  }
138  offset += sres.used;
139  }
140 
141  return conversion_result{ offset };
142 }
143 
144 template < convertible D, std::size_t N, std::endian Endianess >
145 struct converter< std::array< D, N >, Endianess >
146 {
148  static constexpr std::size_t max_size = traits_for< std::array< D, N > >::max_size;
149  static constexpr std::size_t min_size = traits_for< std::array< D, N > >::min_size;
150 
154 
159 
160  static constexpr size_type
161  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
162  {
163  std::size_t const used = serialize_range< D, Endianess >( buffer, view{ item } );
164  auto opt_bused = size_type::make( used );
165  EMLABCPP_ASSERT( opt_bused );
166  return *opt_bused;
167  }
168 
169  static constexpr conversion_result
170  deserialize( std::span< std::byte const > const& buffer, value_type& value )
171  {
172  return deserialize_range< D, Endianess >( buffer, view{ value } );
173  }
174 };
175 
176 template < convertible... Ds, std::endian Endianess >
177 struct converter< std::tuple< Ds... >, Endianess >
178 {
179  using def_type = std::tuple< Ds... >;
180 
182  static constexpr std::size_t max_size = traits_for< def_type >::max_size;
183  static constexpr std::size_t min_size = traits_for< def_type >::min_size;
185 
186  static constexpr size_type
187  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
188  {
189  auto iter = buffer.begin();
190 
191  for_each_index< sizeof...( Ds ) >( [&iter, &item]< std::size_t i >() {
192  using sub_converter =
194 
195  std::span< std::byte, sub_converter::max_size > const sub_view{
196  iter, sub_converter::max_size };
197 
198  bounded const bused =
199  sub_converter::serialize_at( sub_view, std::get< i >( item ) );
200 
201  std::advance( iter, *bused );
202  } );
203 
204  auto used = std::distance( buffer.begin(), iter );
205  auto opt_bused = size_type::make( used );
206  EMLABCPP_ASSERT( opt_bused );
207  return *opt_bused;
208  }
209 
210  template < std::size_t I >
212 
213  static constexpr conversion_result
214  deserialize( std::span< std::byte const > const& buffer, value_type& value )
215  {
216  std::size_t offset = 0;
217  mark const* err = nullptr;
218 
219  until_index< sizeof...( Ds ) >(
220  [&offset, &err, &value, &buffer]< std::size_t i >() {
221  if ( offset > buffer.size() ) {
222  err = &SIZE_ERR;
223  return true;
224  }
225  std::span const subspan = buffer.subspan( offset );
226 
227  auto sres =
228  nth_converter< i >::deserialize( subspan, std::get< i >( value ) );
229 
230  offset += sres.used;
231 
232  if ( sres.has_error() ) {
233  err = sres.get_error();
234  return true;
235  }
236  return false;
237  } );
238 
239  return conversion_result{ offset, err };
240  }
241 };
242 
243 // TODO: make a tests for variant with duplicated types
244 template < convertible... Ds, std::endian Endianess >
245 struct converter< std::variant< Ds... >, Endianess >
246 {
247  using def_type = std::variant< Ds... >;
249  static constexpr std::size_t max_size = traits_for< def_type >::max_size;
250  static constexpr std::size_t min_size = traits_for< def_type >::min_size;
251 
252  using id_type = uint8_t;
254  static constexpr std::size_t id_size = id_converter::max_size;
255 
256  static_assert(
257  sizeof...( Ds ) < std::numeric_limits< id_type >::max(),
258  "Number of items for variant is limited by the size of one byte - 256 items" );
259  static_assert( fixedly_sized< id_type > );
261 
262  static constexpr size_type
263  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
264  {
266  buffer.template first< id_size >(), static_cast< id_type >( item.index() ) );
267 
268  return visit_index(
269  [&buffer, &item]< std::size_t i >() -> size_type {
270  using sub_converter = converter_for<
271  std::variant_alternative_t< i, def_type >,
272  Endianess >;
273 
275  return bounded_constant< id_converter::max_size > +
277  buffer.template subspan<
280  *std::get_if< i >( &item ) );
281  },
282  item );
283  }
284 
285  template < std::size_t I >
287 
288  static constexpr conversion_result
289  deserialize( std::span< std::byte const > const& buffer, value_type& value )
290  {
291  id_type id;
292  auto subres = id_converter::deserialize( buffer, id );
293  if ( subres.has_error() )
294  return subres;
295 
296  auto subspan = buffer.subspan< id_size >();
297 
299 
300  until_index< sizeof...( Ds ) >(
301  [&res, &subres, &subspan, &id, &value]< std::size_t i >() {
302  if ( id != i )
303  return false;
304 
306  subspan, value.template emplace< i >() );
307  res.used += subres.used;
308  return true;
309  } );
310 
311  return res;
312  }
313 };
314 
315 template < std::endian Endianess >
316 struct converter< std::monostate, Endianess >
317 {
318  using value_type = std::monostate;
319  static constexpr std::size_t max_size = 0;
321 
322  static constexpr size_type
323  serialize_at( std::span< std::byte, 0 > const, value_type const& )
324  {
325  return size_type{};
326  }
327 
328  static constexpr conversion_result
329  deserialize( std::span< std::byte const > const&, value_type const& )
330  {
331  return conversion_result{ 0 };
332  }
333 };
334 
335 template < convertible T, std::endian Endianess >
336 struct converter< std::optional< T >, Endianess >
337 {
339  using value_type = std::optional< T >;
340  static constexpr std::size_t max_size = traits::max_size;
341  static constexpr std::size_t min_size = traits::min_size;
342  using presence_type = typename traits::presence_type;
343 
344  static_assert( fixedly_sized< presence_type > );
345 
347  static constexpr std::size_t presence_size = presence_converter::max_size;
351 
352  static constexpr presence_type is_present = bounded< uint8_t, 0, 1 >::get< 1 >();
353  static constexpr presence_type not_present = bounded< uint8_t, 0, 1 >::get< 0 >();
354 
355  static constexpr size_type
356  serialize_at( std::span< std::byte, max_size > buffer, value_type const& opt_val )
357  {
358  if ( !opt_val ) {
360  buffer.template first< presence_size >(), not_present );
361  }
363  buffer.template first< presence_size >(), is_present );
364 
365  return psize +
367  buffer.template subspan< presence_size, sub_converter::max_size >(),
368  *opt_val );
369  }
370 
371  static constexpr conversion_result
372  deserialize( std::span< std::byte const > const& buffer, value_type& value )
373  {
374  presence_type is_present_v;
375  auto subres = presence_converter::deserialize(
376  buffer.first< presence_size >(), is_present_v );
377  if ( subres.has_error() )
378  return subres;
379 
380  if ( is_present_v == not_present )
381  return subres;
382 
383  std::span const subspan = buffer.subspan( presence_size );
384 
385  auto res = sub_converter::deserialize( subspan, value.emplace() );
386  res.used += subres.used;
387  return res;
388  }
389 };
390 
391 template < std::size_t N, std::endian Endianess >
392 struct converter< std::bitset< N >, Endianess >
393 {
395  static constexpr std::size_t max_size = traits_for< std::bitset< N > >::max_size;
397 
398  static constexpr bool is_big_endian = Endianess == std::endian::big;
399 
400  static constexpr auto& bget( auto& buffer, std::size_t const i )
401  {
402  return buffer[is_big_endian ? i : max_size - 1 - i];
403  }
404 
405  static constexpr size_type
406  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
407  {
408  for ( std::size_t const i : range( max_size ) ) {
409  std::bitset< 8 > byte;
410  for ( std::size_t const j : range( 8u ) )
411  byte[j] = item[i * 8 + j];
412  bget( buffer, i ) = static_cast< std::byte >( byte.to_ulong() );
413  }
414  return size_type{};
415  }
416 
417  static constexpr conversion_result
418  deserialize( std::span< std::byte const > const& buffer, value_type& value )
419  {
420  if ( buffer.size() < max_size )
421  return { 0, &SIZE_ERR };
422  for ( std::size_t const i : range( max_size ) ) {
423  std::bitset< 8 > byte = static_cast< uint8_t >( bget( buffer, i ) );
424  for ( std::size_t const j : range( 8u ) )
425  value[i * 8 + j] = byte[j];
426  }
427  return conversion_result{ max_size };
428  }
429 };
430 
431 template < std::size_t N, std::endian Endianess >
433 {
436  static constexpr std::size_t min_size = traits_type::min_size;
437  static constexpr std::size_t max_size = traits_type::max_size;
439  using msg_size_type = typename traits_type::msg_size_type;
440  static_assert( fixedly_sized< msg_size_type > );
442  static constexpr std::size_t msg_size_size = msg_size_converter::max_size;
443 
444  static constexpr size_type
445  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
446  {
448  buffer.template first< msg_size_size >(),
449  static_cast< msg_size_type >( item.size() ) );
450 
451  std::copy( item.begin(), item.end(), buffer.begin() + msg_size_size );
452 
454  auto opt_bused = size_type::make( item.size() + *used );
455  EMLABCPP_ASSERT( opt_bused );
456  return *opt_bused;
457  }
458 
459  static constexpr conversion_result
460  deserialize( std::span< std::byte const > const& buffer, value_type& value )
461  {
462  msg_size_type size;
463  auto subres = msg_size_converter::deserialize( buffer, size );
464  if ( subres.has_error() )
465  return subres;
466  if ( buffer.size() < subres.used + size )
467  return { subres.used, &SIZE_ERR };
468  if ( size > N )
469  return { subres.used, &BIGSIZE_ERR };
470  value.resize( size );
471  std::copy_n(
472  buffer.begin() + static_cast< std::ptrdiff_t >( subres.used ),
473  size,
474  value.begin() );
475 
476  return conversion_result{ subres.used + value.size() };
477  }
478 };
479 
480 template < std::size_t N, std::endian Endianess >
482 {
484  static constexpr std::size_t max_size = traits_for< sizeless_message< N > >::max_size;
486 
487  static constexpr size_type
488  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
489  {
490  for ( std::size_t const i : range( item.size() ) )
491  buffer[i] = item[i];
493  auto opt_bused = size_type::make( item.size() );
494  EMLABCPP_ASSERT( opt_bused );
495  return *opt_bused;
496  }
497 
498  static constexpr conversion_result
499  deserialize( std::span< std::byte const > const& buffer, value_type& value )
500  {
501  if ( buffer.size() > N )
502  return { 0, &BIGSIZE_ERR };
503  value.resize( buffer.size() );
504  std::copy( buffer.begin(), buffer.end(), value.begin() );
505 
506  return conversion_result{ value.size() };
507  }
508 };
509 
510 template < convertible D, auto Offset, std::endian Endianess >
511 struct converter< value_offset< D, Offset >, Endianess >
512 {
515 
518 
519  static constexpr size_type
520  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
521  {
522  return sub_converter::serialize_at( buffer, item + Offset );
523  }
524 
525  static constexpr conversion_result
526  deserialize( std::span< std::byte const > const& buffer, value_type& value )
527  {
528  auto subres = sub_converter::deserialize( buffer, value );
529 
530  value -= Offset;
531 
532  return subres;
533  }
534 };
535 
536 template < quantity_derived D, std::endian Endianess >
537 struct converter< D, Endianess >
538 {
540  static constexpr std::size_t max_size = traits_for< D >::max_size;
541 
542  using inner_type = typename D::value_type;
543 
544  static_assert( convertible< inner_type > );
545 
548 
549  static constexpr size_type
550  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
551  {
552  return sub_converter::serialize_at( buffer, *item );
553  }
554 
555  static constexpr conversion_result
556  deserialize( std::span< std::byte const > const& buffer, value_type& value )
557  {
558  inner_type val;
559  auto sub_res = sub_converter::deserialize( buffer, val );
560  value = D{ val };
561  return sub_res;
562  }
563 };
564 
565 template < convertible D, D Min, D Max, std::endian Endianess >
566 struct converter< bounded< D, Min, Max >, Endianess >
567 {
569  static constexpr std::size_t max_size = traits_for< bounded< D, Min, Max > >::max_size;
570 
573 
574  static constexpr size_type
575  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
576  {
577  return sub_converter::serialize_at( buffer, *item );
578  }
579 
580  static constexpr conversion_result
581  deserialize( std::span< std::byte const > const& buffer, value_type& value )
582  {
583  D sub_val{};
584  auto subres = sub_converter::deserialize( buffer, sub_val );
585  if ( subres.has_error() )
586  return subres;
587 
588  auto opt_val = value_type::make( sub_val );
589  if ( !opt_val )
590  return { 0, &BOUNDS_ERR };
591  value = *opt_val;
592  return subres;
593  }
594 };
595 
596 template < convertible CounterDef, convertible D, std::endian Endianess >
597 struct converter< sized_buffer< CounterDef, D >, Endianess >
598 {
600  static constexpr std::size_t max_size =
602  static constexpr std::size_t min_size =
604 
606 
610  static constexpr std::size_t counter_size = counter_converter::max_size;
611 
613  static_assert( fixedly_sized< CounterDef > );
614 
616 
617  static constexpr size_type
618  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
619  {
620  auto vused = sub_converter::serialize_at(
621  buffer.template last< sub_converter::max_size >(), item );
622  auto cused = counter_converter::serialize_at(
623  buffer.template first< counter_size >(),
624  static_cast< counter_type >( *vused ) );
625  return vused + cused;
626  }
627 
628  static constexpr conversion_result
629  deserialize( std::span< std::byte const > const& buffer, value_type& value )
630  {
631  counter_type size = 0;
632  auto cres = counter_converter::deserialize( buffer, size );
633  if ( cres.has_error() )
634  return cres;
635  if ( buffer.size() < cres.used + size )
636  return { cres.used, &SIZE_ERR };
637  auto subres =
638  sub_converter::deserialize( buffer.subspan( counter_size, size ), value );
639  subres.used += cres.used;
640  return subres;
641  }
642 };
643 
644 template < auto V, std::endian Endianess >
645 struct converter< tag< V >, Endianess >
646 {
648  static constexpr std::size_t max_size = traits_for< tag< V > >::max_size;
649 
650  using sub_converter = converter_for< decltype( V ), Endianess >;
651 
653 
654  static constexpr size_type
655  serialize_at( std::span< std::byte, max_size > buffer, value_type const& )
656  {
657  return sub_converter::serialize_at( buffer, V );
658  }
659 
660  static constexpr conversion_result
661  deserialize( std::span< std::byte const > const& buffer, value_type& )
662  {
663  decltype( V ) val{};
664  auto subres = sub_converter::deserialize( buffer, val );
665  if ( subres.has_error() )
666  return subres;
667  if ( val != V )
668  return { 0, &BADVAL_ERR };
669  return conversion_result{ subres.used };
670  }
671 };
672 
673 template < typename... Ds, std::endian Endianess >
674 struct converter< tag_group< Ds... >, Endianess >
675 {
676  using traits = traits_for< tag_group< Ds... > >;
677  using value_type = typename traits::value_type;
678  static constexpr std::size_t max_size = traits::max_size;
679  static constexpr std::size_t min_size = traits::min_size;
680 
681  using def_variant = std::variant< Ds... >;
683 
684  static constexpr size_type
685  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
686  {
687  return visit_index(
688  [&buffer, &item]< std::size_t i >() -> size_type {
689  auto tag_used = nth_tag_converter< i >::serialize_at(
690  buffer.template subspan< 0, nth_tag_converter< i >::max_size >(),
691  nth_tag< i >{} );
692  auto* val_ptr = std::get_if< i >( &item );
694  buffer.template subspan<
697  *val_ptr );
698  return tag_used + used;
699  },
700  item );
701  }
702 
703  template < std::size_t I >
706 
707  template < std::size_t I >
709 
710  template < std::size_t I >
712 
713  static constexpr conversion_result
714  deserialize( std::span< std::byte const > const& buffer, value_type& value )
715  {
717  until_index< sizeof...( Ds ) >( [&buffer, &value, &res]< std::size_t i >() -> bool {
719  auto tag_res = nth_tag_converter< i >::deserialize( buffer, tag );
720  if ( tag_res.has_error() )
721  return false;
722 
724  buffer.subspan( tag_res.used ), value.template emplace< i >() );
725  res.used += tag_res.used;
726  return true;
727  } );
728  return res;
729  }
730 };
731 
732 template < typename... Ds, std::endian Endianess >
733 struct converter< group< Ds... >, Endianess >
734 {
735  using value_type = typename traits_for< group< Ds... > >::value_type;
736  static constexpr std::size_t max_size = traits_for< group< Ds... > >::max_size;
737  static constexpr std::size_t min_size = traits_for< group< Ds... > >::min_size;
738 
739  using def_variant = std::variant< Ds... >;
741 
742  static constexpr size_type
743  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
744  {
745  return visit_index(
746  [&buffer, &item]< std::size_t i >() -> size_type {
747  using sub_converter = converter_for<
748  std::variant_alternative_t< i, def_variant >,
749  Endianess >;
751  buffer.template subspan< 0, sub_converter::max_size >(),
752  std::get< i >( item ) );
753  },
754  item );
755  }
756 
757  template < std::size_t I >
760 
761  static constexpr conversion_result
762  deserialize( std::span< std::byte const > const& buffer, value_type& value )
763  {
765 
766  bool const got_match =
767  until_index< sizeof...( Ds ) >( [&buffer, &res, &value]< std::size_t i >() {
769  buffer, value.template emplace< i >() );
770 
771  if ( res.used == 0 )
772  return false;
773  return true;
774  } );
775 
776  if ( got_match )
777  return res;
778 
779  return { 0, &GROUP_ERR };
780  }
781 };
782 
783 template < std::endian Endianess, typename D, std::endian ParentEndianess >
784 struct converter< endianess_wrapper< Endianess, D >, ParentEndianess >
785  : converter_for< D, Endianess >
786 {
787 };
788 
789 template < std::derived_from< converter_def_type_base > D, std::endian Endianess >
790 struct converter< D, Endianess > : converter_for< typename D::def_type, Endianess >
791 {
792 };
793 
794 template < std::size_t N, std::endian Endianess >
796 {
798 
799  using value_type = typename traits::value_type;
800  static constexpr std::size_t max_size = traits::max_size;
802 
803  using counter_type = typename traits::counter_type;
805  static constexpr std::size_t counter_size = counter_converter::max_size;
806 
808 
809  static constexpr size_type
810  serialize_at( std::span< std::byte, max_size > const buffer, value_type const& item )
811  {
812  std::size_t const size = item.size();
813 
815  buffer.template first< counter_size >(), static_cast< counter_type >( size ) );
816 
817  std::copy_n(
818  item.begin(), size, reinterpret_cast< char* >( buffer.data() + counter_size ) );
819 
820  auto opt_bused = size_type::make( size + counter_size );
821  EMLABCPP_ASSERT( opt_bused );
822  return *opt_bused;
823  }
824 
826 
827  static constexpr conversion_result
828  deserialize( std::span< std::byte const > const& buffer, value_type& value )
829  {
830  counter_type size = 0;
831  auto subres = counter_converter::deserialize( buffer, size );
832  if ( subres.has_error() )
833  return subres;
834  if ( buffer.size() < subres.used + size )
835  return { subres.used, &SIZE_ERR };
836  if ( size >= N )
837  return { subres.used, &BIGSIZE_ERR };
838  std::copy_n(
839  buffer.begin() + static_cast< std::ptrdiff_t >( subres.used ),
840  size,
841  reinterpret_cast< std::byte* >( value.begin() ) );
842 
843  return conversion_result{ subres.used + size };
844  }
845 };
846 
847 template < typename Rep, typename Ratio, std::endian Endianess >
848 struct converter< std::chrono::duration< Rep, Ratio >, Endianess >
849 {
851  using value_type = typename traits::value_type;
852 
853  using rep_traits = typename traits::rep_traits;
855 
856  static constexpr std::size_t max_size = traits::max_size;
857  static constexpr std::size_t min_size = traits::min_size;
858 
860 
861  static constexpr size_type
862  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
863  {
864  return rep_converter::serialize_at( buffer, item.count() );
865  }
866 
867  static constexpr conversion_result
868  deserialize( std::span< std::byte const > const& buffer, value_type& value )
869  {
870  Rep rep;
871  auto res = rep_converter::deserialize( buffer, rep );
872  value = value_type{ rep };
873  return res;
874  }
875 };
876 
877 template < std::endian Endianess >
879 {
881  using value_type = typename traits::value_type;
884  static constexpr std::size_t max_size = traits::max_size;
886 
887  static constexpr size_type
888  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
889  {
891  buffer.first< mark_converter::max_size >(), item.error_mark );
893  buffer.last< offset_converter::max_size >(), item.offset );
894  return size_type{};
895  }
896 
897  static constexpr conversion_result
898  deserialize( std::span< std::byte const > const& buffer, value_type& value )
899  {
900 
901  auto subres = mark_converter::deserialize( buffer, value.error_mark );
902  if ( subres.has_error() )
903  return subres;
905  buffer.subspan< mark_converter::max_size >(), value.offset );
906  }
907 };
908 
909 template < typename T, std::size_t N, std::endian Endianess >
911 {
913 
914  static_assert( N <= std::numeric_limits< uint16_t >::max() );
915 
919 
920  static constexpr std::size_t counter_size = counter_converter::max_size;
921 
922  static_assert( fixedly_sized< counter_type > );
923 
924  static constexpr std::size_t max_size = traits_for< static_vector< T, N > >::max_size;
925  static constexpr std::size_t min_size = traits_for< static_vector< T, N > >::min_size;
927 
928  static constexpr size_type
929  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
930  {
932  buffer.template first< counter_size >(),
933  static_cast< counter_type >( item.size() ) );
934 
935  std::size_t used =
936  serialize_range< T, Endianess >( buffer.subspan( counter_size ), view{ item } );
937  used += counter_size;
938  auto opt_bused = size_type::make( used );
939  EMLABCPP_ASSERT( opt_bused );
940 
941  return *opt_bused;
942  }
943 
944  static constexpr conversion_result
945  deserialize( std::span< std::byte const > const& buffer, value_type& value )
946  {
948  auto const subres = counter_converter::deserialize( buffer, count );
949  if ( subres.has_error() )
950  return subres;
951  while ( value.size() != count && value.size() < value.max_size() )
952  value.emplace_back();
953  conversion_result res = deserialize_range< T, Endianess >(
954  buffer.subspan( counter_size ), view{ value } );
955  res.used += counter_size;
956  return res;
957  }
958 };
959 
960 template < decomposable T, std::endian Endianess >
962 {
964  using value_type = typename traits::value_type;
965  static constexpr std::size_t max_size = traits::max_size;
966  static constexpr std::size_t min_size = traits::min_size;
967 
969 
970  using tuple_type = typename traits::tuple_type;
972 
973  static constexpr size_type
974  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
975  {
976  tuple_type const tpl = decompose( item );
977  return sub_converter::serialize_at( buffer, tpl );
978  }
979 
980  static constexpr conversion_result
981  deserialize( std::span< std::byte const > const& buffer, value_type& value )
982  {
983  tuple_type val;
984  auto subres = sub_converter::deserialize( buffer, val );
985  if ( subres.has_error() )
986  return subres;
987  value = compose< T >( val );
988  return subres;
989  }
990 };
991 
992 template < typename T, std::endian Endianess >
994 {
996  using value_type = typename traits::value_type;
997  static constexpr std::size_t min_size = traits::min_size;
998  static constexpr std::size_t max_size = traits::max_size;
1000 
1001  static constexpr size_type
1002  serialize_at( std::span< std::byte, max_size > buffer, value_type const& item )
1003  {
1004  std::memcpy( buffer.begin(), &item, sizeof( value_type ) );
1005  }
1006 
1007  static constexpr conversion_result
1008  deserialize( std::span< std::byte const > const& buffer, value_type& value )
1009  {
1010  if ( buffer.size() < max_size )
1011  return { 0, &SIZE_ERR };
1012 
1013  std::memcpy( &value, buffer.begin(), sizeof( value_type ) );
1014  return conversion_result{ max_size };
1015  }
1016 };
1017 
1018 } // namespace emlabcpp::protocol
#define EMLABCPP_ASSERT(cond)
MIT License.
Definition: assert.h:38
The bounded class represents a wrapper over type T constrained between MinVal and MaxVal as compile-t...
Definition: bounded.h:44
static std::optional< bounded< T, min_val, max_val > > make(U val)
Creates an optional bounded value if the input value is within the allowed range.
Definition: bounded.h:81
Protocol library has custom type that represents message, however this is just simple overaly over st...
Definition: message.h:40
Sizeless message is class that behaves in a same way as normal message, however it is serialized diff...
Definition: message.h:183
Data container for up to N elements.
Definition: static_vector.h:36
Generic class to represent view of some container.
Definition: view.h:41
MIT License.
Definition: multiplexer.h:33
std::size_t serialize_range(std::span< std::byte > const buffer, view< T const * > const &data)
Definition: converter.h:104
static constexpr auto GROUP_ERR
no item of group matched the content of message
Definition: error.h:56
static constexpr auto BIGSIZE_ERR
too much bytes left in the message for the item
Definition: error.h:48
requires(std::is_enum_v< T >) struct serializer< T
static constexpr T deserialize(std::span< std::byte const, max_size > const &buffer)
Definition: serializer.h:81
decltype(traits_for_impl< D >()) traits_for
Definition: traits.h:59
Endianess
Definition: serializer.h:70
static constexpr void serialize_at(std::span< std::byte, max_size > buffer, T item)
Definition: serializer.h:76
bounded< std::size_t, max_size, max_size > size_type
Definition: serializer.h:74
static constexpr auto SIZE_ERR
Definition: error.h:44
auto converter_for_impl()
Definition: converter.h:45
static constexpr auto BOUNDS_ERR
value in the message is outside of the range of bounded type
Definition: error.h:50
static constexpr std::size_t max_size
Definition: serializer.h:73
concept convertible
This concepts limits types to types that can be declared, that is the overload of 'traits_for' is ful...
Definition: traits.h:67
decltype(converter_for_impl< D, E >()) converter_for
Definition: converter.h:54
static constexpr auto UNDEFVAR_ERR
variant id is outside of the range for defined variant
Definition: error.h:52
conversion_result deserialize_range(std::span< std::byte const > const &buffer, view< T * > const &data)
Definition: converter.h:122
static constexpr auto BADVAL_ERR
parsed value is not correct, such as constant
Definition: error.h:54
concept converter_check
converter_check<T> concept verifies that 'T' is valid overload of converter.
Definition: converter.h:59
Definition: converter.h:42
converter<T,E> structure defines how type T should be serialized and deserialized.
Definition: converter.h:39
Definition: error.h:39
Serializes values from definitions Ds to std::variant.
Definition: base.h:89
Creates a segment starting with counter defined by CounterDef, this counter limits how many bytes are...
Definition: base.h:104
Definition: base.h:95
std::variant< int64_t, float, bool, string_buffer > value_type
Definition: base.h:51
constexpr std::size_t count(Container &&cont, UnaryCallable &&f=std::identity())
Applies the predicate 'f(x)' to each element of container 'cont' and returns the count of items,...
Definition: algorithm.h:234
length distance
Definition: physical_quantity.h:129
constexpr pointer data() noexcept
Returns pointer to first item of the storage.
Definition: static_storage.h:108
constexpr bool until_index(PredicateCallable &&f)
Executes predicate f() with template argument of type 'std::size_t', which ranges from 0 to i until f...
Definition: algorithm.h:488
constexpr void for_each_index(NullCallable &&f)
Executes unary callable f() with template argument of type 'std::size_t', which ranges from 0 to N.
Definition: algorithm.h:466
void copy(Container &&cont, Iterator iter)
Definition: algorithm.h:455
decltype(auto) visit_index(Visitor &&vis, Variant const &var)
Definition: visit.h:35
T value_type
Definition: static_storage.h:100
T res
Definition: algorithm.h:505
constexpr Derived max(vec_point_base< Derived, N > const &a, vec_point_base< Derived, N > const &b)
Definition: vec_point_base.h:229
constexpr view< iterators::numeric_iterator< Numeric > > range(Numeric from, Numeric to)
Builds numeric view over interval [from, to)
Definition: range.h:34
N
Definition: static_storage.h:97
concept with_value_type
Definition: concepts.h:182
physical_quantity< 0, 0, 0, 0, 0, 0, 0, 0, 1 > byte
Definition: physical_quantity.h:118
constexpr std::tuple decompose(T &&)
Definition: decompose.h:104
converter_for< tuple_type, Endianess > sub_converter
Definition: converter.h:971
typename traits::value_type value_type
Definition: converter.h:964
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:981
traits_for< T > traits
Definition: converter.h:963
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:974
typename traits::tuple_type tuple_type
Definition: converter.h:970
std::size_t used
Definition: base.h:41
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:91
converter_for< inner_type, Endianess > sub_converter
Definition: converter.h:546
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:550
typename traits_for< D >::value_type value_type
Definition: converter.h:72
typename D::value_type inner_type
Definition: converter.h:542
static constexpr auto & bget(auto &buffer, std::size_t const i)
Definition: converter.h:78
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type item)
Definition: converter.h:84
converter_for< D, Endianess > sub_converter
Definition: converter.h:571
typename traits_for< bounded< D, Min, Max > >::value_type value_type
Definition: converter.h:568
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:581
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:575
typename sub_converter::size_type size_type
Definition: converter.h:572
traits_for< error_record > traits
Definition: converter.h:880
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:888
converter_for< std::size_t, Endianess > offset_converter
Definition: converter.h:883
typename traits::value_type value_type
Definition: converter.h:881
converter_for< mark, Endianess > mark_converter
Definition: converter.h:882
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:898
converter_for< std::variant_alternative_t< I, def_variant >, Endianess > nth_converter
Definition: converter.h:759
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:743
std::variant< Ds... > def_variant
Definition: converter.h:739
typename traits_for< group< Ds... > >::value_type value_type
Definition: converter.h:735
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:762
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:460
typename traits_type::msg_size_type msg_size_type
Definition: converter.h:439
typename traits_type::value_type value_type
Definition: converter.h:435
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:445
converter_for< msg_size_type, Endianess > msg_size_converter
Definition: converter.h:441
traits_for< message< N > > traits_type
Definition: converter.h:434
typename counter_converter::size_type counter_size_type
Definition: converter.h:608
typename traits_for< sized_buffer< CounterDef, D > >::value_type value_type
Definition: converter.h:599
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:618
converter_for< D, Endianess > sub_converter
Definition: converter.h:605
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:629
typename counter_converter::value_type counter_type
Definition: converter.h:609
converter_for< CounterDef, Endianess > counter_converter
Definition: converter.h:607
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:488
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:499
typename traits_for< sizeless_message< N > >::value_type value_type
Definition: converter.h:483
converter_for< T, Endianess > sub_converter
Definition: converter.h:918
typename traits_for< static_vector< T, N > >::value_type value_type
Definition: converter.h:912
typename traits_for< static_vector< T, N > >::counter_type counter_type
Definition: converter.h:916
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:945
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:929
converter_for< counter_type, Endianess > counter_converter
Definition: converter.h:917
typename sub_converter::size_type sub_size_type
Definition: converter.h:152
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:170
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
In both methods, we create the bounded size without properly checking that it the bounded type was ma...
Definition: converter.h:161
typename traits_for< std::array< D, N > >::value_type value_type
Definition: converter.h:147
converter_for< D, Endianess > sub_converter
Definition: converter.h:151
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:418
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:406
static constexpr auto & bget(auto &buffer, std::size_t const i)
Definition: converter.h:400
typename traits_for< std::bitset< N > >::value_type value_type
Definition: converter.h:394
typename traits::rep_traits rep_traits
Definition: converter.h:853
converter_for< Rep, Endianess > rep_converter
Definition: converter.h:854
typename traits::value_type value_type
Definition: converter.h:851
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:868
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:862
traits_for< std::chrono::duration< Rep, Ratio > > traits
Definition: converter.h:850
static constexpr conversion_result deserialize(std::span< std::byte const > const &, value_type const &)
Definition: converter.h:329
std::monostate value_type
Definition: converter.h:318
static constexpr size_type serialize_at(std::span< std::byte, 0 > const, value_type const &)
Definition: converter.h:323
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &opt_val)
Definition: converter.h:356
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:372
converter_for< T, Endianess > sub_converter
Definition: converter.h:348
converter_for< presence_type, Endianess > presence_converter
Definition: converter.h:346
typename traits::presence_type presence_type
Definition: converter.h:342
typename sub_converter::size_type sub_size
Definition: converter.h:349
traits_for< std::optional< T > > traits
Definition: converter.h:338
std::optional< T > value_type
Definition: converter.h:339
converter_for< std::tuple_element_t< I, def_type >, Endianess > nth_converter
Definition: converter.h:211
std::tuple< Ds... > def_type
Definition: converter.h:179
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:187
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:214
typename traits_for< def_type >::value_type value_type
Definition: converter.h:181
converter_for< id_type, Endianess > id_converter
Definition: converter.h:253
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:289
std::variant< Ds... > def_type
Definition: converter.h:247
typename traits_for< def_type >::value_type value_type
Definition: converter.h:248
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:263
converter_for< std::variant_alternative_t< I, def_type >, Endianess > nth_converter
Definition: converter.h:286
traits_for< string_buffer< N > > traits
Definition: converter.h:797
typename traits::counter_type counter_type
Definition: converter.h:803
converter_for< counter_type, Endianess > counter_converter
Definition: converter.h:804
converter_for< typename value_type::base_type, Endianess > sub_converter
Definition: converter.h:807
static constexpr size_type serialize_at(std::span< std::byte, max_size > const buffer, value_type const &item)
Definition: converter.h:810
typename traits::value_type value_type
Definition: converter.h:799
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
TODO: duplication between this, messages, and static_vector.
Definition: converter.h:828
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &)
Definition: converter.h:655
typename sub_converter::size_type size_type
Definition: converter.h:652
typename traits_for< tag< V > >::value_type value_type
Definition: converter.h:647
converter_for< decltype(V), Endianess > sub_converter
Definition: converter.h:650
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &)
Definition: converter.h:661
typename traits::value_type value_type
Definition: converter.h:677
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:685
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:714
converter_for< nth_tag< I >, Endianess > nth_tag_converter
Definition: converter.h:711
traits_for< tag_group< Ds... > > traits
Definition: converter.h:676
converter_for< std::variant_alternative_t< I, def_variant >, Endianess > nth_converter
Definition: converter.h:705
std::variant< Ds... > def_variant
Definition: converter.h:681
typename sub_converter::size_type size_type
Definition: converter.h:517
converter_for< D, Endianess > sub_converter
Definition: converter.h:516
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:526
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:520
typename traits_for< value_offset< D, Offset > >::value_type value_type
Definition: converter.h:513
Follows a set of special data types used for definition of protocol.
Definition: base.h:79
Definition: converter.h:994
static constexpr std::size_t max_size
Definition: converter.h:998
typename traits::value_type value_type
Definition: converter.h:996
static constexpr size_type serialize_at(std::span< std::byte, max_size > buffer, value_type const &item)
Definition: converter.h:1002
static constexpr std::size_t min_size
Definition: converter.h:997
traits_for< T > traits
Definition: converter.h:995
static constexpr conversion_result deserialize(std::span< std::byte const > const &buffer, value_type &value)
Definition: converter.h:1008
static constexpr T deserialize(std::span< std::byte const, max_size > const &buffer)
Definition: serializer.h:56
static constexpr void serialize_at(std::span< std::byte, max_size > buffer, T item)
Definition: serializer.h:48
tuple is high levle alternative to use just 'std::tuple' that is more friendly for standalone protoco...
Definition: tuple.h:43
The value defined by D present in the message is offseted by Offset.
Definition: base.h:113
Definition: types.h:73