Diffstat (limited to 'src/impls.rs')
-rw-r--r--src/impls.rs141
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>;
+ }
+};