Skip to main content

codas/
types.rs

1//! Built-in data types and their in-memory
2//! representations.
3//!
4//! # Unstable
5//!
6//! The APIs exposed by this module are _primarily_
7//! used for code generation and dynamic data manipulation;
8//! the exact APIs are subject to change, and may
9//! not be well-optimized.
10use core::convert::Infallible;
11
12use alloc::{boxed::Box, vec, vec::Vec};
13
14use crate::codec::{
15    CodecError, DataFormat, DataHeader, Decodable, Encodable, Format, FormatMetadata,
16    ReadsDecodable, 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 dynamic::Unspecified;
27pub use text::*;
28
29/// Enumeration of available built in types.
30#[non_exhaustive]
31#[derive(Default, Debug, Clone, PartialEq)]
32pub enum Type {
33    /// Unspecified data.
34    #[default]
35    Unspecified,
36
37    /// Unsigned (positive) 8-bit number.
38    U8,
39    /// Unsigned (positive) 16-bit number.
40    U16,
41    /// Unsigned (positive) 32-bit number.
42    U32,
43    /// Unsigned (positive) 64-bit number.
44    U64,
45
46    /// Signed (positive or negative) 8-bit number.
47    I8,
48    /// Signed (positive or negative) 16-bit number.
49    I16,
50    /// Signed (positive or negative) 32-bit number.
51    I32,
52    /// Signed (positive or negative) 64-bit number.
53    I64,
54
55    /// 32-bit floating point (decimal) number.
56    F32,
57    /// 64-bit floating point (decimal) number.
58    F64,
59
60    /// Boolean (true or false).
61    Bool,
62
63    /// UTF-8 encoded text.
64    Text,
65
66    /// Data with [`DataType`].
67    Data(DataType),
68
69    /// Data with [`Type`] that's _semantically_ a list.
70    List(Box<Type>),
71
72    /// A mapping between data of two types.
73    Map(Box<(Type, Type)>),
74}
75
76impl Type {
77    /// The type's encoding format.
78    pub const fn format(&self) -> Format {
79        match self {
80            Type::Unspecified => Format::Fluid,
81            Type::U8 => u8::FORMAT,
82            Type::U16 => u16::FORMAT,
83            Type::U32 => u32::FORMAT,
84            Type::U64 => u64::FORMAT,
85            Type::I8 => i8::FORMAT,
86            Type::I16 => i16::FORMAT,
87            Type::I32 => i32::FORMAT,
88            Type::I64 => i64::FORMAT,
89            Type::F32 => f32::FORMAT,
90            Type::F64 => f64::FORMAT,
91            Type::Bool => bool::FORMAT,
92            Type::Text => Text::FORMAT,
93            Type::Data(data) => data.format,
94            Type::List(typing) => typing.format().as_data_format().as_format(),
95
96            // Maps are formatted as a list of keys
97            // followed by a list of values.
98            Type::Map(..) => DataFormat {
99                ordinal: 0,
100                blob_size: 0,
101                data_fields: 2,
102            }
103            .as_format(),
104        }
105    }
106
107    /// Returns the type with `name`.
108    ///
109    /// This function assumes `name` is in ASCII lowercase.
110    pub fn from_name(name: &str) -> Option<Self> {
111        match name {
112            "unspecified" => Some(Type::Unspecified),
113            "u8" => Some(Type::U8),
114            "u16" => Some(Type::U16),
115            "u32" => Some(Type::U32),
116            "u64" => Some(Type::U64),
117            "i8" => Some(Type::I8),
118            "i16" => Some(Type::I16),
119            "i32" => Some(Type::I32),
120            "i64" => Some(Type::I64),
121            "f32" => Some(Type::F32),
122            "f64" => Some(Type::F64),
123            "bool" => Some(Type::Bool),
124            "text" => Some(Type::Text),
125            _ => None,
126        }
127    }
128}
129
130/// In-memory representation of a coda.
131#[derive(Default, Debug, Clone, PartialEq)]
132pub struct Coda {
133    /// The coda's full name, including any
134    /// hierarchical components and separators.
135    pub global_name: Text,
136
137    /// The final component of [`Self::global_name`]
138    /// that does not describe a hierarchy.
139    pub local_name: Text,
140
141    pub docs: Option<Text>,
142
143    /// Data in ascending order by ordinal.
144    pub(crate) data: Vec<DataType>,
145}
146
147impl Coda {
148    /// Returns a new coda containing `data`.
149    pub fn new(global_name: Text, local_name: Text, docs: Option<Text>, data: &[DataType]) -> Self {
150        Self {
151            global_name,
152            local_name,
153            docs,
154            data: Vec::from(data),
155        }
156    }
157
158    /// Returns an iterator over all data types in the coda.
159    ///
160    /// The implicit [`crate::types::Unspecified`] data type
161    /// is _not_ included in the returned iterator.
162    pub fn iter(&self) -> impl Iterator<Item = &DataType> {
163        self.data.iter()
164    }
165
166    /// Returns the data type with `name`,
167    /// if it is known by the coda.
168    #[cfg(feature = "parse")]
169    pub(crate) fn type_from_name(&self, name: &str) -> Option<Type> {
170        for data in self.data.iter() {
171            if data.name.eq_ignore_ascii_case(name) {
172                return Some(Type::Data(data.clone()));
173            }
174        }
175
176        Type::from_name(name)
177    }
178}
179
180/// Data containing a structured set of [`DataField`]s.
181#[derive(Default, Debug, Clone, PartialEq)]
182pub struct DataType {
183    /// The name of the data type.
184    ///
185    /// TODO: We've been structuring names similar
186    /// to fully-qualified Rust type names (like `my::data::TypeName`).
187    /// We should standardize on a language-neutral naming
188    /// convention; perhaps HTTP-style URLs (like `/my/data/TypeName`)
189    /// so downstream tools have an easy way to map hierarchical
190    /// names back to native type names as appropriate.
191    pub name: Text,
192
193    /// Markdown-formatted documentation of the data type.
194    pub docs: Option<Text>,
195
196    /// Ordered set of [`Format::Blob`]
197    /// fields in the data type.
198    blob_fields: Vec<DataField>,
199
200    /// Ordered set of [`Format::Data`]
201    /// fields in the data type.
202    ///
203    /// These fields are always encoded, in
204    /// order, _after_ all [`Self::blob_fields`].
205    data_fields: Vec<DataField>,
206
207    /// The encoding format of data with this type.
208    format: Format,
209}
210
211impl DataType {
212    /// Returns a new fixed data type with
213    /// `name`, `ordinal`, `blob_fields`, and `data_fields`.
214    pub fn new(
215        name: Text,
216        docs: Option<Text>,
217        ordinal: FormatMetadata,
218        blob_fields: &[DataField],
219        data_fields: &[DataField],
220    ) -> Self {
221        // Build a new encoding format for the data.
222        let mut format = Format::data(ordinal);
223
224        // Add blob fields to the format.
225        let mut i = 0;
226        while i < blob_fields.len() {
227            let field = &blob_fields[i];
228            format = format.with(field.typing.format());
229            i += 1;
230        }
231
232        // Add data fields to the format.
233        let mut i = 0;
234        while i < data_fields.len() {
235            let field = &data_fields[i];
236            format = format.with(field.typing.format());
237            i += 1;
238        }
239
240        Self {
241            name,
242            docs,
243            blob_fields: Vec::from(blob_fields),
244            data_fields: Vec::from(data_fields),
245            format,
246        }
247    }
248
249    /// Returns a new data type with a fluid format.
250    pub const fn new_fluid(name: Text, docs: Option<Text>) -> Self {
251        Self {
252            name,
253            docs,
254            blob_fields: vec![],
255            data_fields: vec![],
256            format: Format::Fluid,
257        }
258    }
259
260    /// Returns an iterator over all fields within the type.
261    pub fn iter(&self) -> impl Iterator<Item = &DataField> {
262        self.blob_fields.iter().chain(self.data_fields.iter())
263    }
264
265    /// Adds a new `field` to the type.
266    pub fn with(mut self, field: DataField) -> Self {
267        if matches!(self.format, Format::Fluid) {
268            todo!("it should be an error to add fields to a type defined as fluid")
269        }
270
271        let field_format = field.typing.format();
272        self.format = self.format.with(field_format);
273        match field_format {
274            Format::Blob(..) => {
275                self.blob_fields.push(field);
276            }
277            Format::Data(..) | Format::Fluid => {
278                self.data_fields.push(field);
279            }
280        };
281
282        self
283    }
284
285    /// Returns the type's encoding format.
286    pub const fn format(&self) -> &Format {
287        &self.format
288    }
289}
290
291/// A field in a [`DataType`].
292#[derive(Default, Clone, Debug, PartialEq)]
293pub struct DataField {
294    /// Name of the field.
295    pub name: Text,
296
297    /// Markdown-formatted documentation of the field.
298    pub docs: Option<Text>,
299
300    /// Type of the field.
301    pub typing: Type,
302
303    /// True if the field is semantically optional.
304    pub optional: bool,
305
306    /// True if the field is semantically flattened.
307    ///
308    /// This property has _no_ effect on the encoding,
309    /// decoding, or in-language representation of
310    /// a field; it's an informational marker that some
311    /// marshallers (like JSON) may use to enable
312    /// compatibility between coda-defined data and
313    /// legacy systems.
314    pub flattened: bool,
315}
316
317/// A thing that _might_ contain data with a
318/// specific format `D`.
319///
320/// This trait is mainly intended for use with the
321/// enums auto-generated for [`Coda`]s
322pub trait TryAsFormat<D> {
323    /// Type of error returned when `self`
324    /// doesn't contain data of format `D`.
325    ///
326    /// This error should be the ordinal
327    /// identifier of the _actual_ data in `D`,
328    /// or [`Infallible`].
329    type Error;
330
331    /// Returns a `D`-formatted reference to the data.
332    fn try_as_format(&self) -> Result<&D, Self::Error>;
333}
334
335/// Every data format can be interpreted as itself.
336impl<T> TryAsFormat<T> for T {
337    type Error = Infallible;
338
339    fn try_as_format(&self) -> Result<&T, Self::Error> {
340        Ok(self)
341    }
342}
343
344// Codecs /////////////////////////////////////////////////
345
346impl Encodable for Type {
347    const FORMAT: Format = Format::Fluid;
348
349    fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
350        match self {
351            Type::Data(typing) => writer.write_data(typing),
352            Type::List(typing) => writer.write_data(typing.as_ref()),
353            Type::Map(typing) => {
354                writer.write_data(&typing.as_ref().0)?;
355                writer.write_data(&typing.as_ref().1)?;
356                Ok(())
357            }
358
359            // Only data types contain additional encoded info.
360            _ => Ok(()),
361        }
362    }
363
364    fn encode_header(
365        &self,
366        writer: &mut (impl WritesEncodable + ?Sized),
367    ) -> Result<(), CodecError> {
368        let ordinal = match self {
369            Type::Unspecified => 0u16,
370            Type::U8 => 1u16,
371            Type::U16 => 2u16,
372            Type::U32 => 3u16,
373            Type::U64 => 4u16,
374            Type::I8 => 5u16,
375            Type::I16 => 6u16,
376            Type::I32 => 7u16,
377            Type::I64 => 8u16,
378            Type::F32 => 9u16,
379            Type::F64 => 10u16,
380            Type::Bool => 11u16,
381            Type::Text => 12u16,
382            Type::Data(..) => {
383                return DataHeader {
384                    count: 1,
385                    format: Format::data(13u16).with(Type::FORMAT).as_data_format(),
386                }
387                .encode(writer);
388            }
389            Type::List { .. } => {
390                return DataHeader {
391                    count: 1,
392                    format: Format::data(14u16).with(Type::FORMAT).as_data_format(),
393                }
394                .encode(writer);
395            }
396            Type::Map { .. } => {
397                return DataHeader {
398                    count: 1,
399                    format: Format::data(15u16).with(Type::FORMAT).as_data_format(),
400                }
401                .encode(writer);
402            }
403        };
404
405        DataHeader {
406            count: 1,
407            format: Format::data(ordinal).as_data_format(),
408        }
409        .encode(writer)
410    }
411}
412
413impl Decodable for Type {
414    fn decode(
415        &mut self,
416        reader: &mut (impl ReadsDecodable + ?Sized),
417        header: Option<DataHeader>,
418    ) -> Result<(), CodecError> {
419        let header = Self::ensure_header(
420            header,
421            &[
422                0u16, 1u16, 2u16, 3u16, 4u16, 5u16, 6u16, 7u16, 8u16, 9u16, 10u16, 11u16, 12u16,
423                13u16, 14u16, 15u16,
424            ],
425        )?;
426
427        match header.format.ordinal {
428            0u16 => {
429                *self = Type::Unspecified;
430            }
431            1u16 => {
432                *self = Type::U8;
433            }
434            2u16 => {
435                *self = Type::U16;
436            }
437            3u16 => {
438                *self = Type::U32;
439            }
440            4u16 => {
441                *self = Type::U64;
442            }
443            5u16 => {
444                *self = Type::I8;
445            }
446            6u16 => {
447                *self = Type::I16;
448            }
449            7u16 => {
450                *self = Type::I32;
451            }
452            8u16 => {
453                *self = Type::I64;
454            }
455            9u16 => {
456                *self = Type::F32;
457            }
458            10u16 => {
459                *self = Type::F64;
460            }
461            11u16 => {
462                *self = Type::Bool;
463            }
464            12u16 => {
465                *self = Type::Text;
466            }
467            13u16 => {
468                let mut typing = DataType::default();
469                reader.read_data_into(&mut typing)?;
470                *self = Type::Data(typing);
471            }
472            14u16 => {
473                let mut typing = Type::default();
474                reader.read_data_into(&mut typing)?;
475                *self = Type::List(typing.into());
476            }
477            15u16 => {
478                let mut key_typing = Type::default();
479                reader.read_data_into(&mut key_typing)?;
480                let mut value_typing = Type::default();
481                reader.read_data_into(&mut value_typing)?;
482                *self = Type::Map((key_typing, value_typing).into());
483            }
484            _ => unreachable!(),
485        };
486
487        Ok(())
488    }
489}
490
491impl Encodable for Coda {
492    const FORMAT: crate::codec::Format = Format::data(0)
493        .with(Text::FORMAT)
494        .with(Text::FORMAT)
495        .with(Text::FORMAT)
496        .with(Vec::<DataType>::FORMAT);
497
498    fn encode(
499        &self,
500        writer: &mut (impl crate::codec::WritesEncodable + ?Sized),
501    ) -> Result<(), crate::codec::CodecError> {
502        writer.write_data(&self.global_name)?;
503        writer.write_data(&self.local_name)?;
504        writer.write_data(&self.docs)?;
505        writer.write_data(&self.data)?;
506        Ok(())
507    }
508}
509
510impl Decodable for Coda {
511    fn decode(
512        &mut self,
513        reader: &mut (impl crate::codec::ReadsDecodable + ?Sized),
514        header: Option<crate::codec::DataHeader>,
515    ) -> Result<(), crate::codec::CodecError> {
516        let _ = Self::ensure_header(header, &[0u16])?;
517
518        reader.read_data_into(&mut self.global_name)?;
519        reader.read_data_into(&mut self.local_name)?;
520        reader.read_data_into(&mut self.docs)?;
521        reader.read_data_into(&mut self.data)?;
522
523        Ok(())
524    }
525}
526
527impl Encodable for DataType {
528    const FORMAT: Format = Format::data(0)
529        .with(Text::FORMAT)
530        .with(Option::<Text>::FORMAT)
531        .with(Vec::<DataField>::FORMAT)
532        .with(Vec::<DataField>::FORMAT)
533        .with(Format::FORMAT);
534
535    fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
536        writer.write_data(&self.name)?;
537        writer.write_data(&self.docs)?;
538        writer.write_data(&self.blob_fields)?;
539        writer.write_data(&self.data_fields)?;
540        writer.write_data(&self.format)?;
541        Ok(())
542    }
543}
544
545impl Decodable for DataType {
546    fn decode(
547        &mut self,
548        reader: &mut (impl ReadsDecodable + ?Sized),
549        header: Option<DataHeader>,
550    ) -> Result<(), CodecError> {
551        let _ = Self::ensure_header(header, &[0])?;
552
553        reader.read_data_into(&mut self.name)?;
554        reader.read_data_into(&mut self.docs)?;
555        reader.read_data_into(&mut self.blob_fields)?;
556        reader.read_data_into(&mut self.data_fields)?;
557        reader.read_data_into(&mut self.format)?;
558
559        Ok(())
560    }
561}
562
563impl Encodable for DataField {
564    const FORMAT: Format = Format::data(0)
565        .with(bool::FORMAT)
566        .with(bool::FORMAT)
567        .with(Text::FORMAT)
568        .with(Option::<Text>::FORMAT)
569        .with(Type::FORMAT);
570
571    fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
572        writer.write_data(&self.optional)?;
573        writer.write_data(&self.flattened)?;
574        writer.write_data(&self.name)?;
575        writer.write_data(&self.docs)?;
576        writer.write_data(&self.typing)?;
577        Ok(())
578    }
579}
580
581impl Decodable for DataField {
582    fn decode(
583        &mut self,
584        reader: &mut (impl ReadsDecodable + ?Sized),
585        header: Option<DataHeader>,
586    ) -> Result<(), CodecError> {
587        let _ = Self::ensure_header(header, &[0])?;
588        reader.read_data_into(&mut self.optional)?;
589        reader.read_data_into(&mut self.flattened)?;
590        reader.read_data_into(&mut self.name)?;
591        reader.read_data_into(&mut self.docs)?;
592        reader.read_data_into(&mut self.typing)?;
593        Ok(())
594    }
595}
596
597impl<T> Encodable for Option<T>
598where
599    T: Default + Encodable + 'static,
600{
601    /// Options are a semantic feature that's not
602    /// technically encoded: Optional data encodes
603    /// identically to "not optional" data. In the
604    /// case of `None`, data is encoded and decoded
605    /// as its default value.
606    const FORMAT: Format = T::FORMAT;
607
608    fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
609        match &self {
610            Some(value) => {
611                value.encode(writer)?;
612            }
613
614            None => {
615                Self::FORMAT.encode_default_value(writer)?;
616            }
617        }
618
619        Ok(())
620    }
621
622    fn encode_header(
623        &self,
624        writer: &mut (impl WritesEncodable + ?Sized),
625    ) -> Result<(), CodecError> {
626        match &self {
627            Some(value) => value.encode_header(writer),
628            None => Self::FORMAT.encode_default_header(writer),
629        }
630    }
631}
632
633impl<T> Decodable for Option<T>
634where
635    T: Decodable + Default + PartialEq + 'static,
636{
637    fn decode(
638        &mut self,
639        reader: &mut (impl ReadsDecodable + ?Sized),
640        header: Option<DataHeader>,
641    ) -> Result<(), CodecError> {
642        let mut decoded = T::default();
643        decoded.decode(reader, header)?;
644
645        // TODO: It'd be better if we could detect "defaulty-ness"
646        //       during the decoding step, so that we're not having
647        //       to manually compare a decoded value to its default.
648        if decoded == T::default() {
649            *self = None;
650        } else {
651            *self = Some(decoded);
652        }
653
654        Ok(())
655    }
656}
657
658#[cfg(test)]
659mod tests {
660    use crate::codec::{Decodable, WritesEncodable};
661
662    use super::*;
663
664    /// Sample data structure for testing type manipulation APIs.
665    #[derive(Clone, Debug, Default, PartialEq)]
666    pub struct TestData {
667        pub number: i32,
668        pub floaty: f64,
669        pub text_list: Vec<Text>,
670        pub text: Text,
671        pub nested: NestedTestData,
672        pub two_d: Vec<Vec<Text>>,
673    }
674
675    impl TestData {
676        pub fn typing() -> DataType {
677            let blob_fields = vec![
678                DataField {
679                    name: Text::from("number"),
680                    docs: None,
681                    typing: Type::I32,
682                    optional: false,
683                    flattened: false,
684                },
685                DataField {
686                    name: Text::from("floaty"),
687                    docs: None,
688                    typing: Type::F64,
689                    optional: false,
690                    flattened: false,
691                },
692            ];
693
694            let data_fields = vec![
695                DataField {
696                    name: Text::from("text_list"),
697                    docs: None,
698                    typing: Type::List(Type::Text.into()),
699                    optional: false,
700                    flattened: false,
701                },
702                DataField {
703                    name: Text::from("text"),
704                    docs: None,
705                    typing: Type::Text,
706                    optional: false,
707                    flattened: false,
708                },
709                DataField {
710                    name: Text::from("nested"),
711                    docs: None,
712                    typing: Type::Data(NestedTestData::typing()),
713                    optional: false,
714                    flattened: false,
715                },
716                DataField {
717                    name: Text::from("two_d"),
718                    docs: None,
719                    typing: Type::List(Type::List(Type::Text.into()).into()),
720                    optional: false,
721                    flattened: false,
722                },
723            ];
724
725            let typing = DataType::new(Text::from("Testdata"), None, 1, &blob_fields, &data_fields);
726
727            assert_eq!(Self::FORMAT, *typing.format());
728
729            typing
730        }
731    }
732
733    impl Encodable for TestData {
734        const FORMAT: Format = Format::data(1)
735            .with(i32::FORMAT)
736            .with(f64::FORMAT)
737            .with(Vec::<Text>::FORMAT)
738            .with(Text::FORMAT)
739            .with(NestedTestData::FORMAT)
740            .with(Vec::<Vec<Text>>::FORMAT);
741
742        fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
743            writer.write_data(&self.number)?;
744            writer.write_data(&self.floaty)?;
745            writer.write_data(&self.text_list)?;
746            writer.write_data(&self.text)?;
747            writer.write_data(&self.nested)?;
748            writer.write_data(&self.two_d)?;
749            Ok(())
750        }
751    }
752
753    impl Decodable for TestData {
754        fn decode(
755            &mut self,
756            reader: &mut (impl ReadsDecodable + ?Sized),
757            header: Option<DataHeader>,
758        ) -> Result<(), CodecError> {
759            let _ = Self::ensure_header(header, &[1])?;
760
761            reader.read_data_into(&mut self.number)?;
762            reader.read_data_into(&mut self.floaty)?;
763            reader.read_data_into(&mut self.text_list)?;
764            reader.read_data_into(&mut self.text)?;
765            reader.read_data_into(&mut self.nested)?;
766            reader.read_data_into(&mut self.two_d)?;
767
768            Ok(())
769        }
770    }
771
772    /// Simple data structure intended for nesting
773    /// inside of a [`TestData`].
774    #[derive(Clone, Debug, Default, PartialEq)]
775    pub struct NestedTestData {
776        pub boolean: bool,
777    }
778
779    impl NestedTestData {
780        pub fn typing() -> DataType {
781            let blob_fields = vec![DataField {
782                name: Text::from("boolean"),
783                docs: None,
784                typing: Type::Bool,
785                optional: false,
786                flattened: false,
787            }];
788
789            let data_fields = vec![];
790
791            let typing = DataType::new(
792                Text::from("NestedTestdata"),
793                None,
794                2,
795                &blob_fields,
796                &data_fields,
797            );
798
799            assert_eq!(Self::FORMAT, *typing.format());
800
801            typing
802        }
803    }
804
805    impl Encodable for NestedTestData {
806        const FORMAT: Format = Format::data(2).with(bool::FORMAT);
807
808        fn encode(&self, writer: &mut (impl WritesEncodable + ?Sized)) -> Result<(), CodecError> {
809            writer.write_data(&self.boolean)?;
810            Ok(())
811        }
812    }
813
814    impl Decodable for NestedTestData {
815        fn decode(
816            &mut self,
817            reader: &mut (impl ReadsDecodable + ?Sized),
818            header: Option<DataHeader>,
819        ) -> Result<(), CodecError> {
820            let _ = Self::ensure_header(header, &[2])?;
821
822            reader.read_data_into(&mut self.boolean)?;
823
824            Ok(())
825        }
826    }
827
828    #[test]
829    pub fn data_type_codec() {
830        let data_type = TestData::typing();
831
832        let mut encoded_data_type = vec![];
833        encoded_data_type.write_data(&data_type).unwrap();
834        let decoded_data_type = encoded_data_type.as_slice().read_data().unwrap();
835
836        assert_eq!(data_type, decoded_data_type);
837    }
838
839    #[test]
840    fn codes_unstructured_optionals() {
841        let option: Option<u32> = Some(1337u32);
842        let mut data = vec![];
843        data.write_data(&option).expect("encoded");
844        println!("encoded");
845        let decoded_option = data.as_slice().read_data().expect("decoded");
846        assert_eq!(option, decoded_option);
847
848        // Do None values decode as None?
849        let option: Option<u32> = None;
850        let mut data = vec![];
851        data.write_data(&option).expect("encoded");
852        let decoded_option = data.as_slice().read_data().expect("decoded");
853        assert_eq!(option, decoded_option);
854
855        // Do default values decode as None?
856        let option: Option<u32> = Some(0);
857        let mut data = vec![];
858        data.write_data(&option).expect("encoded");
859        let decoded_option: Option<u32> = data.as_slice().read_data().expect("decoded");
860        assert_eq!(None, decoded_option);
861    }
862
863    #[test]
864    fn codes_structured_optionals() {
865        let option: Option<Text> = Some("Hello, World!".into());
866        let mut data = vec![];
867        data.write_data(&option).expect("encoded");
868        println!("encoded");
869        let decoded_option = data.as_slice().read_data().expect("decoded");
870        assert_eq!(option, decoded_option);
871
872        // Do None values decode as None?
873        let option: Option<Text> = None;
874        let mut data = vec![];
875        data.write_data(&option).expect("encoded");
876        let decoded_option = data.as_slice().read_data().expect("decoded");
877        assert_eq!(option, decoded_option);
878
879        // Do default values decode as None?
880        let option: Option<Text> = Some("".into());
881        let mut data = vec![];
882        data.write_data(&option).expect("encoded");
883        let decoded_option: Option<Text> = data.as_slice().read_data().expect("decoded");
884        assert_eq!(None, decoded_option);
885    }
886}