Skip to main content

SinkHandle

Struct SinkHandle 

Source
pub struct SinkHandle<'a, 'de: 'a>(/* private fields */);
Expand description

A handle to a Sink.

During deserialization the sinks often need to return other sinks to recurse into structures. This poses a challenge if the target sink cannot be directly borrowed. This is where SinkHandle comes in. In cases where the Sink cannot be borrowed it’s owned by the handle, either in the arena of the state (arena, which is what sinks typically use) or on the heap (heap).

The handle itself implements Sink and forwards all calls to the sink it holds.

Unlike the SerializeHandle of serialization, which holds a value that is not serialized yet, this holds a sink that is already deserializing a value. The serialization equivalent of a sink is an emitter in a Emit. The constructors line up: to borrows, arena and heap own in the same way for both handles.

Implementations§

Source§

impl<'a, 'de> SinkHandle<'a, 'de>

Source

pub fn to(sink: &'a mut dyn Sink<'de>) -> SinkHandle<'a, 'de>

Create a borrowed handle to a Sink.

Source

pub fn arena<S: Sink<'de> + 'a>( sink: S, state: &mut State, ) -> SinkHandle<'a, 'de>

Creates an owned handle to a sink in the arena of the state.

This is how sinks are typically created: the arena belongs to the state of the deserialization and the sinks of the containers that are open are on top of each other in it, allocating one is little more than bumping a pointer. Its space is reused once the handle is dropped (and the sinks allocated after it are dropped too).

A sink can outlive the deserialization it was created for (the state). The arena then frees its memory except for the chunk the sink is in, which is freed when the sink is dropped (and the other sinks in it). A sink that is meant to be kept for longer should rather be created with heap.

use deser::de::{Deserialize, DeserializeDriver, Sink, SinkHandle};
use deser::{Error, Event, State};

/// The number of items of a sequence.
struct Count(usize);

struct CountSink<'a> {
    out: &'a mut Option<Count>,
    count: usize,
}

impl<'de> Sink<'de> for CountSink<'_> {
    fn seq(&mut self, _state: &mut State) -> Result<(), Error> {
        Ok(())
    }

    fn next_value(
        &mut self,
        _state: &mut State,
    ) -> Result<SinkHandle<'_, 'de>, Error> {
        self.count += 1;
        // the items themselves are ignored
        Ok(SinkHandle::null())
    }

    fn finish(&mut self, _state: &mut State) -> Result<(), Error> {
        *self.out = Some(Count(self.count));
        Ok(())
    }
}

impl<'de> Deserialize<'de> for Count {
    fn deserialize_into<'a>(
        out: &'a mut Option<Self>,
        state: &mut State,
    ) -> SinkHandle<'a, 'de> {
        SinkHandle::arena(CountSink { out, count: 0 }, state)
    }
}

let mut out = None::<Count>;
let mut driver = DeserializeDriver::new(&mut out);
for event in [Event::seq_start(), "a".into(), "b".into(), Event::SeqEnd] {
    driver.emit(event).unwrap();
}
drop(driver);
assert_eq!(out.unwrap().0, 2);
Source

pub fn heap<S: Sink<'de> + 'a>(sink: S) -> SinkHandle<'a, 'de>

Creates an owned handle to a sink on the heap.

Unlike arena the sink does not need a state and is independent of any deserialization, but every sink is a separate allocation.

Source

pub fn null() -> SinkHandle<'a, 'de>

Creates a sink handle that drops all values.

This can be used in places where a sink is required but no value wants to be collected. For instance it can be tricky to provide a mutable reference to a sink from a function that doesn’t have a way to put a slot somewhere.

Source

pub fn shorten<'b>(self) -> SinkHandle<'b, 'de>
where 'a: 'b,

Shortens the lifetime of the handle.

Handles are invariant over their lifetime, this performs the conversion explicitly.

Source

pub fn is_null(&self) -> bool

Returns true if this is a null handle.

Source

pub fn ignore_null(self) -> SinkHandle<'a, 'de>

Converts the handle into one that ignores null atoms.

When a null atom is received the wrapped sink is not invoked (not even finish) and the handle turns into a null handle. An atom counts as null if it is Atom::Null or an extension value which falls back to null. An empty Atom::Lexical (like the value of ?limit= in a query string) is passed to the wrapped sink, if the sink rejects it the handle turns into a null handle too.

This is used to implement Option<T>: the slot is set to Some(None) before the handle of the inner value is created and made to ignore nulls.

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

/// Deserializes like an `Option<T>`.
fn deserialize_optional<'a, 'de, T: Deserialize<'de>>(
    out: &'a mut Option<Option<T>>,
    state: &mut State,
) -> SinkHandle<'a, 'de> {
    T::deserialize_into(out.insert(None), state).ignore_null()
}

Trait Implementations§

Source§

impl<'a, 'de> Sink<'de> for SinkHandle<'a, 'de>

Source§

fn atom(&mut self, atom: Atom<'_>, state: &mut State) -> Result<(), Error>

Receives an Atom. Read more
Source§

fn borrowed_atom( &mut self, atom: Atom<'de>, state: &mut State, ) -> Result<(), Error>

Receives an Atom that borrows from the data being deserialized. Read more
Source§

fn map(&mut self, state: &mut State) -> Result<(), Error>

Begins the deserialization of a map. Read more
Source§

fn seq(&mut self, state: &mut State) -> Result<(), Error>

Begins the receiving process for sequences. Read more
Source§

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

Returns a sink for the next key in a map.
Source§

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

Returns a sink for the next value in a map or sequence.
Source§

fn value_for_key( &mut self, key: &str, state: &mut State, ) -> Result<Option<SinkHandle<'_, 'de>>, Error>

Returns a value sink for a specific struct field. Read more
Source§

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

Called after atom, map or `seq. Read more
Source§

fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error>

Called when an item of this map or sequence failed. Read more
Source§

fn expecting(&self) -> Cow<'_, str>

Returns what the sink expects, for error messages. Read more

Auto Trait Implementations§

§

impl<'a, 'de> !RefUnwindSafe for SinkHandle<'a, 'de>

§

impl<'a, 'de> !Sync for SinkHandle<'a, 'de>

§

impl<'a, 'de> !Unpin for SinkHandle<'a, 'de>

§

impl<'a, 'de> !UnwindSafe for SinkHandle<'a, 'de>

§

impl<'a, 'de> Freeze for SinkHandle<'a, 'de>

§

impl<'a, 'de> Send for SinkHandle<'a, 'de>

§

impl<'a, 'de> UnsafeUnpin for SinkHandle<'a, 'de>

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> 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, 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.