1use core::convert::Infallible;
11
12use alloc::{boxed::Box, vec, vec::Vec};
13
14use crate::codec::{
15 CodecError, DataFormat, DataHeader, Decodable, Encodable, FieldReader, Format, ReadsDecodable,
16 UnexpectedDataFormatSnafu, WritesEncodable,
17};
18
19pub mod binary;
20pub mod cryptography;
21pub mod dynamic;
22pub mod list;
23pub mod map;
24pub mod number;
25mod text;
26pub use binary::Array;
27pub use dynamic::Unspecified;
28pub use text::*;
29
30#[non_exhaustive]
32#[derive(Default, Debug, Clone, PartialEq)]
33pub enum Type {
34 #[default]
36 Unspecified,
37
38 U8,
40 U16,
42 U32,
44 U64,
46
47 I8,
49 I16,
51 I32,
53 I64,
55
56 F32,
58 F64,
60
61 Bool,
63
64 Text,
66
67 Array(u16, Box<Type>),
72
73 Data(DataType),
75
76 List(Box<Type>),
78
79 Map(Box<(Type, Type)>),
81}
82
83impl Type {
84 pub(crate) const UNSPECIFIED_ORDINAL: u8 = 0;
87 pub(crate) const U8_ORDINAL: u8 = 255;
88 pub(crate) const U16_ORDINAL: u8 = 254;
89 pub(crate) const U32_ORDINAL: u8 = 253;
90 pub(crate) const U64_ORDINAL: u8 = 252;
91 pub(crate) const I8_ORDINAL: u8 = 251;
92 pub(crate) const I16_ORDINAL: u8 = 250;
93 pub(crate) const I32_ORDINAL: u8 = 249;
94 pub(crate) const I64_ORDINAL: u8 = 248;
95 pub(crate) const F32_ORDINAL: u8 = 247;
96 pub(crate) const F64_ORDINAL: u8 = 246;
97 pub(crate) const BOOL_ORDINAL: u8 = 245;
98 pub(crate) const TEXT_ORDINAL: u8 = 244;
99 pub(crate) const ARRAY_ORDINAL: u8 = 243;
100 pub(crate) const LIST_ORDINAL: u8 = 242;
101 pub(crate) const MAP_ORDINAL: u8 = 241;
102
103 pub const fn ordinal(&self) -> u8 {
105 match self {
106 Type::Unspecified => Self::UNSPECIFIED_ORDINAL,
107 Type::U8 => Self::U8_ORDINAL,
108 Type::U16 => Self::U16_ORDINAL,
109 Type::U32 => Self::U32_ORDINAL,
110 Type::U64 => Self::U64_ORDINAL,
111 Type::I8 => Self::I8_ORDINAL,
112 Type::I16 => Self::I16_ORDINAL,
113 Type::I32 => Self::I32_ORDINAL,
114 Type::I64 => Self::I64_ORDINAL,
115 Type::F32 => Self::F32_ORDINAL,
116 Type::F64 => Self::F64_ORDINAL,
117 Type::Bool => Self::BOOL_ORDINAL,
118 Type::Text => Self::TEXT_ORDINAL,
119 Type::Array(..) => Self::ARRAY_ORDINAL,
120 Type::Data(data) => data.format.as_data_format().ordinal,
121 Type::List(_) => Self::LIST_ORDINAL,
122 Type::Map(_) => Self::MAP_ORDINAL,
123 }
124 }
125
126 pub fn from_ordinal(ordinal: u8) -> Option<Self> {
136 match ordinal {
137 Self::UNSPECIFIED_ORDINAL => Some(Type::Unspecified),
138 Self::U8_ORDINAL => Some(Type::U8),
139 Self::U16_ORDINAL => Some(Type::U16),
140 Self::U32_ORDINAL => Some(Type::U32),
141 Self::U64_ORDINAL => Some(Type::U64),
142 Self::I8_ORDINAL => Some(Type::I8),
143 Self::I16_ORDINAL => Some(Type::I16),
144 Self::I32_ORDINAL => Some(Type::I32),
145 Self::I64_ORDINAL => Some(Type::I64),
146 Self::F32_ORDINAL => Some(Type::F32),
147 Self::F64_ORDINAL => Some(Type::F64),
148 Self::BOOL_ORDINAL => Some(Type::Bool),
149 Self::TEXT_ORDINAL => Some(Type::Text),
150 Self::ARRAY_ORDINAL => Some(Type::Array(0, Type::Unspecified.into())),
151 Self::LIST_ORDINAL => Some(Type::List(Type::Unspecified.into())),
152 Self::MAP_ORDINAL => Some(Type::Map((Type::Unspecified, Type::Unspecified).into())),
153 _ => None,
154 }
155 }
156
157 pub const fn format(&self) -> Format {
159 match self {
160 Type::Unspecified => Format::Fluid,
161 Type::U8 => u8::FORMAT,
162 Type::U16 => u16::FORMAT,
163 Type::U32 => u32::FORMAT,
164 Type::U64 => u64::FORMAT,
165 Type::I8 => i8::FORMAT,
166 Type::I16 => i16::FORMAT,
167 Type::I32 => i32::FORMAT,
168 Type::I64 => i64::FORMAT,
169 Type::F32 => f32::FORMAT,
170 Type::F64 => f64::FORMAT,
171 Type::Bool => bool::FORMAT,
172 Type::Text => Text::FORMAT,
173 Type::Array(count, elem) => match elem.format() {
174 Format::Blob(size) => {
175 let total = *count as u32 * size as u32;
176 assert!(
177 total <= u16::MAX as u32,
178 "array size exceeds maximum blob size (u16::MAX)"
179 );
180 Format::Blob(total as u16)
181 }
182 _ => panic!("array elements must have a fixed size"),
183 },
184 Type::Data(data) => data.format,
185 Type::List(typing) => typing.format().as_sequence(),
186
187 Type::Map(..) => DataFormat {
190 blob_size: 0,
191 data_fields: 2,
192 ordinal: 0,
193 }
194 .as_format(),
195 }
196 }
197
198 pub fn from_name(name: &str) -> Option<Self> {
202 match name {
203 "unspecified" => Some(Type::Unspecified),
204 "u8" => Some(Type::U8),
205 "u16" => Some(Type::U16),
206 "u32" => Some(Type::U32),
207 "u64" => Some(Type::U64),
208 "i8" => Some(Type::I8),
209 "i16" => Some(Type::I16),
210 "i32" => Some(Type::I32),
211 "i64" => Some(Type::I64),
212 "f32" => Some(Type::F32),
213 "f64" => Some(Type::F64),
214 "bool" => Some(Type::Bool),
215 "text" => Some(Type::Text),
216 _ => None,
217 }
218 }
219}
220
221#[derive(Default, Debug, Clone, PartialEq)]
223pub struct Coda {
224 pub global_name: Text,
227
228 pub local_name: Text,
231
232 pub docs: Option<Text>,
233
234 pub(crate) data: Vec<DataType>,
236}
237
238impl Coda {
239 pub fn new(global_name: Text, local_name: Text, docs: Option<Text>, data: &[DataType]) -> Self {
241 Self {
242 global_name,
243 local_name,
244 docs,
245 data: Vec::from(data),
246 }
247 }
248
249 pub fn iter(&self) -> impl Iterator<Item = &DataType> {
254 self.data.iter()
255 }
256
257 #[cfg(feature = "parse")]
260 pub(crate) fn type_from_name(&self, name: &str) -> Option<Type> {
261 for data in self.data.iter() {
262 if data.name.eq_ignore_ascii_case(name) {
263 return Some(Type::Data(data.clone()));
264 }
265 }
266
267 Type::from_name(name)
268 }
269}
270
271#[derive(Default, Debug, Clone, PartialEq)]
273pub struct DataType {
274 pub name: Text,
283
284 pub docs: Option<Text>,
286
287 blob_fields: Vec<DataField>,
290
291 data_fields: Vec<DataField>,
297
298 format: Format,
300}
301
302impl DataType {
303 pub fn new(
306 name: Text,
307 docs: Option<Text>,
308 ordinal: u8,
309 blob_fields: &[DataField],
310 data_fields: &[DataField],
311 ) -> Self {
312 let mut format = Format::data(ordinal);
314
315 let mut i = 0;
317 while i < blob_fields.len() {
318 let field = &blob_fields[i];
319 format = format.with(field.typing.format());
320 i += 1;
321 }
322
323 let mut i = 0;
325 while i < data_fields.len() {
326 let field = &data_fields[i];
327 format = format.with(field.typing.format());
328 i += 1;
329 }
330
331 Self {
332 name,
333 docs,
334 blob_fields: Vec::from(blob_fields),
335 data_fields: Vec::from(data_fields),
336 format,
337 }
338 }
339
340 pub const fn new_fluid(name: Text, docs: Option<Text>) -> Self {
342 Self {
343 name,
344 docs,
345 blob_fields: vec![],
346 data_fields: vec![],
347 format: Format::Fluid,
348 }
349 }
350
351 pub fn iter(&self) -> impl Iterator<Item = &DataField> {
353 self.blob_fields.iter().chain(self.data_fields.iter())
354 }
355
356 pub fn with(mut self, field: DataField) -> Self {
358 if matches!(self.format, Format::Fluid) {
359 todo!("it should be an error to add fields to a type defined as fluid")
360 }
361
362 let field_format = field.format();
363 self.format = self.format.with(field_format);
364 match field_format {
365 Format::Blob(..) => self.blob_fields.push(field),
366 Format::Data(..) | Format::Sequence(..) | Format::Fluid => self.data_fields.push(field),
367 };
368
369 self
370 }
371
372 pub const fn format(&self) -> &Format {
374 &self.format
375 }
376}
377
378#[derive(Default, Clone, Debug, PartialEq)]
380pub struct DataField {
381 pub name: Text,
383
384 pub docs: Option<Text>,
386
387 pub typing: Type,
389
390 pub optional: bool,
392
393 pub flattened: bool,
402}
403
404impl DataField {
405 fn format(&self) -> Format {
409 let format = self.typing.format();
410 if self.optional {
411 format.as_sequence()
412 } else {
413 format
414 }
415 }
416}
417
418pub trait TryAsFormat<D> {
424 type Error;
431
432 fn try_as_format(&self) -> Result<&D, Self::Error>;
434}
435
436impl<T> TryAsFormat<T> for T {
438 type Error = Infallible;
439
440 fn try_as_format(&self) -> Result<&T, Self::Error> {
441 Ok(self)
442 }
443}
444
445impl Encodable for Type {
448 const FORMAT: Format = Format::Fluid;
449
450 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
451 match self {
452 Type::Array(count, elem) => {
453 writer.write_data(count)?;
454 writer.write_data(elem.as_ref())
455 }
456 Type::Data(typing) => writer.write_data(typing),
457 Type::List(typing) => writer.write_data(typing.as_ref()),
458 Type::Map(typing) => {
459 writer.write_data(&typing.as_ref().0)?;
460 writer.write_data(&typing.as_ref().1)?;
461 Ok(())
462 }
463
464 _ => Ok(()),
466 }
467 }
468
469 fn encode_header(
470 &self,
471 writer: &mut (impl WritesEncodable + ?Sized),
472 ) -> Result<(), CodecError> {
473 let format = match self {
474 Type::Map(_) => Format::data(self.ordinal())
475 .with(Type::FORMAT)
476 .with(Type::FORMAT)
477 .as_data_format(),
478 Type::Data(..) | Type::List(_) => Format::data(self.ordinal())
479 .with(Type::FORMAT)
480 .as_data_format(),
481 Type::Array(..) => Format::data(self.ordinal())
482 .with(u16::FORMAT)
483 .with(Type::FORMAT)
484 .as_data_format(),
485 _ => Format::data(self.ordinal()).as_data_format(),
486 };
487
488 DataHeader { count: 1, format }.encode(writer)
489 }
490}
491
492impl Decodable for Type {
493 fn decode(
494 &mut self,
495 reader: &mut (impl ReadsDecodable + ?Sized),
496 header: Option<DataHeader>,
497 ) -> Result<(), CodecError> {
498 let header = header.ok_or_else(|| {
499 UnexpectedDataFormatSnafu {
500 expected: Self::FORMAT,
501 actual: None::<DataHeader>,
502 }
503 .build()
504 })?;
505
506 if header.count != 1 {
508 return UnexpectedDataFormatSnafu {
509 expected: Self::FORMAT,
510 actual: Some(header),
511 }
512 .fail();
513 }
514
515 match header.format.ordinal {
516 Self::ARRAY_ORDINAL => {
517 if header.format.blob_size != 2 || header.format.data_fields != 1 {
519 return UnexpectedDataFormatSnafu {
520 expected: Self::FORMAT,
521 actual: Some(header),
522 }
523 .fail();
524 }
525 let mut count = 0u16;
526 reader.read_data_into(&mut count)?;
527 let mut elem = Type::default();
528 reader.read_data_into(&mut elem)?;
529 *self = Type::Array(count, elem.into());
530 }
531 Self::LIST_ORDINAL => {
532 if header.format.blob_size != 0 || header.format.data_fields != 1 {
534 return UnexpectedDataFormatSnafu {
535 expected: Self::FORMAT,
536 actual: Some(header),
537 }
538 .fail();
539 }
540 let mut typing = Type::default();
541 reader.read_data_into(&mut typing)?;
542 *self = Type::List(typing.into());
543 }
544 Self::MAP_ORDINAL => {
545 if header.format.blob_size != 0 || header.format.data_fields != 2 {
547 return UnexpectedDataFormatSnafu {
548 expected: Self::FORMAT,
549 actual: Some(header),
550 }
551 .fail();
552 }
553 let mut key_typing = Type::default();
554 reader.read_data_into(&mut key_typing)?;
555 let mut value_typing = Type::default();
556 reader.read_data_into(&mut value_typing)?;
557 *self = Type::Map((key_typing, value_typing).into());
558 }
559 ordinal => match Type::from_ordinal(ordinal) {
560 Some(simple) => {
562 if header.format.blob_size != 0 || header.format.data_fields != 0 {
563 return UnexpectedDataFormatSnafu {
564 expected: Self::FORMAT,
565 actual: Some(header),
566 }
567 .fail();
568 }
569 *self = simple;
570 }
571 None => {
573 if header.format.blob_size != 0 || header.format.data_fields != 1 {
575 return UnexpectedDataFormatSnafu {
576 expected: Self::FORMAT,
577 actual: Some(header),
578 }
579 .fail();
580 }
581 let mut typing = DataType::default();
582 reader.read_data_into(&mut typing)?;
583 *self = Type::Data(typing);
584 }
585 },
586 }
587
588 Ok(())
589 }
590}
591
592impl Encodable for Coda {
593 const FORMAT: crate::codec::Format = Format::data(1)
594 .with(Text::FORMAT)
595 .with(Text::FORMAT)
596 .with(Text::FORMAT)
597 .with(Vec::<DataType>::FORMAT);
598
599 fn encode(
600 &self,
601 writer: &mut (impl crate::codec::WritesEncodable + ?Sized),
602 ) -> Result<(), crate::codec::CodecError> {
603 writer.write_data(&self.global_name)?;
604 writer.write_data(&self.local_name)?;
605 writer.write_data(&self.docs)?;
606 writer.write_data(&self.data)?;
607 Ok(())
608 }
609}
610
611impl Decodable for Coda {
612 fn decode(
613 &mut self,
614 reader: &mut (impl crate::codec::ReadsDecodable + ?Sized),
615 header: Option<crate::codec::DataHeader>,
616 ) -> Result<(), crate::codec::CodecError> {
617 let header = Self::ensure_header(header)?;
618 let mut fields = FieldReader::new(reader, header);
619 fields.read(&mut self.global_name)?;
620 fields.read(&mut self.local_name)?;
621 fields.read(&mut self.docs)?;
622 fields.read(&mut self.data)?;
623 fields.finish()
624 }
625}
626
627impl Encodable for DataType {
628 const FORMAT: Format = Format::data(2)
629 .with(Text::FORMAT)
630 .with(Option::<Text>::FORMAT)
631 .with(Vec::<DataField>::FORMAT)
632 .with(Vec::<DataField>::FORMAT)
633 .with(Format::FORMAT);
634
635 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
636 writer.write_data(&self.name)?;
637 writer.write_data(&self.docs)?;
638 writer.write_data(&self.blob_fields)?;
639 writer.write_data(&self.data_fields)?;
640 writer.write_data(&self.format)?;
641 Ok(())
642 }
643}
644
645impl Decodable for DataType {
646 fn decode(
647 &mut self,
648 reader: &mut (impl ReadsDecodable + ?Sized),
649 header: Option<DataHeader>,
650 ) -> Result<(), CodecError> {
651 let header = Self::ensure_header(header)?;
652 let mut fields = FieldReader::new(reader, header);
653 fields.read(&mut self.name)?;
654 fields.read(&mut self.docs)?;
655 fields.read(&mut self.blob_fields)?;
656 fields.read(&mut self.data_fields)?;
657 fields.read(&mut self.format)?;
658 fields.finish()
659 }
660}
661
662impl Encodable for DataField {
663 const FORMAT: Format = Format::data(3)
664 .with(bool::FORMAT)
665 .with(bool::FORMAT)
666 .with(Text::FORMAT)
667 .with(Option::<Text>::FORMAT)
668 .with(Type::FORMAT);
669
670 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
671 writer.write_data(&self.optional)?;
672 writer.write_data(&self.flattened)?;
673 writer.write_data(&self.name)?;
674 writer.write_data(&self.docs)?;
675 writer.write_data(&self.typing)?;
676 Ok(())
677 }
678}
679
680impl Decodable for DataField {
681 fn decode(
682 &mut self,
683 reader: &mut (impl ReadsDecodable + ?Sized),
684 header: Option<DataHeader>,
685 ) -> Result<(), CodecError> {
686 let header = Self::ensure_header(header)?;
687 let mut fields = FieldReader::new(reader, header);
688 fields.read(&mut self.optional)?;
689 fields.read(&mut self.flattened)?;
690 fields.read(&mut self.name)?;
691 fields.read(&mut self.docs)?;
692 fields.read(&mut self.typing)?;
693 fields.finish()
694 }
695}
696
697impl<T> Encodable for Option<T>
698where
699 T: Default + Encodable + 'static,
700{
701 const FORMAT: Format = T::FORMAT.as_sequence();
705
706 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
707 match self {
708 None => Ok(()),
709 Some(value) => writer.write_sequence_data(value),
710 }
711 }
712
713 fn encode_header(
714 &self,
715 writer: &mut (impl WritesEncodable + ?Sized),
716 ) -> Result<(), CodecError> {
717 DataHeader {
718 count: if self.is_some() { 1 } else { 0 },
719 format: Self::FORMAT.as_data_format(),
720 }
721 .encode(writer)
722 }
723}
724
725impl<T> Decodable for Option<T>
726where
727 T: Decodable + Default + 'static,
728{
729 fn decode(
730 &mut self,
731 reader: &mut (impl ReadsDecodable + ?Sized),
732 header: Option<DataHeader>,
733 ) -> Result<(), CodecError> {
734 let header = Self::ensure_header(header)?;
735
736 match header.count {
737 0 => *self = None,
738 1 => {
739 let value = self.get_or_insert_with(T::default);
740 reader.read_next_data_into(header, value)?;
741 }
742 count => return crate::codec::UnsupportedCountSnafu { count }.fail(),
743 }
744
745 Ok(())
746 }
747}
748
749#[cfg(test)]
750mod tests {
751 use crate::codec::{Decodable, WritesEncodable};
752
753 use super::*;
754
755 #[derive(Clone, Debug, Default, PartialEq)]
757 pub struct TestData {
758 pub number: i32,
759 pub floaty: f64,
760 pub text_list: Vec<Text>,
761 pub text: Text,
762 pub nested: NestedTestData,
763 pub two_d: Vec<Vec<Text>>,
764 }
765
766 impl TestData {
767 pub fn typing() -> DataType {
768 let blob_fields = vec![
769 DataField {
770 name: Text::from("number"),
771 docs: None,
772 typing: Type::I32,
773 optional: false,
774 flattened: false,
775 },
776 DataField {
777 name: Text::from("floaty"),
778 docs: None,
779 typing: Type::F64,
780 optional: false,
781 flattened: false,
782 },
783 ];
784
785 let data_fields = vec![
786 DataField {
787 name: Text::from("text_list"),
788 docs: None,
789 typing: Type::List(Type::Text.into()),
790 optional: false,
791 flattened: false,
792 },
793 DataField {
794 name: Text::from("text"),
795 docs: None,
796 typing: Type::Text,
797 optional: false,
798 flattened: false,
799 },
800 DataField {
801 name: Text::from("nested"),
802 docs: None,
803 typing: Type::Data(NestedTestData::typing()),
804 optional: false,
805 flattened: false,
806 },
807 DataField {
808 name: Text::from("two_d"),
809 docs: None,
810 typing: Type::List(Type::List(Type::Text.into()).into()),
811 optional: false,
812 flattened: false,
813 },
814 ];
815
816 let typing = DataType::new(Text::from("Testdata"), None, 1, &blob_fields, &data_fields);
817
818 assert_eq!(Self::FORMAT, *typing.format());
819
820 typing
821 }
822 }
823
824 impl Encodable for TestData {
825 const FORMAT: Format = Format::data(1)
826 .with(i32::FORMAT)
827 .with(f64::FORMAT)
828 .with(Vec::<Text>::FORMAT)
829 .with(Text::FORMAT)
830 .with(NestedTestData::FORMAT)
831 .with(Vec::<Vec<Text>>::FORMAT);
832
833 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
834 writer.write_data(&self.number)?;
835 writer.write_data(&self.floaty)?;
836 writer.write_data(&self.text_list)?;
837 writer.write_data(&self.text)?;
838 writer.write_data(&self.nested)?;
839 writer.write_data(&self.two_d)?;
840 Ok(())
841 }
842 }
843
844 impl Decodable for TestData {
845 fn decode(
846 &mut self,
847 reader: &mut (impl ReadsDecodable + ?Sized),
848 header: Option<DataHeader>,
849 ) -> Result<(), CodecError> {
850 let header = Self::ensure_header(header)?;
851 let mut fields = FieldReader::new(reader, header);
852 fields.read(&mut self.number)?;
853 fields.read(&mut self.floaty)?;
854 fields.read(&mut self.text_list)?;
855 fields.read(&mut self.text)?;
856 fields.read(&mut self.nested)?;
857 fields.read(&mut self.two_d)?;
858 fields.finish()
859 }
860 }
861
862 #[derive(Clone, Debug, Default, PartialEq)]
865 pub struct NestedTestData {
866 pub boolean: bool,
867 }
868
869 impl NestedTestData {
870 pub fn typing() -> DataType {
871 let blob_fields = vec![DataField {
872 name: Text::from("boolean"),
873 docs: None,
874 typing: Type::Bool,
875 optional: false,
876 flattened: false,
877 }];
878
879 let data_fields = vec![];
880
881 let typing = DataType::new(
882 Text::from("NestedTestdata"),
883 None,
884 2,
885 &blob_fields,
886 &data_fields,
887 );
888
889 assert_eq!(Self::FORMAT, *typing.format());
890
891 typing
892 }
893 }
894
895 impl Encodable for NestedTestData {
896 const FORMAT: Format = Format::data(2).with(bool::FORMAT);
897
898 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
899 writer.write_data(&self.boolean)?;
900 Ok(())
901 }
902 }
903
904 impl Decodable for NestedTestData {
905 fn decode(
906 &mut self,
907 reader: &mut (impl ReadsDecodable + ?Sized),
908 header: Option<DataHeader>,
909 ) -> Result<(), CodecError> {
910 let header = Self::ensure_header(header)?;
911 let mut fields = FieldReader::new(reader, header);
912 fields.read(&mut self.boolean)?;
913 fields.finish()
914 }
915 }
916
917 #[derive(Clone, Debug, Default, PartialEq)]
919 pub struct EvolvedNestedTestData {
920 pub boolean: bool,
921 pub extra_number: u16,
922 pub extra_text: Text,
923 pub extra_optional: Option<u32>,
924 }
925
926 impl Encodable for EvolvedNestedTestData {
927 const FORMAT: Format = Format::data(2)
928 .with(bool::FORMAT)
929 .with(u16::FORMAT)
930 .with(Text::FORMAT)
931 .with(Option::<u32>::FORMAT);
932
933 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
934 writer.write_data(&self.boolean)?;
935 writer.write_data(&self.extra_number)?;
936 writer.write_data(&self.extra_text)?;
937 writer.write_data(&self.extra_optional)?;
938 Ok(())
939 }
940 }
941
942 impl Decodable for EvolvedNestedTestData {
943 fn decode(
944 &mut self,
945 reader: &mut (impl ReadsDecodable + ?Sized),
946 header: Option<DataHeader>,
947 ) -> Result<(), CodecError> {
948 let header = Self::ensure_header(header)?;
949 let mut fields = FieldReader::new(reader, header);
950 fields.read(&mut self.boolean)?;
951 fields.read(&mut self.extra_number)?;
952 fields.read(&mut self.extra_text)?;
953 fields.read(&mut self.extra_optional)?;
954 fields.finish()
955 }
956 }
957
958 #[test]
959 pub fn data_type_codec() {
960 let data_type = TestData::typing();
961
962 let mut encoded_data_type = vec![];
963 encoded_data_type.write_data(&data_type).unwrap();
964 let decoded_data_type = encoded_data_type.as_slice().read_data().unwrap();
965
966 assert_eq!(data_type, decoded_data_type);
967 }
968
969 #[test]
970 fn schema_formats_match_runtime_formats() {
971 use alloc::collections::BTreeMap;
972
973 fn check<T: Encodable>(typing: Type) {
974 assert_eq!(T::FORMAT, typing.format(), "{typing:?}");
975 }
976
977 fn check_optional<T: Encodable + Default + 'static>(typing: Type) {
978 let field = DataField {
979 name: Text::from("field"),
980 docs: None,
981 typing: typing.clone(),
982 optional: true,
983 flattened: false,
984 };
985 assert_eq!(Option::<T>::FORMAT, field.format(), "optional {typing:?}");
986 }
987
988 let data = || Type::Data(TestData::typing());
989 let map = || Type::Map((Type::Text, Type::F32).into());
990
991 check::<u8>(Type::U8);
992 check::<u16>(Type::U16);
993 check::<u32>(Type::U32);
994 check::<u64>(Type::U64);
995 check::<i8>(Type::I8);
996 check::<i16>(Type::I16);
997 check::<i32>(Type::I32);
998 check::<i64>(Type::I64);
999 check::<f32>(Type::F32);
1000 check::<f64>(Type::F64);
1001 check::<bool>(Type::Bool);
1002 check::<Text>(Type::Text);
1003 check::<Unspecified>(Type::Unspecified);
1004 check::<Array<u8, 32>>(Type::Array(32, Type::U8.into()));
1005 check::<Array<Array<f32, 3>, 3>>(Type::Array(3, Type::Array(3, Type::F32.into()).into()));
1006 check::<TestData>(data());
1007 check::<BTreeMap<Text, f32>>(map());
1008
1009 check::<Vec<u32>>(Type::List(Type::U32.into()));
1010 check::<Vec<Text>>(Type::List(Type::Text.into()));
1011 check::<Vec<Vec<Text>>>(Type::List(Type::List(Type::Text.into()).into()));
1012 check::<Vec<Unspecified>>(Type::List(Type::Unspecified.into()));
1013 check::<Vec<Array<f32, 3>>>(Type::List(Type::Array(3, Type::F32.into()).into()));
1014 check::<Vec<TestData>>(Type::List(data().into()));
1015 check::<Vec<BTreeMap<Text, f32>>>(Type::List(map().into()));
1016
1017 check_optional::<u32>(Type::U32);
1018 check_optional::<Text>(Type::Text);
1019 check_optional::<Unspecified>(Type::Unspecified);
1020 check_optional::<Array<u8, 48>>(Type::Array(48, Type::U8.into()));
1021 check_optional::<TestData>(data());
1022 check_optional::<BTreeMap<Text, f32>>(map());
1023 check_optional::<Vec<u32>>(Type::List(Type::U32.into()));
1024 check_optional::<Vec<TestData>>(Type::List(data().into()));
1025 }
1026
1027 #[test]
1030 fn options_are_short_lists() -> Result<(), CodecError> {
1031 fn check<T>(some: T) -> Result<(), CodecError>
1032 where
1033 T: Decodable + Default + Clone + PartialEq + core::fmt::Debug + 'static,
1034 {
1035 for (option, list) in [(None, vec![]), (Some(some.clone()), vec![some])] {
1036 let mut option_bytes = vec![];
1037 option_bytes.write_data(&option)?;
1038 let mut list_bytes = vec![];
1039 list_bytes.write_data(&list)?;
1040 assert_eq!(option_bytes, list_bytes);
1041
1042 assert_eq!(option, option_bytes.as_slice().read_data::<Option<T>>()?);
1043 assert_eq!(list, list_bytes.as_slice().read_data::<Vec<T>>()?);
1044 assert_eq!(list, option_bytes.as_slice().read_data::<Vec<T>>()?);
1045 assert_eq!(option, list_bytes.as_slice().read_data::<Option<T>>()?);
1046 }
1047
1048 let mut list_bytes = vec![];
1050 list_bytes.write_data(&vec![T::default(), T::default()])?;
1051 assert!(matches!(
1052 list_bytes.as_slice().read_data::<Option<T>>(),
1053 Err(CodecError::UnsupportedCount { count: 2 })
1054 ));
1055
1056 Ok(())
1057 }
1058
1059 check(7u32)?;
1060 check(Text::from("seven"))?;
1061 check(NestedTestData { boolean: true })?;
1062 check(vec![7u32])?;
1063 check(Some(7u32))?;
1064 Ok(())
1065 }
1066
1067 #[test]
1068 fn named_data_are_packed() -> Result<(), CodecError> {
1069 let list = vec![
1070 NestedTestData { boolean: true },
1071 NestedTestData { boolean: false },
1072 NestedTestData { boolean: true },
1073 ];
1074
1075 let mut encoded = vec![];
1076 encoded.write_data(&list)?;
1077 assert_eq!(8 + 3, encoded.len(), "one header, then packed data");
1078 assert_eq!(
1079 [3, 0, 0, 0, 1, 0, 0, 2, 1, 0, 1],
1080 encoded.as_slice(),
1081 "count=3, blob_size=1, data_fields=0, ordinal=2, then bools"
1082 );
1083 let decoded: Vec<NestedTestData> = encoded.as_slice().read_data()?;
1084 assert_eq!(list, decoded);
1085
1086 let optional = Some(NestedTestData { boolean: true });
1087 let mut encoded = vec![];
1088 encoded.write_data(&optional)?;
1089 assert_eq!(8 + 1, encoded.len(), "one header, then the packed data");
1090 let decoded: Option<NestedTestData> = encoded.as_slice().read_data()?;
1091 assert_eq!(optional, decoded);
1092
1093 let mut encoded = vec![];
1096 encoded.write_data(&list)?;
1097 assert!(matches!(
1098 encoded.as_slice().read_data::<NestedTestData>(),
1099 Err(CodecError::UnsupportedCount { count: 3 })
1100 ));
1101
1102 Ok(())
1103 }
1104
1105 #[test]
1106 fn evolved_data_decode() -> Result<(), CodecError> {
1107 let old = NestedTestData { boolean: true };
1108 let new = EvolvedNestedTestData {
1109 boolean: true,
1110 extra_number: 9001,
1111 extra_text: "extra".into(),
1112 extra_optional: Some(7),
1113 };
1114
1115 let mut encoded = vec![];
1118 encoded.write_data(&new)?;
1119 encoded.write_data(&42u8)?; let mut reader = encoded.as_slice();
1121 let decoded: NestedTestData = reader.read_data()?;
1122 assert_eq!(old, decoded);
1123 assert_eq!(42u8, reader.read_data()?, "skipped to the sentinel");
1124
1125 let mut encoded = vec![];
1129 encoded.write_data(&old)?;
1130 let mut decoded = new.clone();
1131 encoded.as_slice().read_data_into(&mut decoded)?;
1132 assert_eq!(
1133 EvolvedNestedTestData {
1134 boolean: true,
1135 ..Default::default()
1136 },
1137 decoded
1138 );
1139
1140 let news = vec![new.clone(), new.clone()];
1142 let mut encoded = vec![];
1143 encoded.write_data(&news)?;
1144 encoded.write_data(&42u8)?;
1145 let mut reader = encoded.as_slice();
1146 let decoded: Vec<NestedTestData> = reader.read_data()?;
1147 assert_eq!(vec![old.clone(), old.clone()], decoded);
1148 assert_eq!(42u8, reader.read_data()?, "skipped to the sentinel");
1149
1150 let olds = vec![old.clone(), old.clone()];
1151 let mut encoded = vec![];
1152 encoded.write_data(&olds)?;
1153 let decoded: Vec<EvolvedNestedTestData> = encoded.as_slice().read_data()?;
1154 assert_eq!(
1155 vec![
1156 EvolvedNestedTestData {
1157 boolean: true,
1158 ..Default::default()
1159 };
1160 2
1161 ],
1162 decoded
1163 );
1164
1165 let mut encoded = vec![];
1167 encoded.write_data(&Some(new.clone()))?;
1168 let decoded: Option<NestedTestData> = encoded.as_slice().read_data()?;
1169 assert_eq!(Some(old), decoded);
1170
1171 Ok(())
1172 }
1173
1174 #[test]
1175 fn invalid_utf8_is_an_error() {
1176 let mut encoded = vec![];
1177 encoded.write_data(&Text::from("ok")).unwrap();
1178 encoded[8] = 0xFF;
1179 assert!(matches!(
1180 encoded.as_slice().read_data::<Text>(),
1181 Err(CodecError::InvalidUtf8)
1182 ));
1183 }
1184
1185 #[test]
1186 fn array_type_codec() {
1187 let typing = Type::Array(4096, Type::U8.into());
1190 let mut encoded = vec![];
1191 encoded.write_data(&typing).unwrap();
1192 let decoded: Type = encoded.as_slice().read_data().unwrap();
1193 assert_eq!(typing, decoded);
1194
1195 let typing = Type::Array(3, Type::Array(3, Type::F32.into()).into());
1197 assert_eq!(Format::Blob(36), typing.format());
1198 let mut encoded = vec![];
1199 encoded.write_data(&typing).unwrap();
1200 let decoded: Type = encoded.as_slice().read_data().unwrap();
1201 assert_eq!(typing, decoded);
1202
1203 let data_type = DataType::new(Text::from("Blobby"), None, 1, &[], &[]).with(DataField {
1205 name: Text::from("hash"),
1206 docs: None,
1207 typing: Type::Array(32, Type::U8.into()),
1208 optional: false,
1209 flattened: false,
1210 });
1211 assert_eq!(Format::data(1).with(Format::Blob(32)), *data_type.format());
1212
1213 let mut encoded = vec![];
1214 encoded.write_data(&data_type).unwrap();
1215 let decoded: DataType = encoded.as_slice().read_data().unwrap();
1216 assert_eq!(data_type, decoded);
1217 }
1218
1219 #[derive(Clone, Debug, Default, PartialEq)]
1223 struct BlobTestData {
1224 id: u32,
1225 hash: Array<u8, 16>,
1226 text: Text,
1227 }
1228
1229 impl Encodable for BlobTestData {
1230 const FORMAT: Format = Format::data(1)
1231 .with(u32::FORMAT)
1232 .with(Array::<u8, 16>::FORMAT)
1233 .with(Text::FORMAT);
1234
1235 fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
1236 writer.write_data(&self.id)?;
1237 writer.write_data(&self.hash)?;
1238 writer.write_data(&self.text)?;
1239 Ok(())
1240 }
1241 }
1242
1243 impl Decodable for BlobTestData {
1244 fn decode(
1245 &mut self,
1246 reader: &mut (impl ReadsDecodable + ?Sized),
1247 header: Option<DataHeader>,
1248 ) -> Result<(), CodecError> {
1249 let _ = Self::ensure_header(header)?;
1250 reader.read_data_into(&mut self.id)?;
1251 reader.read_data_into(&mut self.hash)?;
1252 reader.read_data_into(&mut self.text)?;
1253 Ok(())
1254 }
1255 }
1256
1257 #[test]
1258 fn blob_fields_encode_into_blob_section() {
1259 assert_eq!(
1262 Format::Data(DataFormat {
1263 blob_size: 4 + 16,
1264 data_fields: 1,
1265 ordinal: 1,
1266 }),
1267 BlobTestData::FORMAT
1268 );
1269
1270 let data = BlobTestData {
1271 id: 9001,
1272 hash: Array([7; 16]),
1273 text: "blobby!".into(),
1274 };
1275 let mut encoded = vec![];
1276 encoded.write_data(&data).unwrap();
1277
1278 assert_eq!(8 + 4 + 16 + 8 + data.text.len(), encoded.len());
1281
1282 assert_eq!(&[7; 16], &encoded[12..28]);
1285
1286 let decoded: BlobTestData = encoded.as_slice().read_data().unwrap();
1287 assert_eq!(data, decoded);
1288 }
1289
1290 #[test]
1291 fn blob_field_lists_encode_homogeneously() {
1292 let list: Vec<[u8; 4]> = vec![[1; 4], [2; 4], [3; 4]];
1296 let mut encoded = vec![];
1297 encoded.write_data(&list).unwrap();
1298 assert_eq!(8 + 3 * 4, encoded.len());
1299
1300 let decoded: Vec<[u8; 4]> = encoded.as_slice().read_data().unwrap();
1301 assert_eq!(list, decoded);
1302 }
1303
1304 #[test]
1305 fn codes_unstructured_optionals() {
1306 let option: Option<u32> = Some(1337u32);
1307 let mut data = vec![];
1308 data.write_data(&option).expect("encoded");
1309 println!("encoded");
1310 let decoded_option = data.as_slice().read_data().expect("decoded");
1311 assert_eq!(option, decoded_option);
1312
1313 let option: Option<u32> = None;
1315 let mut data = vec![];
1316 data.write_data(&option).expect("encoded");
1317 let decoded_option = data.as_slice().read_data().expect("decoded");
1318 assert_eq!(option, decoded_option);
1319
1320 let option: Option<u32> = Some(0);
1322 let mut data = vec![];
1323 data.write_data(&option).expect("encoded");
1324 let decoded_option: Option<u32> = data.as_slice().read_data().expect("decoded");
1325 assert_eq!(Some(0), decoded_option);
1326 }
1327
1328 #[test]
1329 fn codes_structured_optionals() {
1330 let option: Option<Text> = Some("Hello, World!".into());
1331 let mut data = vec![];
1332 data.write_data(&option).expect("encoded");
1333 println!("encoded");
1334 let decoded_option = data.as_slice().read_data().expect("decoded");
1335 assert_eq!(option, decoded_option);
1336
1337 let option: Option<Text> = None;
1339 let mut data = vec![];
1340 data.write_data(&option).expect("encoded");
1341 let decoded_option = data.as_slice().read_data().expect("decoded");
1342 assert_eq!(option, decoded_option);
1343
1344 let option: Option<Text> = Some("".into());
1346 let mut data = vec![];
1347 data.write_data(&option).expect("encoded");
1348 let decoded_option: Option<Text> = data.as_slice().read_data().expect("decoded");
1349 assert_eq!(Some("".into()), decoded_option);
1350 }
1351
1352 #[test]
1353 fn codes_nested_optionals() {
1354 let option: Option<Option<u32>> = None;
1356 let mut data = vec![];
1357 data.write_data(&option).expect("encoded");
1358 let decoded: Option<Option<u32>> = data.as_slice().read_data().expect("decoded");
1359 assert_eq!(option, decoded);
1360
1361 let option: Option<Option<u32>> = Some(None);
1363 let mut data = vec![];
1364 data.write_data(&option).expect("encoded");
1365 let decoded: Option<Option<u32>> = data.as_slice().read_data().expect("decoded");
1366 assert_eq!(option, decoded);
1367
1368 let option: Option<Option<u32>> = Some(Some(0));
1370 let mut data = vec![];
1371 data.write_data(&option).expect("encoded");
1372 let decoded: Option<Option<u32>> = data.as_slice().read_data().expect("decoded");
1373 assert_eq!(option, decoded);
1374
1375 let option: Option<Option<u32>> = Some(Some(42));
1377 let mut data = vec![];
1378 data.write_data(&option).expect("encoded");
1379 let decoded: Option<Option<u32>> = data.as_slice().read_data().expect("decoded");
1380 assert_eq!(option, decoded);
1381 }
1382
1383 #[test]
1384 fn codes_optional_vec() {
1385 let option: Option<Vec<u16>> = None;
1387 let mut data = vec![];
1388 data.write_data(&option).expect("encoded");
1389 let decoded: Option<Vec<u16>> = data.as_slice().read_data().expect("decoded");
1390 assert_eq!(option, decoded);
1391
1392 let option: Option<Vec<u16>> = Some(vec![]);
1394 let mut data = vec![];
1395 data.write_data(&option).expect("encoded");
1396 let decoded: Option<Vec<u16>> = data.as_slice().read_data().expect("decoded");
1397 assert_eq!(option, decoded);
1398
1399 let option: Option<Vec<u16>> = Some(vec![42]);
1401 let mut data = vec![];
1402 data.write_data(&option).expect("encoded");
1403 let decoded: Option<Vec<u16>> = data.as_slice().read_data().expect("decoded");
1404 assert_eq!(option, decoded);
1405 }
1406
1407 #[test]
1411 fn ordinal_round_trip() {
1412 for ordinal in 0..=255u8 {
1413 if let Some(typ) = Type::from_ordinal(ordinal) {
1414 assert_eq!(
1415 ordinal,
1416 typ.ordinal(),
1417 "from_ordinal({ordinal}) returned {typ:?} with ordinal {}",
1418 typ.ordinal()
1419 );
1420 }
1421 }
1422 }
1423}