use core::fmt; use core::marker::PhantomData; use core::str::{self, FromStr}; use serde::de; /// A serde visitor that works for `T`s implementing `FromStr`. pub struct FromStrVisitor { expectation: &'static str, _pd: PhantomData, } impl FromStrVisitor { pub fn new(expectation: &'static str) -> Self { FromStrVisitor { expectation, _pd: PhantomData, } } } impl<'de, T> de::Visitor<'de> for FromStrVisitor where T: FromStr, ::Err: fmt::Display, { type Value = T; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.expectation) } fn visit_str(self, v: &str) -> Result { FromStr::from_str(v).map_err(E::custom) } } pub struct BytesVisitor { expectation: &'static str, parse_fn: F, } impl BytesVisitor where F: FnOnce(&[u8]) -> Result, Err: fmt::Display, { pub fn new(expectation: &'static str, parse_fn: F) -> Self { BytesVisitor { expectation, parse_fn, } } } impl<'de, F, T, Err> de::Visitor<'de> for BytesVisitor where F: FnOnce(&[u8]) -> Result, Err: fmt::Display, { type Value = T; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.expectation) } fn visit_bytes(self, v: &[u8]) -> Result { (self.parse_fn)(v).map_err(E::custom) } } macro_rules! impl_tuple_visitor { ($thing:ident, $len:expr) => { pub(crate) struct $thing { expectation: &'static str, parse_fn: F, } impl $thing where F: FnOnce(&[u8]) -> Result, E: fmt::Display, { pub fn new(expectation: &'static str, parse_fn: F) -> Self { $thing { expectation, parse_fn, } } } impl<'de, F, T, E> de::Visitor<'de> for $thing where F: FnOnce(&[u8]) -> Result, E: fmt::Display, { type Value = T; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.expectation) } fn visit_seq(self, mut seq: V) -> Result where V: de::SeqAccess<'de>, { let mut bytes = [0u8; $len]; for (i, byte) in bytes.iter_mut().enumerate() { if let Some(value) = seq.next_element()? { *byte = value; } else { return Err(de::Error::invalid_length(i, &self)); } } (self.parse_fn)(&bytes).map_err(de::Error::custom) } } } } impl_tuple_visitor!(Tuple32Visitor, 32); impl_tuple_visitor!(Tuple33Visitor, 33);