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>()).map(|value| {
182            // SAFETY: values are always stored with the key of their type
183            unsafe { &*(value as *const dyn DebugAny).cast::<T>() }
184        })
185    }
186
187    #[inline]
188    fn lookup<'a>(&self, values: &'a [Entry], key: TypeId) -> Option<&'a dyn DebugAny> {
189        values
190            .iter()
191            .find(|(k, _)| k.0 == key)
192            .map(|(_, value)| &**value)
193    }
194
195    /// Returns `true` if the context holds no values.
196    #[inline]
197    pub fn is_empty(&self) -> bool {
198        self.values.as_ref().is_none_or(|values| values.is_empty())
199    }
200
201    /// Adds the values of `defaults` whose types this context has no value
202    /// for.
203    ///
204    /// Returns `false` if nothing was added.
205    pub(crate) fn fill_from(&mut self, defaults: &Context) -> bool {
206        let Some(ref defaults) = defaults.values else {
207            return false;
208        };
209        let own = match self.values {
210            Some(ref mut own) if !own.is_empty() => own,
211            _ => {
212                // the values are shared with the defaults
213                self.values = Some(defaults.clone());
214                return !defaults.is_empty();
215            }
216        };
217        if Arc::ptr_eq(own, defaults) {
218            return false;
219        }
220        let missing: Vec<Entry> = defaults
221            .iter()
222            .filter(|(key, _)| !own.iter().any(|(own_key, _)| own_key.0 == key.0))
223            .cloned()
224            .collect();
225        if missing.is_empty() {
226            return false;
227        }
228        Arc::make_mut(own).extend(missing);
229        true
230    }
231}
232
233/// Contexts are equal if they share their values (one is a clone of the
234/// other and neither was changed since) or if both are empty.  The values
235/// themselves are not compared, they do not need to implement `PartialEq`.
236impl PartialEq for Context {
237    fn eq(&self, other: &Context) -> bool {
238        match (&self.values, &other.values) {
239            (Some(a), Some(b)) if Arc::ptr_eq(a, b) => true,
240            _ => self.is_empty() && other.is_empty(),
241        }
242    }
243}
244
245impl Eq for Context {}
246
247// The values are shared and only lent out immutably.  As they are `Sync`
248// they can only change through synchronized interior mutability (like
249// mutexes and atomics) which is unwind safe.  Without this the contexts
250// (and the configurations of the formats which hold one) could not be
251// used across `catch_unwind`.
252impl core::panic::UnwindSafe for Context {}
253impl core::panic::RefUnwindSafe for Context {}
254
255impl Debug for Context {
256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257        let mut map = f.debug_map();
258        if let Some(ref values) = self.values {
259            map.entries(values.iter().map(|(key, value)| (key, value)));
260        }
261        map.finish()
262    }
263}
264
265#[test]
266fn test_context() {
267    let empty = Context::new();
268    assert!(empty.is_empty());
269    assert_eq!(empty.get::<u32>(), None);
270
271    let mut context = Context::with(1u32);
272    context.set("x");
273    assert_eq!(context.get::<u32>(), Some(&1));
274    assert_eq!(context.get::<&str>(), Some(&"x"));
275    assert_eq!(context.get::<u64>(), None);
276
277    // clones share the values until they are changed
278    let mut other = context.clone();
279    other.set(2u32);
280    assert_eq!(context.get::<u32>(), Some(&1));
281    assert_eq!(other.get::<u32>(), Some(&2));
282    assert_eq!(other.get::<&str>(), Some(&"x"));
283    assert_eq!(format!("{:?}", other), r#"{u32: 2, &str: "x"}"#);
284
285    // contexts are equal if they share their values
286    assert_eq!(context, context.clone());
287    assert_ne!(context, other);
288    assert_ne!(context, Context::with(1u32));
289    assert_eq!(empty, Context::default());
290
291    fn unwind_safe<T: core::panic::UnwindSafe + core::panic::RefUnwindSafe>() {}
292    unwind_safe::<Context>();
293}
294
295#[test]
296fn test_fill_from() {
297    let defaults = {
298        let mut context = Context::with(1u32);
299        context.set("x");
300        context
301    };
302
303    // an empty context shares the values of the defaults
304    let mut context = Context::new();
305    assert!(context.fill_from(&defaults));
306    assert_eq!(context, defaults);
307    assert!(!context.fill_from(&defaults));
308    assert!(!context.fill_from(&Context::new()));
309
310    // values of the context are kept, the others are added
311    let mut context = Context::with(2u32);
312    assert!(context.fill_from(&defaults));
313    assert_eq!(context.get::<u32>(), Some(&2));
314    assert_eq!(context.get::<&str>(), Some(&"x"));
315    assert!(!context.fill_from(&defaults));
316    assert_eq!(defaults.get::<u32>(), Some(&1));
317}