use std::fmt;
use std::ops::{Deref, DerefMut};
use serde::de::{SeqAccess, Visitor};
use serde::ser::SerializeSeq;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::Repetition;
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Field(pub er7::Field);
impl From<er7::Field> for Field {
fn from(inner: er7::Field) -> Field {
Field(inner)
}
}
impl From<Field> for er7::Field {
fn from(outer: Field) -> er7::Field {
outer.0
}
}
impl Deref for Field {
type Target = er7::Field;
fn deref(&self) -> &er7::Field {
&self.0
}
}
impl DerefMut for Field {
fn deref_mut(&mut self) -> &mut er7::Field {
&mut self.0
}
}
impl Serialize for Field {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let repetitions = &self.0.repetitions;
let mut seq = serializer.serialize_seq(Some(repetitions.len()))?;
for repetition in repetitions {
seq.serialize_element(&Repetition(repetition.clone()))?;
}
seq.end()
}
}
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an array of repetitions, each an array of components")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Field, A::Error>
where
A: SeqAccess<'de>,
{
let mut repetitions = Vec::with_capacity(seq.size_hint().unwrap_or(0));
while let Some(repetition) = seq.next_element::<Repetition>()? {
repetitions.push(repetition.0);
}
Ok(Field(er7::Field { repetitions }))
}
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(FieldVisitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trips_repeated_values() {
let field = Field(er7::Field {
repetitions: vec![
er7::Repetition {
components: vec![er7::Component {
subcomponents: vec![er7::Subcomponent::new("555-1111")],
}],
},
er7::Repetition {
components: vec![er7::Component {
subcomponents: vec![er7::Subcomponent::new("555-2222")],
}],
},
],
});
let json = serde_json::to_string(&field).unwrap();
assert_eq!(json, r#"[[["555-1111"]],[["555-2222"]]]"#);
let back: Field = serde_json::from_str(&json).unwrap();
assert_eq!(back, field);
}
#[test]
fn an_absent_field_is_an_empty_array() {
let field = Field::default();
assert_eq!(serde_json::to_string(&field).unwrap(), "[]");
}
}