Skip to content

Commit

Permalink
Add Allocator to Decode trait
Browse files Browse the repository at this point in the history
* Allow specifying a custom lifetime and allocator identifier
  • Loading branch information
udoprog committed Jan 2, 2025
1 parent 9486150 commit 5a048e1
Show file tree
Hide file tree
Showing 74 changed files with 937 additions and 442 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ The tradeoffs we will be showcasing to achieve speed here are:
We achieve this through the following methods:

```rust
use musli::alloc::System;
use musli::context::{ErrorMarker as Error, Ignore};
use musli::options::{self, Float, Integer, Width, Options};
use musli::storage::Encoding;
Expand All @@ -372,7 +373,7 @@ where
#[inline]
pub fn decode<'buf, T>(buf: &'buf [u8], alloc: &Slice<'_>) -> Result<T, Error>
where
T: Decode<'buf, Packed>,
T: Decode<'buf, Packed, System>,
{
let cx = Ignore::with_alloc(alloc);
ENCODING.from_slice_with(&cx, buf)
Expand Down
3 changes: 2 additions & 1 deletion asm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ pub mod generic {

#[cfg(feature = "musli")]
pub mod musli {
use musli::alloc::System;
use musli::context::{ErrorMarker as Error, Ignore};
use musli::options::{self, Options};
use musli::storage::Encoding;
Expand Down Expand Up @@ -220,7 +221,7 @@ pub mod musli {
#[inline(always)]
pub fn decode<'buf, T>(buf: &'buf [u8]) -> Result<T, Error>
where
T: Decode<'buf, Packed>,
T: Decode<'buf, Packed, System>,
{
let cx = Ignore::new();
ENCODING.from_slice_with(&cx, buf)
Expand Down
2 changes: 1 addition & 1 deletion crates/musli-core/src/alloc/raw_vec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// A raw buffer allocated through an [`Allocator`].
///
/// [`Allocator`]: super::Allocator
/// [`Allocator`]: crate::Allocator
///
/// ## Examples
///
Expand Down
2 changes: 1 addition & 1 deletion crates/musli-core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::error::Error;
use core::fmt;
use core::str;

use crate::alloc::Allocator;
use crate::Allocator;

/// Provides ergonomic access to the serialization context.
///
Expand Down
1 change: 1 addition & 0 deletions crates/musli-core/src/de/as_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub trait AsDecoder {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>
where
Self: 'this;
Expand Down
10 changes: 8 additions & 2 deletions crates/musli-core/src/de/decode.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::Allocator;

use super::Decoder;

/// Trait governing how types are decoded.
Expand Down Expand Up @@ -37,7 +39,11 @@ use super::Decoder;
/// }
/// }
/// ```
pub trait Decode<'de, M>: Sized {
pub trait Decode<'de, M, A>
where
Self: Sized,
A: Allocator,
{
/// Whether the type is packed. Packed types can be bitwise copied if the
/// representation of the serialization format is identical to the memory
/// layout of the type.
Expand All @@ -53,5 +59,5 @@ pub trait Decode<'de, M>: Sized {
/// Decode the given input.
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M>;
D: Decoder<'de, Mode = M, Allocator = A>;
}
10 changes: 8 additions & 2 deletions crates/musli-core/src/de/decode_bytes.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::Allocator;

use super::Decoder;

/// Trait governing how types are decoded as bytes.
Expand Down Expand Up @@ -40,7 +42,11 @@ use super::Decoder;
/// }
/// }
/// ```
pub trait DecodeBytes<'de, M>: Sized {
pub trait DecodeBytes<'de, M, A>
where
Self: Sized,
A: Allocator,
{
/// Whether the type is packed. Packed types can be bitwise copied if the
/// representation of the serialization format is identical to the memory
/// layout of the type.
Expand All @@ -53,5 +59,5 @@ pub trait DecodeBytes<'de, M>: Sized {
/// Decode the given input as bytes.
fn decode_bytes<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M>;
D: Decoder<'de, Mode = M, Allocator = A>;
}
10 changes: 8 additions & 2 deletions crates/musli-core/src/de/decode_packed.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::Allocator;

use super::Decoder;

/// Trait governing how a type is decoded as a packed value.
Expand Down Expand Up @@ -45,9 +47,13 @@ use super::Decoder;
/// }
/// }
/// ```
pub trait DecodePacked<'de, M>: Sized {
pub trait DecodePacked<'de, M, A>
where
Self: Sized,
A: Allocator,
{
/// Decode the given input as bytes.
fn decode_packed<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M>;
D: Decoder<'de, Mode = M, Allocator = A>;
}
10 changes: 8 additions & 2 deletions crates/musli-core/src/de/decode_trace.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::Allocator;

