Skip to main content

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}