use serde::de::{self, Deserializer, MapAccess, Visitor};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::fmt;
use super::Reference;
use crate::Oid;
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(untagged)]
pub enum Target {
Oid { oid: Oid },
Path { path: String },
Ref {
#[serde(rename = "ref")]
ref_: Reference,
},
Pair { pair: Box<[Target; 2]> },
Refs { refs: bool },
Shard { shard: bool },
Empty {},
}
impl<'de> Deserialize<'de> for Target {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct TargetVisitor;
impl<'de> Visitor<'de> for TargetVisitor {
type Value = Target;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(
"a Target object: {} | {oid} | {path} | {ref} | {pair} | {refs} | {shard}",
)
}
fn visit_map<M>(self, mut map: M) -> Result<Target, M::Error>
where
M: MapAccess<'de>,
{
let mut entries: Vec<(String, Value)> = Vec::new();
while let Some((k, v)) = map.next_entry::<String, Value>()? {
entries.push((k, v));
}
if entries.is_empty() {
return Ok(Target::Empty {});
}
if entries.len() != 1 {
return Err(de::Error::custom(format!(
"Target object must have exactly one key, got {}",
entries.len()
)));
}
let (key, value) = entries.into_iter().next().unwrap();
match key.as_str() {
"oid" => Ok(Target::Oid {
oid: serde_json::from_value(value).map_err(de::Error::custom)?,
}),
"path" => Ok(Target::Path {
path: serde_json::from_value(value).map_err(de::Error::custom)?,
}),
"ref" => Ok(Target::Ref {
ref_: serde_json::from_value(value).map_err(de::Error::custom)?,
}),
"pair" => Ok(Target::Pair {
pair: serde_json::from_value(value).map_err(de::Error::custom)?,
}),
"refs" => Ok(Target::Refs {
refs: serde_json::from_value(value).map_err(de::Error::custom)?,
}),
"shard" => Ok(Target::Shard {
shard: serde_json::from_value(value).map_err(de::Error::custom)?,
}),
other => Err(de::Error::custom(format!(
"unknown Target key: `{}`",
other
))),
}
}
}
deserializer.deserialize_map(TargetVisitor)
}
}