1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//! [`serde_context`](crate) provides convenient contextful (de)serialization compatible with the [`serde`](https://docs.rs/serde/latest/serde/index.html) 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`](https://docs.rs/serde/latest/serde/trait.Serialize.html) and
//! [`Deserialize`](https://docs.rs/serde/latest/serde/trait.Deserialize.html) 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_local`]s 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 ([`Cell`](std::cell::Cell)s,
//! [`RefCell`](std::cell::RefCell)s, [`UnsafeCell`](std::cell::UnsafeCell)s...) 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`](https://docs.rs/serde/latest/serde/de/trait.DeserializeSeed.html): 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`](https://docs.rs/serde_state/latest/serde_state): a fork of serde that supports stateful
//! (de)serialization. Unfortunately, it looks to be unmaintained.
//! * [`serde_seeded`](https://docs.rs/serde-seeded/latest/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`](https://docs.rs/serde/latest/serde/trait.Serialize.html)
//! implementation. You can find more serious examples in this crate's
//! [examples directory](https://codeberg.org/blefebvre/serde_context/src/branch/master/examples).
//!
//! 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.
//!
//! ```rust
//! # use serde::{Serialize, Serializer};
//! # use serde::ser::Error;
//! # use serde_context::{context_scope, serialize_with_context};
//! #
//! 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)
//! })
//! }
//! }
//!
//! # fn main() -> anyhow::Result<()> {
//! 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");
//! # Ok(())
//! # }
//! ```
use ;
pub use crate;
/// Serialize a value with some provided context.
///
/// Provided `context` can then be accessed using [`context_scope`] in implementations of
/// [`Serialize`]. This function is meant to be the contextful version of `value.serialize(serializer)`.
///
/// # Example
///
/// This is only a minimal example for this function's usage. You can find more in this [`crate`]'s
/// top-level documentation as well as [its examples directory](https://codeberg.org/blefebvre/serde_context/src/branch/master/examples).
///
/// ```rust
/// # use serde_context::serialize_with_context;
/// #
/// # fn main() -> anyhow::Result<()> {
/// let mut bytes = Vec::<u8>::new();
/// let mut serializer = serde_json::Serializer::new(&mut bytes);
/// serialize_with_context(&vec![1, 2, 3], &mut serializer, ())?;
/// assert_eq!(bytes, b"[1,2,3]");
/// # Ok(())
/// # }
/// ```
/// Deserialize a value with some provided context.
///
/// Provided `context` can then be accessed using [`context_scope`] in implementations of
/// [`Deserialize`]. This function is meant to be the contextful version of `T::deserialize(deserializer)`.
///
/// # Example
///
/// This is only a minimal example for this function's usage. You can find more in this [`crate`]'s
/// top-level documentation as well as [its examples directory](https://codeberg.org/blefebvre/serde_context/src/branch/master/examples).
///
/// ```rust
/// # use serde_context::deserialize_with_context;
/// #
/// # fn main() -> anyhow::Result<()> {
/// let mut deserializer = serde_json::Deserializer::from_str("[1,2,3]");
/// let ids: Vec<i32> = deserialize_with_context(&mut deserializer, ())?;
/// assert_eq!(ids, vec![1, 2, 3]);
/// # Ok(())
/// # }
/// ```
/// This is the contextful version of [`Deserialize::deserialize_in_place`], the hidden method
/// that provides in-place deserialization.
///
/// See [`deserialize_with_context`].
/// Access context provided to [`serialize_with_context`] or [`deserialize_with_context`].
///
/// This function is meant to be used within [`Serialize`] and [`Deserialize`] implementations
/// to access context for contextful (de)serialization.
///
/// # Example
///
/// This is only a minimal example for this function's usage. You can find more in this [`crate`]'s
/// top-level documentation as well as [its examples directory](https://codeberg.org/blefebvre/serde_context/src/branch/master/examples).
///
/// ```rust
/// # use serde_context::{context_scope, MissingContextError};
/// #
/// struct Foo;
///
/// # fn returns_error() -> anyhow::Result<()> {
/// context_scope(|cx| {
/// let foo = cx.get::<Foo>()?;
/// // Do something with foo...
/// # _ = foo;
/// # Ok(())
/// })
/// # }
///
/// # assert!(matches!(returns_error(), Err(_)))
/// ```