Crate serde_context

Crate serde_context 

Source
Expand description

serde_context provides convenient contextful (de)serialization compatible with the serde ecosystem.

§Basic usage

Any type that implements Context (blanket implementations are provided) can be passed to serialize_with_context or deserialize_with_context and then accessed by using context_scope within Serialize and Deserialize implementations. See these items respective documentations for more information.

§Features

This crate provides no conditional compilation features. It requires the standard library because it uses thread_locals to store and access context.

§Limitations

There are a few limitations to this crate:

  • Only immutable references may be passed as context. You may still use interior mutability (Cells, RefCells, UnsafeCells…) to mutate state.
  • Only types implementing 'static can be used as context for (de)serialization. Unsized types are supported, though.
  • There is no type-checking of required context. Trying to (de)serialize a type that requires some context but failing to provide it will result in a runtime error.

§Alternatives

There are a few alternatives to this crate you might want to consider, each with their pros and cons:

  • DeserializeSeed: the official serde stateful deserialization-only API. Requires implementing that trait for each type you are interested in deserializing, and no derive macro is provided (nor are there any plans to ever make an official one).
  • serde_state: a fork of serde that supports stateful (de)serialization. Unfortunately, it looks to be unmaintained.
  • serde_seeded: a crate providing an alternative version of the DeserializeSeed trait with a derive macro for it. Relatively young but very promising.

§Example

This minimal, contrived example showcases the basics of this crate: passing context to a serialization process and accessing it within a Serialize implementation. You can find more serious examples in this crate’s examples directory.

More concretely here, we are inserting a multiplier (MyMultiplier) inside of this serialization’s global context, and then using it to multiply every numbers (MyNumber) by it before serialization.

struct MyMultiplier(i32);

struct MyNumber(i32);

impl Serialize for MyNumber {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        context_scope(|cx| {
            let mul = cx.get::<MyMultiplier>().map_err(S::Error::custom)?;
            (self.0 * mul.0).serialize(serializer)
        })
    }
}

let mut bytes = Vec::<u8>::new();
let mut serializer = serde_json::Serializer::new(&mut bytes);
serialize_with_context(&MyNumber(6), &mut serializer, &MyMultiplier(7))?;
assert_eq!(bytes, b"42");

Structs§

ContextRef
Reference to the global context used to retrieve data within it.
MissingContextError
Error that may be returned when requested context is missing.

Traits§

Context
Types that can be passed as context for (de)serialization.

Functions§

context_scope
Access context provided to serialize_with_context or deserialize_with_context.
deserialize_with_context
Deserialize a value with some provided context.
serialize_with_context
Serialize a value with some provided context.