use serde::de::{self, DeserializeOwned, Deserializer, MapAccess, SeqAccess, Visitor};
use spate_core::hash::QualitySet;
use std::borrow::Cow;
use std::fmt;
#[cfg(feature = "simd")]
pub const BACKEND_ID: &str = "simd-json";
#[cfg(not(feature = "simd"))]
pub const BACKEND_ID: &str = "serde_json";
#[derive(Debug)]
pub(crate) struct DecodeError {
pub(crate) is_data: bool,
msg: String,
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.msg)
}
}
impl From<serde_json::Error> for DecodeError {
fn from(e: serde_json::Error) -> Self {
DecodeError {
is_data: e.is_data(),
msg: e.to_string(),
}
}
}
#[cfg(not(feature = "simd"))]
#[inline]
pub(crate) fn decode_one<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, DecodeError> {
serde_json::from_slice(bytes).map_err(DecodeError::from)
}
#[cfg(feature = "simd")]
thread_local! {
static SIMD: std::cell::RefCell<(Vec<u8>, simd_json::Buffers)> =
std::cell::RefCell::new((Vec::new(), simd_json::Buffers::new(0)));
}
#[cfg(feature = "simd")]
#[inline]
pub(crate) fn decode_one<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, DecodeError> {
SIMD.with(|cell| {
let (buf, buffers) = &mut *cell.borrow_mut();
buf.clear();
buf.extend_from_slice(bytes);
simd_json::serde::from_slice_with_buffers::<T>(buf.as_mut_slice(), buffers).map_err(|e| {
DecodeError {
is_data: false,
msg: e.to_string(),
}
})
})
}
pub(crate) fn check_no_duplicate_keys(bytes: &[u8]) -> Result<(), DecodeError> {
serde_json::from_slice::<DupGuard>(bytes)
.map(|_| ())
.map_err(DecodeError::from)
}
struct DupGuard;
impl<'de> serde::Deserialize<'de> for DupGuard {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(DupVisitor)
}
}
struct DupVisitor;
struct Key<'de>(Cow<'de, str>);
impl<'de> serde::Deserialize<'de> for Key<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(KeyVisitor)
}
}
struct KeyVisitor;
impl<'de> Visitor<'de> for KeyVisitor {
type Value = Key<'de>;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("an object key")
}
fn visit_borrowed_str<E: de::Error>(self, v: &'de str) -> Result<Self::Value, E> {
Ok(Key(Cow::Borrowed(v)))
}
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
Ok(Key(Cow::Owned(v.to_owned())))
}
}
impl<'de> Visitor<'de> for DupVisitor {
type Value = DupGuard;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("any JSON value with unique object keys")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut seen: QualitySet<Cow<'de, str>> = QualitySet::default();
while let Some(Key(key)) = map.next_key::<Key<'de>>()? {
if let Some(dup) = seen.replace(key) {
return Err(de::Error::custom(format!("duplicate object key `{dup}`")));
}
map.next_value::<DupGuard>()?;
}
Ok(DupGuard)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
while seq.next_element::<DupGuard>()?.is_some() {}
Ok(DupGuard)
}
fn visit_bool<E>(self, _v: bool) -> Result<Self::Value, E> {
Ok(DupGuard)
}
fn visit_i64<E>(self, _v: i64) -> Result<Self::Value, E> {
Ok(DupGuard)
}
fn visit_u64<E>(self, _v: u64) -> Result<Self::Value, E> {
Ok(DupGuard)
}
fn visit_f64<E>(self, _v: f64) -> Result<Self::Value, E> {
Ok(DupGuard)
}
fn visit_str<E>(self, _v: &str) -> Result<Self::Value, E> {
Ok(DupGuard)
}
fn visit_none<E>(self) -> Result<Self::Value, E> {
Ok(DupGuard)
}
fn visit_unit<E>(self) -> Result<Self::Value, E> {
Ok(DupGuard)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(DupVisitor)
}
}
#[cfg(test)]
mod tests {
use super::{Key, check_no_duplicate_keys};
use serde::Deserialize;
use serde::de::{IgnoredAny, MapAccess, Visitor};
use std::borrow::Cow;
use std::fmt;
struct ObjectKeys<'de>(Vec<Cow<'de, str>>);
impl<'de> Deserialize<'de> for ObjectKeys<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(ObjectKeysVisitor)
}
}
struct ObjectKeysVisitor;
impl<'de> Visitor<'de> for ObjectKeysVisitor {
type Value = ObjectKeys<'de>;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("a JSON object")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut keys = Vec::new();
while let Some(Key(key)) = map.next_key::<Key<'de>>()? {
map.next_value::<IgnoredAny>()?;
keys.push(key);
}
Ok(ObjectKeys(keys))
}
}
#[test]
fn an_unescaped_key_borrows_from_the_payload() {
let ObjectKeys(keys) = serde_json::from_slice(br#"{"abc":1,"\u0061bc":2}"#).unwrap();
assert!(matches!(keys[0], Cow::Borrowed("abc")));
assert!(matches!(keys[1], Cow::Owned(_)));
}
#[test]
fn duplicate_key_names_the_key() {
let err = check_no_duplicate_keys(br#"{"id":1,"id":2}"#).unwrap_err();
assert!(err.is_data, "{err}");
assert_eq!(
err.to_string(),
"duplicate object key `id` at line 1 column 12"
);
}
#[test]
fn escaped_spelling_is_the_same_key() {
let err = check_no_duplicate_keys(br#"{"\u0061":1,"a":2}"#).unwrap_err();
assert!(err.is_data, "{err}");
assert!(
err.to_string().starts_with("duplicate object key `a`"),
"{err}"
);
}
#[test]
fn plain_spelling_matches_an_escaped_duplicate() {
let err = check_no_duplicate_keys(br#"{"a":1,"\u0061":2}"#).unwrap_err();
assert!(err.is_data, "{err}");
assert!(
err.to_string().starts_with("duplicate object key `a`"),
"{err}"
);
}
#[test]
fn same_key_in_sibling_scopes_is_clean() {
check_no_duplicate_keys(br#"{"a":{"a":1},"b":[{"a":1},{"a":2}]}"#).unwrap();
}
}