diff --git a/crates/musli-value/src/en.rs b/crates/musli-value/src/en.rs index 16bd50d49..c9a1a05e4 100644 --- a/crates/musli-value/src/en.rs +++ b/crates/musli-value/src/en.rs @@ -13,7 +13,10 @@ use musli::en::{ }; #[cfg(feature = "alloc")] use musli::hint::{MapHint, SequenceHint, StructHint, TupleHint}; -use musli::Context; +use musli::{Buf, Context}; +use musli_storage::en::StorageEncoder; +use musli_storage::options::Options; +use musli_storage::writer::BufWriter; use crate::value::{Number, Value}; @@ -54,12 +57,12 @@ where } /// Encoder for a single value. -pub struct ValueEncoder<'a, O, C: ?Sized> { +pub struct ValueEncoder<'a, const OPT: Options, O, C: ?Sized> { cx: &'a C, output: O, } -impl<'a, O, C: ?Sized> ValueEncoder<'a, O, C> { +impl<'a, const OPT: Options, O, C: ?Sized> ValueEncoder<'a, OPT, O, C> { #[inline] pub(crate) fn new(cx: &'a C, output: O) -> Self { Self { cx, output } @@ -67,7 +70,7 @@ impl<'a, O, C: ?Sized> ValueEncoder<'a, O, C> { } #[musli::encoder] -impl<'a, O, C> Encoder for ValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> Encoder for ValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -76,27 +79,27 @@ where type Error = C::Error; type Ok = (); type Mode = C::Mode; - type WithContext<'this, U> = ValueEncoder<'this, O, U> where U: 'this + Context; + type WithContext<'this, U> = ValueEncoder<'this, OPT, O, U> where U: 'this + Context; #[cfg(feature = "alloc")] - type EncodeSome = ValueEncoder<'a, SomeValueWriter, C>; + type EncodeSome = ValueEncoder<'a, OPT, SomeValueWriter, C>; #[cfg(feature = "alloc")] - type EncodePack = SequenceValueEncoder<'a, O, C>; + type EncodePack = PackValueEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeSequence = SequenceValueEncoder<'a, O, C>; + type EncodeSequence = SequenceValueEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeTuple = SequenceValueEncoder<'a, O, C>; + type EncodeTuple = SequenceValueEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeMap = MapValueEncoder<'a, O, C>; + type EncodeMap = MapValueEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeMapEntries = MapValueEncoder<'a, O, C>; + type EncodeMapEntries = MapValueEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeStruct = MapValueEncoder<'a, O, C>; + type EncodeStruct = MapValueEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeVariant = VariantValueEncoder<'a, O, C>; + type EncodeVariant = VariantValueEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeTupleVariant = VariantSequenceEncoder<'a, O, C>; + type EncodeTupleVariant = VariantSequenceEncoder<'a, OPT, O, C>; #[cfg(feature = "alloc")] - type EncodeStructVariant = VariantStructEncoder<'a, O, C>; + type EncodeStructVariant = VariantStructEncoder<'a, OPT, O, C>; #[inline] fn cx(&self) -> &C { @@ -293,7 +296,7 @@ where #[cfg(feature = "alloc")] #[inline] fn encode_pack(self) -> Result { - Ok(SequenceValueEncoder::new(self.cx, self.output)) + PackValueEncoder::new(self.cx, self.output) } #[cfg(feature = "alloc")] @@ -356,7 +359,7 @@ where T: ?Sized + Encode, { let mut variant = Value::Unit; - ValueEncoder::new(self.cx, &mut variant).encode(tag)?; + ValueEncoder::::new(self.cx, &mut variant).encode(tag)?; Ok(VariantSequenceEncoder::new( self.cx, @@ -377,7 +380,7 @@ where T: ?Sized + Encode, { let mut variant = Value::Unit; - ValueEncoder::new(self.cx, &mut variant).encode(tag)?; + ValueEncoder::::new(self.cx, &mut variant).encode(tag)?; Ok(VariantStructEncoder::new( self.cx, @@ -388,16 +391,16 @@ where } } -/// A pack encoder. +/// A sequence encoder. #[cfg(feature = "alloc")] -pub struct SequenceValueEncoder<'a, O, C: ?Sized> { +pub struct SequenceValueEncoder<'a, const OPT: Options, O, C: ?Sized> { cx: &'a C, output: O, values: Vec, } #[cfg(feature = "alloc")] -impl<'a, O, C: ?Sized> SequenceValueEncoder<'a, O, C> { +impl<'a, const OPT: Options, O, C: ?Sized> SequenceValueEncoder<'a, OPT, O, C> { #[inline] fn new(cx: &'a C, output: O) -> Self { Self { @@ -409,7 +412,7 @@ impl<'a, O, C: ?Sized> SequenceValueEncoder<'a, O, C> { } #[cfg(feature = "alloc")] -impl<'a, O, C> SequenceEncoder for SequenceValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> SequenceEncoder for SequenceValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -417,7 +420,7 @@ where type Cx = C; type Ok = (); - type EncodeElement<'this> = ValueEncoder<'a, &'this mut Vec, C> + type EncodeElement<'this> = ValueEncoder<'a, OPT, &'this mut Vec, C> where Self: 'this; @@ -433,8 +436,38 @@ where } } +/// A pack encoder. +#[cfg(feature = "alloc")] +pub struct PackValueEncoder<'a, const OPT: Options, O, C> +where + C: ?Sized + Context, +{ + cx: &'a C, + output: O, + writer: BufWriter>, +} + +#[cfg(feature = "alloc")] +impl<'a, const OPT: Options, O, C> PackValueEncoder<'a, OPT, O, C> +where + C: ?Sized + Context, +{ + #[inline] + fn new(cx: &'a C, output: O) -> Result { + let Some(buf) = cx.alloc() else { + return Err(cx.message("Failed to allocate buffer")); + }; + + Ok(Self { + cx, + output, + writer: BufWriter::new(buf), + }) + } +} + #[cfg(feature = "alloc")] -impl<'a, O, C> PackEncoder for SequenceValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> PackEncoder for PackValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -442,23 +475,25 @@ where type Cx = C; type Ok = (); - type EncodePacked<'this> = ValueEncoder<'a, &'this mut Vec, C> + type EncodePacked<'this> = StorageEncoder<'a, &'this mut BufWriter>, OPT, C> where Self: 'this; #[inline] fn encode_packed(&mut self) -> Result, C::Error> { - SequenceEncoder::encode_element(self) + Ok(StorageEncoder::new(self.cx, &mut self.writer)) } #[inline] fn finish_pack(self) -> Result { - SequenceEncoder::finish_sequence(self) + let buf = self.writer.into_inner(); + self.output.write(Value::Bytes(buf.as_slice().into())); + Ok(()) } } #[cfg(feature = "alloc")] -impl<'a, O, C> TupleEncoder for SequenceValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> TupleEncoder for SequenceValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -466,7 +501,7 @@ where type Cx = C; type Ok = (); - type EncodeTupleField<'this> = ValueEncoder<'a, &'this mut Vec, C> + type EncodeTupleField<'this> = ValueEncoder<'a, OPT, &'this mut Vec, C> where Self: 'this; @@ -483,14 +518,14 @@ where /// A pairs encoder. #[cfg(feature = "alloc")] -pub struct MapValueEncoder<'a, O, C: ?Sized> { +pub struct MapValueEncoder<'a, const OPT: Options, O, C: ?Sized> { cx: &'a C, output: O, values: Vec<(Value, Value)>, } #[cfg(feature = "alloc")] -impl<'a, O, C: ?Sized> MapValueEncoder<'a, O, C> { +impl<'a, const OPT: Options, O, C: ?Sized> MapValueEncoder<'a, OPT, O, C> { #[inline] fn new(cx: &'a C, output: O) -> Self { Self { @@ -502,14 +537,14 @@ impl<'a, O, C: ?Sized> MapValueEncoder<'a, O, C> { } #[cfg(feature = "alloc")] -impl<'a, O, C> MapEncoder for MapValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> MapEncoder for MapValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, { type Cx = C; type Ok = (); - type EncodeMapEntry<'this> = PairValueEncoder<'this, C> + type EncodeMapEntry<'this> = PairValueEncoder<'this, OPT, C> where Self: 'this; @@ -526,17 +561,17 @@ where } #[cfg(feature = "alloc")] -impl<'a, O, C> MapEntriesEncoder for MapValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> MapEntriesEncoder for MapValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, { type Cx = C; type Ok = (); - type EncodeMapEntryKey<'this> = ValueEncoder<'a, &'this mut Value, C> + type EncodeMapEntryKey<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; - type EncodeMapEntryValue<'this> = ValueEncoder<'a, &'this mut Value, C> + type EncodeMapEntryValue<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; @@ -568,7 +603,7 @@ where } #[cfg(feature = "alloc")] -impl<'a, O, C> StructEncoder for MapValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> StructEncoder for MapValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -576,7 +611,7 @@ where type Cx = C; type Ok = (); - type EncodeStructField<'this> = PairValueEncoder<'this, C> + type EncodeStructField<'this> = PairValueEncoder<'this, OPT, C> where Self: 'this; @@ -594,14 +629,14 @@ where /// A pairs encoder. #[cfg(feature = "alloc")] -pub struct PairValueEncoder<'a, C: ?Sized> { +pub struct PairValueEncoder<'a, const OPT: Options, C: ?Sized> { cx: &'a C, output: &'a mut Vec<(Value, Value)>, pair: (Value, Value), } #[cfg(feature = "alloc")] -impl<'a, C: ?Sized> PairValueEncoder<'a, C> { +impl<'a, const OPT: Options, C: ?Sized> PairValueEncoder<'a, OPT, C> { #[inline] fn new(cx: &'a C, output: &'a mut Vec<(Value, Value)>) -> Self { Self { @@ -613,16 +648,16 @@ impl<'a, C: ?Sized> PairValueEncoder<'a, C> { } #[cfg(feature = "alloc")] -impl<'a, C> MapEntryEncoder for PairValueEncoder<'a, C> +impl<'a, const OPT: Options, C> MapEntryEncoder for PairValueEncoder<'a, OPT, C> where C: ?Sized + Context, { type Cx = C; type Ok = (); - type EncodeMapKey<'this> = ValueEncoder<'a, &'this mut Value, C> + type EncodeMapKey<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; - type EncodeMapValue<'this> = ValueEncoder<'a, &'this mut Value, C> where Self: 'this; + type EncodeMapValue<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; #[inline] fn encode_map_key(&mut self) -> Result, C::Error> { @@ -642,16 +677,16 @@ where } #[cfg(feature = "alloc")] -impl<'a, C> StructFieldEncoder for PairValueEncoder<'a, C> +impl<'a, const OPT: Options, C> StructFieldEncoder for PairValueEncoder<'a, OPT, C> where C: ?Sized + Context, { type Cx = C; type Ok = (); - type EncodeFieldName<'this> = ValueEncoder<'a, &'this mut Value, C> + type EncodeFieldName<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; - type EncodeFieldValue<'this> = ValueEncoder<'a, &'this mut Value, C> where Self: 'this; + type EncodeFieldValue<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; #[inline] fn encode_field_name(&mut self) -> Result, C::Error> { @@ -672,14 +707,14 @@ where /// A pairs encoder. #[cfg(feature = "alloc")] -pub struct VariantValueEncoder<'a, O, C: ?Sized> { +pub struct VariantValueEncoder<'a, const OPT: Options, O, C: ?Sized> { cx: &'a C, output: O, pair: (Value, Value), } #[cfg(feature = "alloc")] -impl<'a, O, C: ?Sized> VariantValueEncoder<'a, O, C> { +impl<'a, const OPT: Options, O, C: ?Sized> VariantValueEncoder<'a, OPT, O, C> { #[inline] fn new(cx: &'a C, output: O) -> Self { Self { @@ -691,17 +726,17 @@ impl<'a, O, C: ?Sized> VariantValueEncoder<'a, O, C> { } #[cfg(feature = "alloc")] -impl<'a, O, C> VariantEncoder for VariantValueEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> VariantEncoder for VariantValueEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, { type Cx = C; type Ok = (); - type EncodeTag<'this> = ValueEncoder<'a, &'this mut Value, C> + type EncodeTag<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; - type EncodeValue<'this> = ValueEncoder<'a, &'this mut Value, C> + type EncodeValue<'this> = ValueEncoder<'a, OPT, &'this mut Value, C> where Self: 'this; @@ -724,7 +759,7 @@ where /// A variant sequence encoder. #[cfg(feature = "alloc")] -pub struct VariantSequenceEncoder<'a, O, C: ?Sized> { +pub struct VariantSequenceEncoder<'a, const OPT: Options, O, C: ?Sized> { cx: &'a C, output: O, variant: Value, @@ -732,7 +767,7 @@ pub struct VariantSequenceEncoder<'a, O, C: ?Sized> { } #[cfg(feature = "alloc")] -impl<'a, O, C: ?Sized> VariantSequenceEncoder<'a, O, C> { +impl<'a, const OPT: Options, O, C: ?Sized> VariantSequenceEncoder<'a, OPT, O, C> { #[inline] fn new(cx: &'a C, output: O, variant: Value, len: usize) -> Self { Self { @@ -745,7 +780,7 @@ impl<'a, O, C: ?Sized> VariantSequenceEncoder<'a, O, C> { } #[cfg(feature = "alloc")] -impl<'a, O, C> SequenceEncoder for VariantSequenceEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> SequenceEncoder for VariantSequenceEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -753,7 +788,7 @@ where type Cx = C; type Ok = (); - type EncodeElement<'this> = ValueEncoder<'a, &'this mut Vec, C> + type EncodeElement<'this> = ValueEncoder<'a, OPT, &'this mut Vec, C> where Self: 'this; @@ -773,7 +808,7 @@ where } #[cfg(feature = "alloc")] -impl<'a, O, C> TupleEncoder for VariantSequenceEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> TupleEncoder for VariantSequenceEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -781,7 +816,7 @@ where type Cx = C; type Ok = (); - type EncodeTupleField<'this> = ValueEncoder<'a, &'this mut Vec, C> + type EncodeTupleField<'this> = ValueEncoder<'a, OPT, &'this mut Vec, C> where Self: 'this; @@ -798,7 +833,7 @@ where /// A variant struct encoder. #[cfg(feature = "alloc")] -pub struct VariantStructEncoder<'a, O, C: ?Sized> { +pub struct VariantStructEncoder<'a, const OPT: Options, O, C: ?Sized> { cx: &'a C, output: O, variant: Value, @@ -806,7 +841,7 @@ pub struct VariantStructEncoder<'a, O, C: ?Sized> { } #[cfg(feature = "alloc")] -impl<'a, O, C: ?Sized> VariantStructEncoder<'a, O, C> { +impl<'a, const OPT: Options, O, C: ?Sized> VariantStructEncoder<'a, OPT, O, C> { #[inline] fn new(cx: &'a C, output: O, variant: Value, len: usize) -> Self { Self { @@ -819,7 +854,7 @@ impl<'a, O, C: ?Sized> VariantStructEncoder<'a, O, C> { } #[cfg(feature = "alloc")] -impl<'a, O, C> StructEncoder for VariantStructEncoder<'a, O, C> +impl<'a, const OPT: Options, O, C> StructEncoder for VariantStructEncoder<'a, OPT, O, C> where O: ValueOutput, C: ?Sized + Context, @@ -827,7 +862,7 @@ where type Cx = C; type Ok = (); - type EncodeStructField<'this> = PairValueEncoder<'this, C> + type EncodeStructField<'this> = PairValueEncoder<'this, OPT, C> where Self: 'this; diff --git a/crates/musli-value/src/error.rs b/crates/musli-value/src/error.rs index aa8774be8..0eeb691a9 100644 --- a/crates/musli-value/src/error.rs +++ b/crates/musli-value/src/error.rs @@ -127,7 +127,9 @@ impl fmt::Display for ErrorMessage { write!(f, "Expected sequence, but found {hint}") } #[cfg(feature = "alloc")] - ErrorMessage::ExpectedPack(hint) => write!(f, "Expected pack, but found {hint}"), + ErrorMessage::ExpectedPack(hint) => { + write!(f, "Expected pack of bytes, but found {hint}") + } #[cfg(feature = "alloc")] ErrorMessage::ExpectedMap(hint) => write!(f, "Expected map, but found {hint}"), #[cfg(feature = "alloc")] diff --git a/crates/musli-value/src/lib.rs b/crates/musli-value/src/lib.rs index 8567c7abc..836d42d77 100644 --- a/crates/musli-value/src/lib.rs +++ b/crates/musli-value/src/lib.rs @@ -49,7 +49,7 @@ where let mut buf = musli_common::exports::allocator::buffer(); let alloc = musli_common::exports::allocator::new(&mut buf); let cx = musli_common::exports::context::Same::<_, DefaultMode, Error>::new(&alloc); - ValueEncoder::new(&cx, &mut output).encode(value)?; + ValueEncoder::::new(&cx, &mut output).encode(value)?; Ok(output) }