use crate::State;
use crate::error::{Error, ErrorKind};
use alloc::format;
use alloc::string::String;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum DuplicateKeys {
Last,
First,
#[default]
Error,
}
impl DuplicateKeys {
#[inline]
pub fn of(state: &State) -> DuplicateKeys {
state.get::<DuplicateKeys>().copied().unwrap_or_default()
}
#[inline]
pub fn set(self, state: &mut State) {
*state.get_mut::<DuplicateKeys>() = self;
}
#[inline]
pub fn set_default(self, state: &mut State) {
state.set_default(self);
}
#[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::DuplicateKey, what())),
}
}
}
#[cfg(feature = "derive")]
#[inline(always)]
pub(crate) 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
}
#[cfg(feature = "derive")]
pub(crate) fn is_seen(seen: &[u64], index: usize) -> bool {
seen[index / 64] & (1u64 << (index % 64)) != 0
}
#[cold]
pub(crate) fn duplicate_field(name: &str, state: &State) -> Result<bool, Error> {
DuplicateKeys::of(state).resolve(|| format!("duplicate field `{}`", name))
}