use std::fmt::Formatter;
use std::fmt::Result as FmtResult;
use serde::de::Error;
use serde::de::IgnoredAny;
use serde::de::MapAccess;
use serde::de::SeqAccess;
use serde::de::Visitor;
use super::BigDecimalPayload;
use super::big_decimal_payload_field::BigDecimalPayloadField;
pub(super) struct BigDecimalPayloadVisitor {
allow_sequence: bool,
}
impl BigDecimalPayloadVisitor {
#[must_use]
#[inline]
pub(super) fn new(allow_sequence: bool) -> Self {
Self { allow_sequence }
}
}
impl<'de> Visitor<'de> for BigDecimalPayloadVisitor {
type Value = BigDecimalPayload;
fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
f.write_str("decimal payload record with coefficient and scale fields")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
if !self.allow_sequence {
return Err(Error::custom("human-readable record must use named fields"));
}
let coefficient = seq.next_element()?.ok_or_else(|| Error::invalid_length(0, &self))?;
let scale = seq.next_element()?.ok_or_else(|| Error::invalid_length(1, &self))?;
if seq.next_element::<IgnoredAny>()?.is_some() {
return Err(Error::invalid_length(3, &self));
}
Ok(BigDecimalPayload { coefficient, scale })
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut coefficient = None;
let mut scale = None;
while let Some(key) = map.next_key::<BigDecimalPayloadField>()? {
match key {
BigDecimalPayloadField::Coefficient => {
if coefficient.is_some() {
return Err(Error::duplicate_field("coefficient"));
}
coefficient = Some(map.next_value()?);
}
BigDecimalPayloadField::Scale => {
if scale.is_some() {
return Err(Error::duplicate_field("scale"));
}
scale = Some(map.next_value()?);
}
}
}
Ok(BigDecimalPayload {
coefficient: coefficient.ok_or_else(|| Error::missing_field("coefficient"))?,
scale: scale.ok_or_else(|| Error::missing_field("scale"))?,
})
}
}