Diffstat (limited to 'src/impls/core/str.rs')
| -rw-r--r-- | src/impls/core/str.rs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/impls/core/str.rs b/src/impls/core/str.rs new file mode 100644 index 0000000..a3fcc01 --- /dev/null +++ b/src/impls/core/str.rs @@ -0,0 +1,112 @@ +use core::marker::PhantomData; + +use crate::{ + build::{Build, Builder}, + error::{BasicError, UniError}, + protocol::{ + lookup_hint, lookup_visit, AnyHint, AnyVisit, Hint, Protocol, ProtocolDescription, + ProtocolId, + }, + protocol_list, + protocols::reference::{self, Reference}, + walk::{Walk, WalkMut, WalkOnce}, + walk_with_hints, HintGiven, WalkerHints, +}; + +use super::reference::BuilderRefValue; + +pub struct Walker<'value, 'ctx: 'value>(&'value str, PhantomData<&'ctx ()>); + +impl<'value, 'ctx: 'value, VisitorErr: 'ctx> crate::Walker<'value, 'ctx, VisitorErr> + for Walker<'value, 'ctx> +{ + type Error = BasicError; + + fn walk( + &mut self, + visitor: &mut dyn crate::Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>, + ) -> Result<crate::WalkStatus, UniError<Self::Error, VisitorErr>> { + match lookup_visit::<Reference<str>, _, _>(visitor).map_err(UniError::Walker)? { + Some(visitor) => { + visitor.visit(reference::Ref::Value(self.0))?; + Ok(crate::WalkStatus::Continue) + } + None => Err(UniError::Walker(BasicError::new( + "visitor needs the reference protocol for `str`", + ))), + } + } + + fn all_protocols() -> impl Iterator<Item = ProtocolDescription> + where + Self: Sized, + { + protocol_list![Reference<str>] + } +} + +impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkerHints<'value, 'ctx, VisitorErr> + for Walker<'value, 'ctx> +{ + type Error = BasicError; + + fn protocol( + &mut self, + id: ProtocolId, + ) -> Option<AnyHint<'_, 'value, 'ctx, Self::Error, VisitorErr>> { + match id { + id if id == ProtocolId::of::<Reference<str>>() => Some(AnyHint::new(self)), + _ => None, + } + } +} + +impl<'value, 'ctx: 'value, VisitorErr: 'ctx> Hint<'value, 'ctx, Reference<str>, VisitorErr> + for Walker<'value, 'ctx> +{ + type Error = BasicError; + + fn hint( + &mut self, + visitor: &mut dyn crate::Visitor<'value, 'ctx, Self::Error, Error = VisitorErr>, + _hint: <Reference<str> as crate::protocol::Protocol<'value, 'ctx>>::Hint, + ) -> Result<HintGiven, UniError<Self::Error, VisitorErr>> { + lookup_visit::<Reference<str>, _, _>(visitor) + .map_err(UniError::Walker)? + .ok_or_else(|| { + UniError::Walker(BasicError::new("visitor is missing the str protocol")) + })? + .visit(reference::Ref::Value(self.0))?; + + Ok(HintGiven) + } + + fn known( + &mut self, + _hint: &<Reference<str> as crate::protocol::Protocol<'value, 'ctx>>::Hint, + ) -> Result<<Reference<str> as crate::protocol::Protocol<'value, 'ctx>>::Known, BasicError> + { + Ok(reference::Known { + len: Some(self.0.len()), + kind: Some(reference::Kind::Context), + }) + } +} + +impl<'value, 'ctx: 'value, VisitorErr: 'ctx> WalkMut<'value, 'ctx, VisitorErr> for str { + type ErrorMut = BasicError; + type WalkerMut = Walker<'value, 'ctx>; + + fn walker_mut(&'value mut self) -> Self::WalkerMut { + Walker(self, PhantomData) + } +} + +impl<'value, 'ctx: 'value, VisitorErr: 'ctx> Walk<'value, 'ctx, VisitorErr> for str { + type Error = BasicError; + type Walker = Walker<'value, 'ctx>; + + fn walker(&'value self) -> Self::Walker { + Walker(self, PhantomData) + } +} |