diff --git a/projects/vos-types/Cargo.toml b/projects/vos-types/Cargo.toml index 64c7f3d..b8e4340 100644 --- a/projects/vos-types/Cargo.toml +++ b/projects/vos-types/Cargo.toml @@ -24,4 +24,6 @@ edition = "2021" #peginator = "0.3.0" [features] -default = [] +default = ["alloc"] +alloc = [] +std = [] \ No newline at end of file diff --git a/projects/vos-types/src/decode/mod.rs b/projects/vos-types/src/decode/mod.rs index 8b13789..acd785b 100644 --- a/projects/vos-types/src/decode/mod.rs +++ b/projects/vos-types/src/decode/mod.rs @@ -1 +1,7 @@ - +/// Trait governing how types are decoded. +pub trait Decode<'de>: Sized { + /// Decode the given input. + fn decode(decoder: D) -> Result + where + D: Decoder<'de>; +} diff --git a/projects/vos-types/src/decoder/mod.rs b/projects/vos-types/src/decoder/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/projects/vos-types/src/encode/mod.rs b/projects/vos-types/src/encode/mod.rs index 02c9d8f..8e0bbb4 100644 --- a/projects/vos-types/src/encode/mod.rs +++ b/projects/vos-types/src/encode/mod.rs @@ -1,7 +1,5 @@ use crate::encoder::Encoder; -pub trait EncodeError {} - /// Trait governing how types are encoded. pub trait Encode { /// Encode the given output. diff --git a/projects/vos-types/src/encoder/mod.rs b/projects/vos-types/src/encoder/mod.rs new file mode 100644 index 0000000..5f14d73 --- /dev/null +++ b/projects/vos-types/src/encoder/mod.rs @@ -0,0 +1,1047 @@ +use crate::{error::Report, except::Except}; +use core::fmt::Formatter; + +/// Trait governing how the encoder works. +#[allow(unused_variables)] +pub trait Encoder: Sized { + /// The type returned by the encoder. For [Encode] implementations ensures + /// that they are used correctly, since only functions returned by the + /// [Encoder] is capable of returning this value. + type Ok; + /// The error raised by an encoder. + type Error: Report; + /// Encoder returned when encoding an optional value which is present. + type Some: Encoder; + /// A simple pack that packs a sequence of elements. + type Pack: SequenceEncoder; + /// The type of a sequence encoder. + type List: SequenceEncoder; + /// The type of a tuple encoder. + type Tuple: SequenceEncoder; + /// The type of a map encoder. + type Dict: PairsEncoder; + /// Encoder that can encode a struct. + type Class: PairsEncoder; + /// Encoder for a struct variant. + type Union: VariantEncoder; + + /// An expectation error. Every other implementation defers to this to + /// report that something unexpected happened. + fn expecting(&self, f: &mut Formatter<'_>) -> core::fmt::Result; + + /// Encode a unit or something that is completely empty. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct EmptyStruct; + /// + /// impl Encode for EmptyStruct + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_unit() + /// } + /// } + /// ``` + #[inline] + fn encode_unit(self) -> Result { + Err(Self::Error::message(Except::Boolean)) + } + + /// Encode a boolean value. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: bool, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_bool(self.data) + /// } + /// } + /// ``` + + #[inline] + fn encode_bool(self, value: bool) -> Result { + Err(Self::Error::message(Except::Boolean)) + } + + /// Encode a character. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: char, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_char(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_char(self, _: char) -> Result { + Err(Self::Error::message(Except::Character)) + } + + /// Encode a 8-bit unsigned integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: u8, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_u8(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_u8(self, _: u8) -> Result { + Err(Self::Error::message(Except::Boolean)) + } + + /// Encode a 16-bit unsigned integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: u16, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_u16(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_u16(self, _: u16) -> Result { + Err(Self::Error::message(Except::Boolean)) + } + + /// Encode a 32-bit unsigned integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: u32, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_u32(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_u32(self, _: u32) -> Result { + Err(Self::Error::message(Except::Boolean)) + } + + /// Encode a 64-bit unsigned integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: u64, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_u64(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_u64(self, _: u64) -> Result { + Err(Self::Error::message(Except::Boolean)) + } + + /// Encode a 128-bit unsigned integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: u128, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_u128(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_u128(self, _: u128) -> Result { + Err(Self::Error::message(Except::Boolean)) + } + + /// Encode a 8-bit signed integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: i8, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_i8(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_i8(self, _: i8) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Signed8, &ExpectingWrapper::new(self)))) + } + + /// Encode a 16-bit signed integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: i16, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_i16(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_i16(self, _: i16) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Signed16, &ExpectingWrapper::new(self)))) + } + + /// Encode a 32-bit signed integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: i32, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_i32(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_i32(self, _: i32) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Signed32, &ExpectingWrapper::new(self)))) + } + + /// Encode a 64-bit signed integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: i64, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_i64(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_i64(self, _: i64) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Signed64, &ExpectingWrapper::new(self)))) + } + + /// Encode a 128-bit signed integer. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: i128, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_i128(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_i128(self, _: i128) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Signed128, &ExpectingWrapper::new(self)))) + } + + /// Encode Rusts [`usize`]. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: usize, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_usize(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_usize(self, _: usize) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Usize, &ExpectingWrapper::new(self)))) + } + + /// Encode Rusts [`isize`]. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: isize, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_isize(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_isize(self, _: isize) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Isize, &ExpectingWrapper::new(self)))) + } + + /// Encode a 32-bit floating point value. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: f32, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_f32(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_f32(self, _: f32) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Float32, &ExpectingWrapper::new(self)))) + } + + /// Encode a 64-bit floating point value. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: f64, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_f64(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_f64(self, _: f64) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Float64, &ExpectingWrapper::new(self)))) + } + + /// Encode fixed-length array. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: [u8; 364], + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_array(self.data) + /// } + /// } + /// ``` + #[inline] + fn encode_array(self, _: [u8; N]) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Array, &ExpectingWrapper::new(self)))) + } + + /// Encode a sequence of bytes. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: Vec, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_bytes(self.data.as_slice()) + /// } + /// } + /// ``` + #[inline] + fn encode_bytes(self, _: &[u8]) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Bytes, &ExpectingWrapper::new(self)))) + } + + /// Encode the given slices of bytes in sequence, with one following another + /// as a single contiguous byte array. + /// + /// This can be useful to avoid allocations when a caller doesn't have + /// access to a single byte sequence like in + /// [VecDeque][std::collections::VecDeque]. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: VecDeque, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// let (first, second) = self.data.as_slices(); + /// encoder.encode_bytes_vectored(&[first, second]) + /// } + /// } + /// ``` + #[inline] + fn encode_bytes_vectored(self, _: &[&[u8]]) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Bytes, &ExpectingWrapper::new(self)))) + } + + /// Encode a string. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: String, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// encoder.encode_string(self.data.as_str()) + /// } + /// } + /// ``` + #[inline] + fn encode_string(self, _: &str) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::String, &ExpectingWrapper::new(self)))) + } + + /// Encode an optional value that is present. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: Option, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// match &self.data { + /// Some(data) => encoder.encode_some().and_then(|e| Encode::::encode(data, e)), + /// None => encoder.encode_none(), + /// } + /// } + /// } + /// ``` + #[inline] + fn encode_some(self) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Option, &ExpectingWrapper::new(self)))) + } + + /// Encode an optional value that is absent. + /// + /// # Examples + /// + /// ``` + /// use musli::{Encode, Encoder, Mode}; + /// + /// struct MyType { + /// data: Option, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// match &self.data { + /// Some(data) => encoder.encode_some().and_then(|e| Encode::::encode(data, e)), + /// None => encoder.encode_none(), + /// } + /// } + /// } + /// ``` + #[inline] + fn encode_none(self) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Option, &ExpectingWrapper::new(self)))) + } + + /// Construct a pack that can encode more than one element at a time. + /// + /// This hints to the format that it should attempt to encode all of the + /// elements in the packed sequence as compact as possible and that + /// subsequent unpackers will know the exact length of the element being + /// unpacked. + /// + /// # Examples + /// + /// ``` + /// use musli::{ + /// en::{Encode, Encoder, SequenceEncoder}, + /// mode::Mode, + /// }; + /// + /// struct PackedStruct { + /// field: u32, + /// data: [u8; 364], + /// } + /// + /// impl Encode for PackedStruct + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// let mut pack = encoder.encode_pack()?; + /// pack.next()?.encode_u32(self.field)?; + /// pack.next()?.encode_array(self.data)?; + /// pack.end() + /// } + /// } + /// ``` + #[inline] + fn encode_pack(self) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Pack, &ExpectingWrapper::new(self)))) + } + + /// Encode a sequence with a known length `len`. + /// + /// A sequence encodes one element following another and must in some way + /// encode the length of the sequence in the underlying format. It is + /// decoded with [Decoder::decode_sequence]. + /// + /// [Decoder::decode_sequence]: crate::de::Decoder::decode_sequence + /// + /// # Examples + /// + /// ``` + /// use musli::{ + /// en::{Encode, Encoder, SequenceEncoder}, + /// mode::Mode, + /// }; + /// + /// struct MyType { + /// data: Vec, + /// } + /// + /// impl Encode for MyType + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// let mut seq = encoder.encode_sequence(self.data.len())?; + /// + /// for element in &self.data { + /// seq.push::(element)?; + /// } + /// + /// seq.end() + /// } + /// } + /// ``` + #[inline] + fn encode_sequence(self, #[allow(unused)] len: usize) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Sequence, &ExpectingWrapper::new(self)))) + } + + /// Encode a tuple with a known length `len`. + /// + /// This is almost identical to [Encoder::encode_sequence] except that we + /// know that we are encoding a fixed-length container of length `len`, and + /// assuming the size of that container doesn't change in size it can be + /// decoded using [Decoder::decode_tuple] again without the underlying + /// format having to encode the size of the container. + /// + /// [Decoder::decode_tuple]: crate::de::Decoder::decode_tuple + /// + /// # Examples + /// + /// ``` + /// use musli::{ + /// en::{Encode, Encoder, SequenceEncoder}, + /// mode::Mode, + /// }; + /// + /// struct PackedTuple(u32, [u8; 364]); + /// + /// impl Encode for PackedTuple + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// let mut tuple = encoder.encode_tuple(2)?; + /// tuple.next()?.encode_u32(self.0)?; + /// tuple.next()?.encode_array(self.1)?; + /// tuple.end() + /// } + /// } + /// ``` + #[inline] + fn encode_tuple(self, #[allow(unused)] len: usize) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Tuple, &ExpectingWrapper::new(self)))) + } + + /// Encode a map with a known length `len`. + #[inline] + fn encode_map(self, #[allow(unused)] len: usize) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Map, &ExpectingWrapper::new(self)))) + } + + /// Encode a struct. + /// + /// # Examples + /// + /// ``` + /// use musli::{ + /// en::{Encode, Encoder, PairEncoder, PairsEncoder}, + /// mode::Mode, + /// }; + /// + /// struct Struct { + /// name: String, + /// age: u32, + /// } + /// + /// impl Encode for Struct + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// let mut st = encoder.encode_struct(2)?; + /// st.insert::("name", &self.name)?; + /// st.insert::("age", self.age)?; + /// st.end() + /// } + /// } + /// ``` + #[inline] + fn encode_struct(self, _: usize) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Struct, &ExpectingWrapper::new(self)))) + } + + /// Encode an struct enum variant. + /// + /// # Examples + /// + /// ``` + /// use musli::{ + /// en::{Encode, Encoder, PairsEncoder, VariantEncoder}, + /// mode::Mode, + /// }; + /// + /// enum Enum { + /// UnitVariant, + /// TupleVariant(String), + /// Variant { data: String, age: u32 }, + /// } + /// + /// impl Encode for Enum + /// where + /// M: Mode, + /// { + /// fn encode(&self, encoder: E) -> Result + /// where + /// E: Encoder, + /// { + /// let mut variant = encoder.encode_variant()?; + /// + /// match self { + /// Enum::UnitVariant => variant.insert::("variant1", ()), + /// Enum::TupleVariant(data) => variant.insert::("variant2", data), + /// Enum::Variant { data, age } => { + /// variant.tag()?.encode_string("variant3")?; + /// + /// let mut st = variant.variant()?.encode_struct(2)?; + /// st.insert::("data", data)?; + /// st.insert::("age", age)?; + /// st.end()?; + /// + /// variant.end() + /// } + /// } + /// } + /// } + /// ``` + #[inline] + fn encode_variant(self) -> Result { + Err(Self::Error::message(expecting::invalid_type(&expecting::Variant, &ExpectingWrapper::new(self)))) + } +} + +/// Trait governing how to encode a sequence. +pub trait SequenceEncoder { + /// Result type of the encoder. + type Ok; + /// The error raised by a sequence encoder. + type Error: Report; + + /// The encoder returned when advancing the sequence encoder. + type Encoder<'this>: Encoder + where + Self: 'this; + + /// Prepare encoding of the next element. + #[must_use = "encoders must be consumed"] + fn next(&mut self) -> Result, Self::Error>; + + /// Push an element into the sequence. + #[inline] + fn push(&mut self, value: T) -> Result<(), Self::Error> + where + T: Encode, + { + let encoder = self.next()?; + value.encode(encoder)?; + Ok(()) + } + + /// End the sequence. + fn end(self) -> Result; +} + +/// Encoder for a sequence of pairs. +pub trait PairsEncoder { + /// Result type of the encoder. + type Ok; + /// The error raised by a map encoder. + type Error: Report; + /// Encode the next pair. + type Encoder<'this>: PairEncoder + where + Self: 'this; + + /// Insert a pair immediately. + #[inline] + fn insert(&mut self, first: F, second: S) -> Result<(), Self::Error> + where + Self: Sized, + F: Encode, + S: Encode, + { + self.next()?.insert(first, second)?; + Ok(()) + } + + /// Encode the next pair. + fn next(&mut self) -> Result, Self::Error>; + + /// Finish encoding pairs. + fn end(self) -> Result; +} + +/// Trait governing how to encode a sequence of pairs. +pub trait PairEncoder { + /// Result type of the encoder. + type Ok; + /// The error raised by a map encoder. + type Error: Report; + + /// The encoder returned when advancing the map encoder to encode the key. + type First<'this>: Encoder + where + Self: 'this; + + /// The encoder returned when advancing the map encoder to encode the value. + type Second<'this>: Encoder + where + Self: 'this; + + /// Insert the pair immediately. + #[inline] + fn insert(mut self, first: F, second: S) -> Result + where + Self: Sized, + M: Mode, + F: Encode, + S: Encode, + { + self.first().and_then(|e| first.encode(e))?; + self.second().and_then(|e| second.encode(e))?; + self.end() + } + + /// Return the encoder for the first element in the pair. + #[must_use = "encoders must be consumed"] + fn first(&mut self) -> Result, Self::Error>; + + /// Return encoder for the second element in the pair. + #[must_use = "encoders must be consumed"] + fn second(&mut self) -> Result, Self::Error>; + + /// Stop encoding this pair. + fn end(self) -> Result; +} + +/// Trait governing how to encode a variant. +pub trait VariantEncoder { + /// Result type of the encoder. + type Ok; + /// The error raised by a map encoder. + type Error: Report; + + /// The encoder returned when advancing the map encoder to encode the key. + type Tag<'this>: Encoder + where + Self: 'this; + + /// The encoder returned when advancing the map encoder to encode the value. + type Variant<'this>: Encoder + where + Self: 'this; + + /// Insert the variant immediately. + #[inline] + fn insert(mut self, first: F, second: S) -> Result + where + Self: Sized, + M: Mode, + F: Encode, + S: Encode, + { + self.tag().and_then(|e| first.encode(e))?; + self.variant().and_then(|e| second.encode(e))?; + self.end() + } + + /// Return the encoder for the first element in the variant. + #[must_use = "encoders must be consumed"] + fn tag(&mut self) -> Result, Self::Error>; + + /// Return encoder for the second element in the variant. + #[must_use = "encoders must be consumed"] + fn variant(&mut self) -> Result, Self::Error>; + + /// End the variant encoder. + fn end(self) -> Result; +} diff --git a/projects/vos-types/src/error/mod.rs b/projects/vos-types/src/error/mod.rs index e69de29..6fb605f 100644 --- a/projects/vos-types/src/error/mod.rs +++ b/projects/vos-types/src/error/mod.rs @@ -0,0 +1,101 @@ +//! Trait governing what error types associated with the encoding framework must +//! support. +//! +//! The most important component in here is `Error::custom` which allows custom +//! encoding implementations to raise custom errors based on types that +//! implement [Display][core::fmt::Display]. + +#[cfg(feature = "alloc")] +use alloc::string::{String, ToString}; +use core::fmt::{Debug, Display}; + +/// Trait governing errors raised during encodeing or decoding. +pub trait Report: Sized + 'static + Send + Sync + Display + Debug { + /// Construct a custom error. + fn custom(error: T) -> Self + where + T: 'static + Send + Sync + Display + Debug; + + /// Collect an error from something that can be displayed. + /// + /// This is made available to format custom error messages in `no_std` + /// environments. The error message is to be collected by formatting `T`. + fn message(message: T) -> Self + where + T: Display; + + /// Trying to decode an uninhabitable type. + #[inline] + fn uninhabitable(type_name: &'static str) -> Self { + Self::message(format_args!("{type_name}: cannot decode uninhabitable types",)) + } + + /// The value for the given tag could not be collected. + #[inline] + fn expected_tag(type_name: &'static str, tag: T) -> Self + where + T: Debug, + { + Self::message(format_args!("{type_name}: expected tag: {tag:?}")) + } + + /// Encountered an unsupported number tag. + #[inline] + fn invalid_field_tag(type_name: &'static str, tag: T) -> Self + where + T: Debug, + { + Self::message(format_args!("{type_name}: invalid field tag: {tag:?}")) + } + + /// Indicate that a variant wasn't supported by tag. + #[inline] + fn invalid_variant_tag(type_name: &'static str, tag: T) -> Self + where + T: Debug, + { + Self::message(format_args!("{type_name}: invalid variant tag: {tag:?}",)) + } + + /// Missing variant field required to decode. + #[inline] + fn missing_variant_field(type_name: &'static str, tag: T) -> Self + where + T: Debug, + { + Self::message(format_args!("{type_name}: missing variant field: {tag:?}")) + } + + /// Indicate that a variant tag could not be determined. + #[inline] + fn missing_variant_tag(type_name: &'static str) -> Self { + Self::message(format_args!("{type_name}: missing variant tag")) + } + + /// Encountered an unsupported variant field. + #[inline] + fn invalid_variant_field_tag(type_name: &'static str, variant: V, tag: T) -> Self + where + V: Debug, + T: Debug, + { + Self::message(format_args!("{type_name}: invalid variant field tag: variant: {variant:?}, tag: {tag:?}",)) + } +} + +#[cfg(feature = "alloc")] +impl Report for String { + fn custom(message: T) -> Self + where + T: 'static + Send + Sync + Display + Debug, + { + message.to_string() + } + + fn message(message: T) -> Self + where + T: Display, + { + message.to_string() + } +} diff --git a/projects/vos-types/src/except/mod.rs b/projects/vos-types/src/except/mod.rs index 1363b3f..4c729f0 100644 --- a/projects/vos-types/src/except/mod.rs +++ b/projects/vos-types/src/except/mod.rs @@ -14,6 +14,9 @@ pub trait Expecting { } } +#[repr(transparent)] +pub struct ExpectingWrapper(T); + impl Expecting for str { #[inline] fn expecting(&self, f: &mut Formatter<'_>) -> core::fmt::Result { @@ -31,6 +34,7 @@ impl Display for &dyn Expecting { pub enum Except { Boolean, Character, + Unsigned { bits: usize }, } impl Expecting for Except { @@ -38,6 +42,9 @@ impl Expecting for Except { match self { Except::Boolean => f.write_str("boolean"), Except::Character => f.write_str("character"), + Except::Unsigned { bits } => { + write!(f, "u{}", bits) + } } } } diff --git a/projects/vos-types/src/lib.rs b/projects/vos-types/src/lib.rs index 078349f..88f69fb 100644 --- a/projects/vos-types/src/lib.rs +++ b/projects/vos-types/src/lib.rs @@ -1,5 +1,11 @@ #![no_std] -pub mod decode; +#[cfg(feature = "alloc")] +extern crate alloc; + +// pub mod decode; +// pub mod decoder; pub mod encode; +pub mod encoder; +pub mod error; pub mod except;