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)
}
}