deser-core 0.9.0

Core traits and types of deser, use the deser crate instead
Documentation
use crate::State;
use crate::error::{Error, ErrorKind};
use alloc::format;
use alloc::string::String;

/// What happens if a key is given more than once.
///
/// JSON objects can contain the same key more than once and query strings
/// commonly repeat keys.  Where a single value is expected (the field of a
/// struct or an entry of a map) the policy decides what happens.  It's an
/// extension value in the [`State`] (see [`set`](Self::set)).  The default is
/// [`Error`](Self::Error): if the same key could mean different values to
/// different parsers (a proxy might use the first value, the application the
/// last) the input is rejected.
///
/// ```
/// use std::collections::BTreeMap;
/// use deser::de::{DeserializeDriver, DuplicateKeys};
/// use deser::Event;
///
/// let mut out = None::<BTreeMap<String, u32>>;
/// let mut driver = DeserializeDriver::new(&mut out);
/// DuplicateKeys::Error.set(driver.state_mut());
/// driver.emit(Event::map_start()).unwrap();
/// for value in [1u64, 2] {
///     driver.emit("a").unwrap();
///     driver.emit(value).unwrap();
/// }
/// let err = driver.emit(Event::MapEnd).unwrap_err();
/// assert_eq!(err.message(), "duplicate key in map");
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum DuplicateKeys {
    /// The last value is used.
    Last,
    /// The first value is used, later ones are ignored.
    First,
    /// Duplicate keys are rejected.
    #[default]
    Error,
}

impl DuplicateKeys {
    /// Returns the policy of a deserialization.
    #[inline]
    pub fn of(state: &State) -> DuplicateKeys {
        state.get::<DuplicateKeys>().copied().unwrap_or_default()
    }

    /// Sets the policy of a deserialization.
    #[inline]
    pub fn set(self, state: &mut State) {
        *state.get_mut::<DuplicateKeys>() = self;
    }

    /// Decides if a duplicate value is used.
    ///
    /// Returns `Ok(true)` if the value replaces the previous one, `Ok(false)`
    /// if it's ignored.  The name is used for the error.
    #[cold]
    pub(crate) fn resolve(self, what: impl FnOnce() -> String) -> Result<bool, Error> {
        match self {
            DuplicateKeys::Last => Ok(true),
            DuplicateKeys::First => Ok(false),
            DuplicateKeys::Error => Err(Error::new(ErrorKind::Unexpected, what())),
        }
    }
}

/// Marks a field of a struct as seen.
///
/// Returns `true` if it was seen before.
#[cfg(feature = "derive")]
#[inline(always)]
pub fn mark_seen(seen: &mut [u64], index: usize) -> bool {
    let (word, bit) = (index / 64, 1u64 << (index % 64));
    let seen_before = seen[word] & bit != 0;
    seen[word] |= bit;
    seen_before
}

/// Returns `true` if the field with the index was seen.
#[cfg(feature = "derive")]
pub(crate) fn is_seen(seen: &[u64], index: usize) -> bool {
    seen[index / 64] & (1u64 << (index % 64)) != 0
}

/// Decides if the value of a field given more than once is used.
///
/// Returns `Ok(true)` if the value replaces the previous one.
#[cold]
pub fn duplicate_field(name: &str, state: &State) -> Result<bool, Error> {
    DuplicateKeys::of(state).resolve(|| format!("duplicate field `{}`", name))
}