Diffstat (limited to 'src/impls.rs')
| -rw-r--r-- | src/impls.rs | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/impls.rs b/src/impls.rs new file mode 100644 index 0000000..1c4d788 --- /dev/null +++ b/src/impls.rs @@ -0,0 +1,141 @@ +use crate::{ + lookup_hint, lookup_visit, + protocol::{AnyHint, AnyVisit, Protocol, ProtocolId}, + protocols::{self, str::Str}, + BasicError, Buildable, Error, Hint, HintGiven, Hints, Walkable, WalkableRef, +}; + +const _: () = { + pub struct Walker<'value>(&'value str); + + impl<'value> crate::Walker<'value> for Walker<'value> { + type Error = BasicError; + + fn hints(&mut self) -> &mut dyn Hints<'value, Self::Error> { + self + } + } + + impl<'value, Err: Error<'value>> Hints<'value, Err> for Walker<'value> { + fn protocol(&mut self, id: ProtocolId) -> Option<AnyHint<'_, 'value, Err>> { + match id { + id if id == ProtocolId::of::<Str>() => Some(AnyHint::new(self)), + _ => None, + } + } + } + + impl<'value, Err: Error<'value>> Hint<'value, Str, Err> for Walker<'value> { + fn hint( + &mut self, + visitor: &mut dyn crate::Visitor<'value, Err>, + _hint: <Str as crate::protocol::Protocol>::Hint, + ) -> Result<HintGiven, Err> { + lookup_visit::<Str, _, _>(visitor)? + .ok_or_else(Err::missing_visit::<Str>)? + .visit(protocols::str::Data::Value(self.0))?; + + Ok(HintGiven) + } + + fn known( + &mut self, + _hint: &<Str as crate::protocol::Protocol>::Hint, + ) -> Result<<Str as crate::protocol::Protocol>::Known, Err> { + Ok(protocols::str::Known { + len: Some(self.0.len()), + kind: Some(protocols::str::Kind::Value), + }) + } + } + + impl<'walking, 'value: 'walking> Walkable<'walking, 'value> for &'value str { + type Walker = Walker<'value>; + + fn walker(&'walking mut self) -> Self::Walker { + Walker(self) + } + } + + impl<'walking, 'value: 'walking> WalkableRef<'walking, 'value> for &'value str { + fn walker_ref(&'walking self) -> Self::Walker { + Walker(self) + } + } + + pub struct Visitor<'value>(Option<&'value str>); + + impl<'value, Err: Error<'value>> crate::Visitor<'value, Err> for Visitor<'value> { + fn request_hint( + &mut self, + hints: &mut dyn Hints<'value, Err>, + ) -> Result<Option<HintGiven>, Err> { + if let Some(hint) = lookup_hint::<Str, _, _>(hints)? { + Ok(Some(hint.hint( + self, + protocols::str::Hint { + kind: Some(protocols::str::Kind::Value), + min_len: None, + max_len: None, + }, + )?)) + } else { + Ok(None) + } + } + + fn protocol(&mut self, id: ProtocolId) -> Option<AnyVisit<'_, 'value, Err>> { + match id { + id if id == ProtocolId::of::<Str>() => Some(AnyVisit::new(self)), + _ => None, + } + } + } + + impl<'value, Err: Error<'value>> crate::Visit<'value, Str, Err> for Visitor<'value> { + fn visit<'walking>( + &'walking mut self, + accessor: <Str as Protocol<'value>>::Accessor<'walking, Err>, + ) -> Result<(), Err> { + match accessor { + protocols::str::Data::Value(str) | protocols::str::Data::Static(str) => { + self.0 = Some(str) + } + protocols::str::Data::Walking(_) => { + return Err(Err::custom("str value does not live long enough")) + } + } + Ok(()) + } + } + + impl<'value, Err: Error<'value>> crate::Builder<'value, Err> for Visitor<'value> { + type Value = &'value str; + + fn init() -> Self + where + Self: Sized, + { + Visitor(None) + } + + fn as_visitor(&mut self) -> &mut dyn crate::Visitor<'value, Err> { + self + } + + fn finish(self) -> Result<Self::Value, Err> + where + Self: Sized, + { + if let Some(str) = self.0 { + Ok(str) + } else { + Err(Err::custom_static_str("missing str")) + } + } + } + + impl<'value, Err: Error<'value>> Buildable<'value, Err> for &'value str { + type Builder = Visitor<'value>; + } +}; |