1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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>;
    }
};