use std::collections::BTreeSet;
use std::fmt;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Error;
use serde::de::MapAccess;
use serde::de::SeqAccess;
use serde::de::Visitor;
pub(crate) fn unique_names(text: &str) -> Result<(), serde_json::Error> {
serde_json::from_str::<Unique>(text).map(|_| ())
}
struct Unique;
impl<'de> Deserialize<'de> for Unique {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_any(UniqueVisitor)
}
}
struct UniqueVisitor;
impl<'de> Visitor<'de> for UniqueVisitor {
type Value = Unique;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a JSON value whose objects repeat no name")
}
fn visit_bool<E: Error>(self, _: bool) -> Result<Unique, E> {
Ok(Unique)
}
fn visit_i64<E: Error>(self, _: i64) -> Result<Unique, E> {
Ok(Unique)
}
fn visit_u64<E: Error>(self, _: u64) -> Result<Unique, E> {
Ok(Unique)
}
fn visit_f64<E: Error>(self, _: f64) -> Result<Unique, E> {
Ok(Unique)
}
fn visit_str<E: Error>(self, _: &str) -> Result<Unique, E> {
Ok(Unique)
}
fn visit_unit<E: Error>(self) -> Result<Unique, E> {
Ok(Unique)
}
fn visit_seq<A: SeqAccess<'de>>(self, mut items: A) -> Result<Unique, A::Error> {
while items.next_element::<Unique>()?.is_some() {}
Ok(Unique)
}
fn visit_map<A: MapAccess<'de>>(self, mut members: A) -> Result<Unique, A::Error> {
let mut seen = BTreeSet::new();
while let Some(name) = members.next_key::<String>()? {
members.next_value::<Unique>()?;
if !seen.insert(name) {
return Err(A::Error::custom("an object repeats a name"));
}
}
Ok(Unique)
}
}