deser_core/context.rs
1use alloc::sync::Arc;
2use alloc::vec::Vec;
3use core::any::TypeId;
4use core::fmt::{self, Debug};
5
6use crate::extensions::{DebugAny, TypeKey};
7
8/// A value of a context with the key of its type.
9type Entry = (TypeKey, Arc<dyn DebugAny>);
10
11/// Configuration for serializations and deserializations.
12///
13/// A context holds typed values which are given to a serialization or
14/// deserialization from the outside: policies like how unknown fields are
15/// handled ([`UnknownFields`](crate::de::UnknownFields)), how bytes are
16/// decoded from strings ([`BytesFormat`](crate::BytesFormat)), limits for
17/// untrusted input ([`Limits`](crate::de::Limits)), whether formats
18/// provide source locations ([`TrackLocations`](crate::TrackLocations)) or
19/// data that types need, such as the variants of open enums. It's created
20/// once and given to every serialization or deserialization that uses it,
21/// usually with the deserializer and serializer configurations of the
22/// formats (for instance `deser_json::DeserializerConfig::builder().context(context)`):
23///
24/// ```
25/// use deser::de::DuplicateKeys;
26/// use deser::Context;
27/// use std::collections::BTreeMap;
28///
29/// let context = Context::with(DuplicateKeys::Last);
30///
31/// let config = deser_json::DeserializerConfig::builder()
32/// .context(context.clone())
33/// .build();
34/// let map: BTreeMap<String, u32> = config.from_str(r#"{"a": 1, "a": 2}"#).unwrap();
35/// assert_eq!(map["a"], 2);
36/// ```
37///
38/// A single deserialization can be given a context of its own in the setup
39/// callback of [`Deserializer::deserialize_with`](crate::de::Deserializer::deserialize_with)
40/// (and serializations in the one of `serialize_with`). Its values take
41/// precedence, the values of the format's context are added for the types
42/// it has no value for:
43///
44/// ```
45/// use deser::de::{Deserializer, DuplicateKeys, Limits};
46/// use deser::Context;
47/// use std::collections::BTreeMap;
48///
49/// let config = deser_json::DeserializerConfig::builder()
50/// .context(Context::with(DuplicateKeys::Last))
51/// .build();
52/// let limits = Context::with(Limits::builder().max_items(2).build());
53///
54/// let input = r#"{"a": 1, "a": 2, "b": 3}"#;
55/// let err = deser_json::Deserializer::from_str_with_config(input, config)
56/// .deserialize_with::<BTreeMap<String, u32>, _>(|driver| {
57/// driver.set_context(limits.clone())
58/// })
59/// .unwrap_err();
60/// assert_eq!(err.to_string(), "LimitExceeded: too many items at line 1 column 18");
61/// ```
62///
63/// The readers and writers of the [`io` module][io-module] have
64/// `set_context` methods too.
65///
66/// The values of the context are the defaults of the extension values of
67/// the [`State`](crate::State): [`State::get`](crate::State::get) returns
68/// the value of the state if there is one and the value of the context
69/// otherwise. The values that the state holds change during a
70/// serialization or deserialization (for instance a format or a type sets
71/// a value for a part of the data), the context does not change.
72///
73/// Cloning a context is cheap, the values are shared. Values are
74/// [`Debug`], [`Send`] and [`Sync`] like the extension values of the state
75/// so that contexts can be shared between threads. Values that collect
76/// results (like [`UnknownFields::Collect`](crate::de::UnknownFields::Collect))
77/// are shared too: everything that uses the context reports to them, so
78/// they belong into the state of a single deserialization instead.
79///
80/// # Values
81///
82/// These are the values that deser itself reads from a context. Unless
83/// noted otherwise, a value in the [`State`](crate::State) takes
84/// precedence over the one of the context.
85///
86/// Deserialization:
87///
88/// * [`UnknownFields`](crate::de::UnknownFields): what happens with keys
89/// of structs that no field takes. Ignored by default.
90/// * [`DuplicateKeys`](crate::de::DuplicateKeys): what happens if a key is
91/// given more than once. Rejected by default (query strings and
92/// environment variables use the last value).
93/// * [`LexicalRules`](crate::de::LexicalRules): how
94/// [lexical atoms](crate::Atom::Lexical) are interpreted. Strict by
95/// default (query strings, environment variables and CSV are lenient).
96/// * [`Limits`](crate::de::Limits): limits of the nesting depth, the
97/// number of events and items and the length of strings and bytes.
98/// Unlimited by default. Only read from the context and enforced by
99/// the [`DeserializeDriver`](crate::de::DeserializeDriver).
100/// * [`CollectErrors`](crate::de::CollectErrors): collects the errors of
101/// the whole deserialization instead of failing on the first one,
102/// optionally up to a limit. Off by default. Only read from the
103/// context.
104/// * [`TrackLocations`](crate::TrackLocations): asks the formats to
105/// provide the [`Source`](crate::Source) to resolve input ranges into
106/// lines and columns. Off by default.
107///
108/// Serialization and deserialization:
109///
110/// * [`BytesFormat`](crate::BytesFormat): how bytes are represented in
111/// formats without native bytes. Base64 by default.
112/// * [`OpenEnums`][open-enums] (with the `open-enums` feature): the
113/// registered variants of open enums. Required to deserialize open
114/// enums, only the registered variants can be deserialized.
115///
116/// Any other type that is [`Debug`], [`Send`], [`Sync`] and `'static` can
117/// be a value too. Types and formats read their own values with
118/// [`State::get`](crate::State::get) (which falls back to the context) or
119/// [`State::context`](crate::State::context):
120///
121/// ```
122/// use deser::{Context, State};
123///
124/// #[derive(Debug)]
125/// struct Greeting(&'static str);
126///
127/// let mut state = State::new();
128/// state.set_context(Context::with(Greeting("hello")));
129/// assert_eq!(state.get::<Greeting>().unwrap().0, "hello");
130/// ```
131#[cfg_attr(feature = "io", doc = "[io-module]: crate::io")]
132#[cfg_attr(
133 not(feature = "io"),
134 doc = "[io-module]: https://docs.rs/deser/latest/deser/io/"
135)]
136#[cfg_attr(feature = "open-enums", doc = "[open-enums]: crate::OpenEnums")]
137#[cfg_attr(
138 not(feature = "open-enums"),
139 doc = "[open-enums]: https://docs.rs/deser/latest/deser/struct.OpenEnums.html"
140)]
141#[derive(Clone, Default)]
142pub struct Context {
143 // `None` for the empty context so that it does not allocate.
144 // Invariant: the value of an entry is always of the type of its key.
145 values: Option<Arc<Vec<Entry>>>,
146}
147
148impl Context {
149 /// Creates an empty context.
150 pub const fn new() -> Context {
151 Context { values: None }
152 }
153
154 /// Creates a context with a value.
155 pub fn with<T: Debug + Send + Sync + 'static>(value: T) -> Context {
156 let mut context = Context::new();
157 context.set(value);
158 context
159 }
160
161 /// Sets a value, replacing a value of the same type.
162 ///
163 /// If the values are shared with clones of the context, they are copied
164 /// (the values themselves are shared).
165 pub fn set<T: Debug + Send + Sync + 'static>(&mut self, value: T) {
166 let values = Arc::make_mut(self.values.get_or_insert_with(Default::default));
167 let value: Arc<dyn DebugAny> = Arc::new(value);
168 match values
169 .iter_mut()
170 .find(|(key, _)| key.0 == TypeId::of::<T>())
171 {
172 Some(entry) => entry.1 = value,
173 None => values.push((TypeKey::of::<T>(), value)),
174 }
175 }
176
177 /// Returns the value of a type.
178 #[inline]
179 pub fn get<T: Debug + Send + Sync + 'static>(&self) -> Option<&T> {
180 let values = self.values.as_deref()?;
181 self.lookup(values, TypeId::of::<T>())?.downcast_ref::<T>()
182 }
183
184 #[inline]
185 fn lookup<'a>(&self, values: &'a [Entry], key: TypeId) -> Option<&'a Arc<dyn DebugAny>> {
186 values
187 .iter()
188 .find(|(k, _)| k.0 == key)
189 .map(|(_, value)| value)
190 }
191
192 /// Returns `true` if the context holds no values.
193 #[inline]
194 pub fn is_empty(&self) -> bool {
195 self.values.as_ref().is_none_or(|values| values.is_empty())
196 }
197
198 /// Adds the values of `defaults` whose types this context has no value
199 /// for.
200 ///
201 /// Returns `false` if nothing was added.
202 pub(crate) fn fill_from(&mut self, defaults: &Context) -> bool {
203 let Some(ref defaults) = defaults.values else {
204 return false;
205 };
206 let own = match self.values {
207 Some(ref mut own) if !own.is_empty() => own,
208 _ => {
209 // the values are shared with the defaults
210 self.values = Some(defaults.clone());
211 return !defaults.is_empty();
212 }
213 };
214 if Arc::ptr_eq(own, defaults) {
215 return false;
216 }
217 let missing: Vec<Entry> = defaults
218 .iter()
219 .filter(|(key, _)| !own.iter().any(|(own_key, _)| own_key.0 == key.0))
220 .cloned()
221 .collect();
222 if missing.is_empty() {
223 return false;
224 }
225 Arc::make_mut(own).extend(missing);
226 true
227 }
228}
229
230/// Contexts are equal if they share their values (one is a clone of the
231/// other and neither was changed since) or if both are empty. The values
232/// themselves are not compared, they do not need to implement `PartialEq`.
233impl PartialEq for Context {
234 fn eq(&self, other: &Context) -> bool {
235 match (&self.values, &other.values) {
236 (Some(a), Some(b)) if Arc::ptr_eq(a, b) => true,
237 _ => self.is_empty() && other.is_empty(),
238 }
239 }
240}
241
242impl Eq for Context {}
243
244// The values are shared and only lent out immutably. As they are `Sync`
245// they can only change through synchronized interior mutability (like
246// mutexes and atomics) which is unwind safe. Without this the contexts
247// (and the configurations of the formats which hold one) could not be
248// used across `catch_unwind`.
249impl core::panic::UnwindSafe for Context {}
250impl core::panic::RefUnwindSafe for Context {}
251
252impl Debug for Context {
253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254 let mut map = f.debug_map();
255 if let Some(ref values) = self.values {
256 map.entries(values.iter().map(|(key, value)| (key, value)));
257 }
258 map.finish()
259 }
260}
261
262#[test]
263fn test_context() {
264 let empty = Context::new();
265 assert!(empty.is_empty());
266 assert_eq!(empty.get::<u32>(), None);
267
268 let mut context = Context::with(1u32);
269 context.set("x");
270 assert_eq!(context.get::<u32>(), Some(&1));
271 assert_eq!(context.get::<&str>(), Some(&"x"));
272 assert_eq!(context.get::<u64>(), None);
273
274 // clones share the values until they are changed
275 let mut other = context.clone();
276 other.set(2u32);
277 assert_eq!(context.get::<u32>(), Some(&1));
278 assert_eq!(other.get::<u32>(), Some(&2));
279 assert_eq!(other.get::<&str>(), Some(&"x"));
280 assert_eq!(format!("{:?}", other), r#"{u32: 2, &str: "x"}"#);
281
282 // contexts are equal if they share their values
283 assert_eq!(context, context.clone());
284 assert_ne!(context, other);
285 assert_ne!(context, Context::with(1u32));
286 assert_eq!(empty, Context::default());
287
288 fn unwind_safe<T: core::panic::UnwindSafe + core::panic::RefUnwindSafe>() {}
289 unwind_safe::<Context>();
290}
291
292#[test]
293fn test_fill_from() {
294 let defaults = {
295 let mut context = Context::with(1u32);
296 context.set("x");
297 context
298 };
299
300 // an empty context shares the values of the defaults
301 let mut context = Context::new();
302 assert!(context.fill_from(&defaults));
303 assert_eq!(context, defaults);
304 assert!(!context.fill_from(&defaults));
305 assert!(!context.fill_from(&Context::new()));
306
307 // values of the context are kept, the others are added
308 let mut context = Context::with(2u32);
309 assert!(context.fill_from(&defaults));
310 assert_eq!(context.get::<u32>(), Some(&2));
311 assert_eq!(context.get::<&str>(), Some(&"x"));
312 assert!(!context.fill_from(&defaults));
313 assert_eq!(defaults.get::<u32>(), Some(&1));
314}