use super::Decoder;

/// Trait governing how types are decoded specifically for tracing.
Expand All @@ -8,9 +10,13 @@ use super::Decoder;
///
/// [`HashMap<K, V>`]: std::collections::HashMap
/// [`fmt::Display`]: std::fmt::Display
pub trait DecodeTrace<'de, M>: Sized {
pub trait DecodeTrace<'de, M, A>
where
Self: Sized,
A: Allocator,
{
/// Decode the given input.
fn trace_decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M>;
D: Decoder<'de, Mode = M, Allocator = A>;
}
28 changes: 21 additions & 7 deletions crates/musli-core/src/de/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::fmt;

use crate::expecting::{self, Expecting};
use crate::hint::{MapHint, SequenceHint};
use crate::Context;
use crate::{Allocator, Context};

use super::{
utils, AsDecoder, Decode, DecodeSliceBuilder, DecodeUnsized, DecodeUnsizedBytes,
Expand All @@ -24,20 +24,34 @@ pub enum TryFastDecode<T, D> {
#[must_use = "Decoders must be consumed through one of its decode_* methods"]
pub trait Decoder<'de>: Sized {
/// Context associated with the decoder.
type Cx: Context<Error = Self::Error, Mode = Self::Mode>;
type Cx: Context<Error = Self::Error, Mode = Self::Mode, Allocator = Self::Allocator>;
/// Error associated with decoding.
type Error;
/// Mode associated with decoding.
type Mode: 'static;
/// The allocator associated with the decoder.
type Allocator: Allocator;
/// [`Decoder`] with a different context returned by
/// [`Decoder::with_context`]
type WithContext<U>: Decoder<'de, Cx = U, Error = U::Error, Mode = U::Mode>
type WithContext<U>: Decoder<
'de,
Cx = U,
Error = U::Error,
Mode = U::Mode,
Allocator = U::Allocator,
>
where
U: Context;
/// Decoder returned by [`Decoder::decode_buffer`].
type DecodeBuffer: AsDecoder<Cx = Self::Cx>;
/// Decoder returned by [`Decoder::decode_option`].
type DecodeSome: Decoder<'de, Cx = Self::Cx, Error = Self::Error, Mode = Self::Mode>;
type DecodeSome: Decoder<
'de,
Cx = Self::Cx,
Error = Self::Error,
Mode = Self::Mode,
Allocator = Self::Allocator,
>;
/// Decoder used by [`Decoder::decode_pack`].
type DecodePack: SequenceDecoder<'de, Cx = Self::Cx>;
/// Decoder returned by [`Decoder::decode_sequence`].
Expand Down Expand Up @@ -121,7 +135,7 @@ pub trait Decoder<'de>: Sized {
#[inline]
fn try_fast_decode<T>(self) -> Result<TryFastDecode<T, Self>, Self::Error>
where
T: Decode<'de, Self::Mode>,
T: Decode<'de, Self::Mode, Self::Allocator>,
{
Ok(TryFastDecode::Unsupported(self))
}
Expand All @@ -132,7 +146,7 @@ pub trait Decoder<'de>: Sized {
#[inline]
fn decode<T>(self) -> Result<T, Self::Error>
where
T: Decode<'de, Self::Mode>,
T: Decode<'de, Self::Mode, Self::Allocator>,
{
match self.try_fast_decode::<T>()? {
TryFastDecode::Ok(value) => Ok(value),
Expand Down Expand Up @@ -1234,7 +1248,7 @@ pub trait Decoder<'de>: Sized {
fn decode_slice<V, T>(self) -> Result<V, <Self::Cx as Context>::Error>
where
V: DecodeSliceBuilder<T>,
T: Decode<'de, Self::Mode>,
T: Decode<'de, Self::Mode, Self::Allocator>,
{
utils::default_decode_slice(self)
}
Expand Down
2 changes: 2 additions & 0 deletions crates/musli-core/src/de/entries_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub trait EntriesDecoder<'de> {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>
where
Self: 'this;
Expand All @@ -28,6 +29,7 @@ pub trait EntriesDecoder<'de> {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>
where
Self: 'this;
Expand Down
2 changes: 2 additions & 0 deletions crates/musli-core/src/de/entry_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub trait EntryDecoder<'de> {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>
where
Self: 'this;
Expand All @@ -21,6 +22,7 @@ pub trait EntryDecoder<'de> {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>;

/// Access the context associated with the decoder.
Expand Down
4 changes: 2 additions & 2 deletions crates/musli-core/src/de/map_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ pub trait MapDecoder<'de> {
/// Decode the next map entry as a tuple.
fn entry<K, V>(&mut self) -> Result<Option<(K, V)>, <Self::Cx as Context>::Error>
where
K: Decode<'de, <Self::Cx as Context>::Mode>,
V: Decode<'de, <Self::Cx as Context>::Mode>,
K: Decode<'de, <Self::Cx as Context>::Mode, <Self::Cx as Context>::Allocator>,
V: Decode<'de, <Self::Cx as Context>::Mode, <Self::Cx as Context>::Allocator>,
{
let Some(mut entry) = self.decode_entry()? else {
return Ok(None);
Expand Down
18 changes: 15 additions & 3 deletions crates/musli-core/src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,24 @@ pub use self::variant_decoder::VariantDecoder;
mod visitor;
pub use self::visitor::Visitor;

use crate::Allocator;

/// Decode to an owned value.
///
/// This is a simpler bound to use than `for<'de> Decode<'de, M>`.
pub trait DecodeOwned<M>: for<'de> Decode<'de, M> {}

impl<M, D> DecodeOwned<M> for D where D: for<'de> Decode<'de, M> {}
pub trait DecodeOwned<M, A>
where
Self: for<'de> Decode<'de, M, A>,
A: Allocator,
{
}

impl<M, D, A> DecodeOwned<M, A> for D
where
D: for<'de> Decode<'de, M, A>,
A: Allocator,
{
}

#[doc(hidden)]
pub mod utils;
5 changes: 3 additions & 2 deletions crates/musli-core/src/de/sequence_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub trait SequenceDecoder<'de> {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>
where
Self: 'this;
Expand Down Expand Up @@ -42,7 +43,7 @@ pub trait SequenceDecoder<'de> {
#[inline]
fn next<T>(&mut self) -> Result<T, <Self::Cx as Context>::Error>
where
T: Decode<'de, <Self::Cx as Context>::Mode>,
T: Decode<'de, <Self::Cx as Context>::Mode, <Self::Cx as Context>::Allocator>,
{
self.decode_next()?.decode()
}
Expand All @@ -51,7 +52,7 @@ pub trait SequenceDecoder<'de> {
#[inline]
fn try_next<T>(&mut self) -> Result<Option<T>, <Self::Cx as Context>::Error>
where
T: Decode<'de, <Self::Cx as Context>::Mode>,
T: Decode<'de, <Self::Cx as Context>::Mode, <Self::Cx as Context>::Allocator>,
{
let Some(decoder) = self.try_decode_next()? else {
return Ok(None);
Expand Down
4 changes: 3 additions & 1 deletion crates/musli-core/src/de/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::Context;

use super::{Decode, DecodeSliceBuilder, Decoder, SequenceDecoder};

/// Default implementation to decode a slice.
Expand All @@ -6,7 +8,7 @@ pub fn default_decode_slice<'de, D, V, T>(decoder: D) -> Result<V, D::Error>
where
D: Decoder<'de>,
V: DecodeSliceBuilder<T>,
T: Decode<'de, D::Mode>,
T: Decode<'de, D::Mode, <D::Cx as Context>::Allocator>,
{
use crate::Context;

Expand Down
2 changes: 2 additions & 0 deletions crates/musli-core/src/de/variant_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub trait VariantDecoder<'de> {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>
where
Self: 'this;
Expand All @@ -21,6 +22,7 @@ pub trait VariantDecoder<'de> {
Cx = Self::Cx,
Error = <Self::Cx as Context>::Error,
Mode = <Self::Cx as Context>::Mode,
Allocator = <Self::Cx as Context>::Allocator,
>
where
Self: 'this;
Expand Down
4 changes: 2 additions & 2 deletions crates/musli-core/src/de/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ where
#[inline]
fn visit_option<D>(self, cx: C, _: Option<D>) -> Result<Self::Ok, C::Error>
where
D: Decoder<'de, Cx = C, Error = C::Error, Mode = C::Mode>,
D: Decoder<'de, Cx = C, Error = C::Error, Mode = C::Mode, Allocator = C::Allocator>,
{
Err(cx.message(expecting::unsupported_type(
&expecting::Option,
Expand Down Expand Up @@ -256,7 +256,7 @@ where
#[inline]
fn visit_unknown<D>(self, decoder: D) -> Result<Self::Ok, D::Error>
where
D: Decoder<'de, Cx = C, Error = C::Error, Mode = C::Mode>,
D: Decoder<'de, Cx = C, Error = C::Error, Mode = C::Mode, Allocator = C::Allocator>,
{
Err(decoder.cx().message(expecting::unsupported_type(
&expecting::Any,
Expand Down
Loading

0 comments on commit 5a048e1

Please sign in to comment.