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