Skip to main content

Recording

Struct Recording 

Source
pub struct Recording(/* private fields */);
Expand description

A recorded value that can be replayed into a sink later.

Some types cannot deserialize a value when it arrives because they first need to see data that comes later. An example are internally tagged enums where the tag can come after the fields of the variant. Such types record values and replay them once they know where they should go.

A recording captures the events of a value together with their input ranges (see State::input_range), the data attached to them (see State::event) and the values of all replayable extensions in the state (see State::set_replayable) at the time of each event. When replaying, these values are restored for every event. This means that information such as source locations or paths remains correct for replayed values. Map keys are also replayed as map keys and atoms are recorded as they are (lexical atoms remain lexical), so format specific handling (like integer keys in JSON) continues to work.

use deser::de::{DeserializeDriver, Recording};
use deser::{Deserialize, Event, State};

let mut recording = Recording::new();
{
    let mut driver =
        DeserializeDriver::from_fn(|state| recording.recorder(state));
    driver.emit(Event::seq_start()).unwrap();
    driver.emit(1u64).unwrap();
    driver.emit(2u64).unwrap();
    driver.emit(Event::SeqEnd).unwrap();
}

// replayed into the sink of a value, here with a new state
let mut out = None::<Vec<u32>>;
let mut state = State::new();
let sink = Vec::<u32>::deserialize_into(&mut out, &mut state);
recording.replay(sink, &mut state).unwrap();
assert_eq!(out, Some(vec![1, 2]));

Recordings are detached from the data they were recorded from: borrowed atoms are recorded as owned (see Atom::to_static). This means that types which only accept borrowed data (like &str) cannot be deserialized from a replayed recording. Types which can hold owned data (like Cow<str>) can. (The buffering of the derive, for instance for internally tagged enums, keeps borrowed data borrowed.)

§Raw Values

Recordings implement Deserialize and Serialize. This makes them usable as raw values that capture any value without interpreting it, for instance for the content of #[deser(other)] enum variants. When serialized the recorded events are emitted again, including the event data attached to them (see State::event). This means that format specific information carried as event data (for instance CBOR tags) survives a round trip through a recording.

The lengths of maps and sequences are known once they are recorded. If the format did not know them (like JSON, which does not say how many elements an array has before its end) they are filled in, so they are available to serializers (see ContainerShape::len).

use deser::de::Recording;
use deser::Deserialize;

#[derive(Deserialize)]
pub struct Envelope {
    kind: String,
    payload: Recording,
}

Implementations§

Source§

impl Recording

Source

pub fn new() -> Recording

Creates an empty recording.

Source

pub fn recorder<'de>(&mut self, state: &mut State) -> SinkHandle<'_, 'de>

Returns a sink that records a value into this recording.

A previously recorded value is discarded.

Source

pub fn capture<'a, 'de, F>(then: F, state: &mut State) -> SinkHandle<'a, 'de>
where F: FnOnce(Recording, &mut State) -> Result<(), Error> + Send + 'a,

Returns a sink that records a value and passes the recording to a callback once the value is complete.

This is useful for types which need to see the complete value before they can deserialize it, like untagged enums which try to replay the value into different types.

use deser::State;
use deser::de::{Deserialize, Recording, SinkHandle};

/// Deserializes either as number or as string.
#[derive(Debug, PartialEq)]
enum NumberOrString {
    Number(u64),
    String(String),
}

impl<'de> Deserialize<'de> for NumberOrString {
    fn deserialize_into<'out>(
        out: &'out mut Option<Self>,
        state: &mut State,
    ) -> SinkHandle<'out, 'de> {
        Recording::capture(move |recording, state| {
            let mut number = None;
            let sink = u64::deserialize_into(&mut number, state);
            if recording.replay(sink, state).is_ok() {
                *out = number.map(NumberOrString::Number);
            } else {
                let mut string = None;
                let sink = String::deserialize_into(&mut string, state);
                recording.replay(sink, state)?;
                *out = string.map(NumberOrString::String);
            }
            Ok(())
        }, state)
    }
}

let values: Vec<NumberOrString> = {
    let mut out = None;
    {
        let mut driver = deser::de::DeserializeDriver::new(&mut out);
        for event in [
            deser::Event::seq_start(),
            42u64.into(),
            "x".into(),
            deser::Event::SeqEnd,
        ] {
            driver.emit(event).unwrap();
        }
    }
    out.unwrap()
};
assert_eq!(
    values,
    [NumberOrString::Number(42), NumberOrString::String("x".into())]
);
Source

pub fn is_empty(&self) -> bool

Returns true if nothing was recorded.

Source

pub fn events(&self) -> impl Iterator<Item = &Event<'static>>

Returns the recorded events.

Source

pub fn as_str(&self) -> Option<&str>

Returns the value if the recording is a single string.

This is useful to look at recorded map keys.

Source

pub fn replay<'de>( &self, sink: SinkHandle<'_, 'de>, state: &mut State, ) -> Result<(), Error>

Replays the recorded value into a sink.

The state is the state of the ongoing deserialization. The replayable extensions in it are restored to their current values after replaying.

Trait Implementations§

Source§

impl Clone for Recording

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Recording

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Recording

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Recording

Source§

fn deserialize_into<'out>( out: &'out mut Option<Self>, state: &mut State, ) -> SinkHandle<'out, 'de>

Creates a sink that deserializes the value into the given slot. Read more
Source§

fn expecting() -> Cow<'static, str>

Returns what the value expects, for error messages. Read more
Source§

fn deserialize_atom( slot: &mut Slot<T, Self>, atom: Atom<'_>, state: &mut State, ) -> Result<(), Error>

Deserializes an atom into the slot. Read more
Source§

fn deserialize_borrowed_atom( slot: &mut Slot<T, Self>, atom: Atom<'de>, state: &mut State, ) -> Result<(), Error>

Deserializes an atom that borrows from the data being deserialized into the slot. Read more
Source§

fn describe_type(d: &mut dyn Describe)

Describes the Rust shape of the type. Read more
Source§

fn initial_value() -> Option<T>

Provides the value of a missing struct field. Read more
Source§

fn deserialize_update<'out>( value: &'out mut T, state: &mut State, ) -> SinkHandle<'out, 'de>

Creates a sink that updates an existing value. Read more
Source§

impl PartialEq for Recording

Recordings are compared by their events.

The event data and the replayable extensions captured with the events are not compared.

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for Recording

Source§

fn serialize<'a>(value: &'a Self, state: &mut State) -> Result<Emit<'a>, Error>

Serializes the value.
Source§

fn container_shape(value: &Self) -> ContainerShape

Returns the shape of the value if it’s a map or sequence. Read more
Source§

fn is_optional(value: &Self) -> bool

Checks if the value represents an optional value. Read more
Source§

fn finish(value: &T, state: &mut State) -> Result<(), Error>

Invoked after the serialization finished. Read more
Source§

fn describe(value: &T, d: &mut dyn Describe)

Describes the Rust shape of the value. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.