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
impl Recording
Sourcepub fn recorder<'de>(&mut self, state: &mut State) -> SinkHandle<'_, 'de>
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.
Sourcepub fn capture<'a, 'de, F>(then: F, state: &mut State) -> SinkHandle<'a, 'de>
pub fn capture<'a, 'de, F>(then: F, state: &mut State) -> SinkHandle<'a, 'de>
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())]
);Trait Implementations§
Source§impl<'de> Deserialize<'de> for Recording
impl<'de> Deserialize<'de> for Recording
Source§fn deserialize_into<'out>(
out: &'out mut Option<Self>,
state: &mut State,
) -> SinkHandle<'out, 'de>
fn deserialize_into<'out>( out: &'out mut Option<Self>, state: &mut State, ) -> SinkHandle<'out, 'de>
Source§fn expecting() -> Cow<'static, str>
fn expecting() -> Cow<'static, str>
Source§fn deserialize_atom(
slot: &mut Slot<T, Self>,
atom: Atom<'_>,
state: &mut State,
) -> Result<(), Error>
fn deserialize_atom( slot: &mut Slot<T, Self>, atom: Atom<'_>, state: &mut State, ) -> Result<(), Error>
Source§fn deserialize_borrowed_atom(
slot: &mut Slot<T, Self>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error>
fn deserialize_borrowed_atom( slot: &mut Slot<T, Self>, atom: Atom<'de>, state: &mut State, ) -> Result<(), Error>
Source§fn describe_type(d: &mut dyn Describe)
fn describe_type(d: &mut dyn Describe)
Source§fn initial_value() -> Option<T>
fn initial_value() -> Option<T>
Source§fn deserialize_update<'out>(
value: &'out mut T,
state: &mut State,
) -> SinkHandle<'out, 'de>
fn deserialize_update<'out>( value: &'out mut T, state: &mut State, ) -> SinkHandle<'out, 'de>
Source§impl PartialEq for Recording
Recordings are compared by their events.
impl PartialEq for Recording
Recordings are compared by their events.
The event data and the replayable extensions captured with the events are not compared.