pear/
expected.rs

1use std::fmt;
2
3use inlinable_string::InlinableString;
4
5use crate::input::Show;
6
7#[derive(Clone)]
8pub enum CowInlineString {
9    Borrowed(&'static str),
10    Inline(InlinableString)
11}
12
13impl std::ops::Deref for CowInlineString {
14    type Target = str;
15    fn deref(&self) -> &Self::Target {
16        match self {
17            CowInlineString::Borrowed(s) => s,
18            CowInlineString::Inline(s) => s,
19        }
20    }
21}
22
23impl std::fmt::Display for CowInlineString {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        str::fmt(self, f)
26    }
27}
28
29impl std::fmt::Debug for CowInlineString {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        str::fmt(self, f)
32    }
33}
34
35pub enum Expected<Token, Slice> {
36    Token(Option<InlinableString>, Option<Token>),
37    Slice(Option<InlinableString>, Option<Slice>),
38    Eof(Option<Token>),
39    Other(CowInlineString),
40    Elided
41}
42
43impl<Token, Slice> Expected<Token, Slice> {
44    pub fn token<T: Show>(expected: Option<&T>, found: Option<Token>) -> Self {
45        let expected = expected.map(|t| iformat!("{}", t as &dyn Show));
46        Expected::Token(expected, found)
47    }
48
49    pub fn eof(found: Option<Token>) -> Self {
50        Expected::Eof(found)
51    }
52}
53
54impl<Token, Slice> Expected<Token, Slice> {
55    pub fn slice<S: Show>(expected: Option<&S>, found: Option<Slice>) -> Self {
56        let expected = expected.map(|t| iformat!("{}", t as &dyn Show));
57        Expected::Slice(expected, found)
58    }
59}
60
61impl<Token, Slice> Expected<Token, Slice> {
62    pub fn map<FT, FS, T, S>(self, t: FT, s: FS) -> Expected<T, S>
63        where FT: Fn(Token) -> T, FS: Fn(Slice) -> S
64    {
65        use Expected::*;
66
67        match self {
68            Token(e, v) => Token(e, v.map(t)),
69            Slice(e, v) => Slice(e, v.map(s)),
70            Eof(v) => Eof(v.map(t)),
71            Other(v) => Other(v),
72            Expected::Elided => Expected::Elided,
73        }
74    }
75}
76
77impl<T: ToOwned, S: ?Sized + ToOwned> Expected<T, &S> {
78    pub fn into_owned(self) -> Expected<T::Owned, S::Owned> {
79        self.map(|t| t.to_owned(), |s| s.to_owned())
80    }
81}
82
83impl<T, S> From<String> for Expected<T, S> {
84    #[inline(always)]
85    fn from(string: String) -> Expected<T, S> {
86        Expected::Other(CowInlineString::Inline(InlinableString::from(string)))
87    }
88}
89
90#[doc(hidden)]
91impl<T, S> From<InlinableString> for Expected<T, S> {
92    #[inline(always)]
93    fn from(string: InlinableString) -> Expected<T, S> {
94        Expected::Other(CowInlineString::Inline(string))
95    }
96}
97
98impl<T, S> From<&'static str> for Expected<T, S> {
99    #[inline(always)]
100    fn from(string: &'static str) -> Expected<T, S> {
101        Expected::Other(CowInlineString::Borrowed(string))
102    }
103}
104
105impl<T: fmt::Debug, S: fmt::Debug> fmt::Debug for Expected<T, S> {
106    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107        match self {
108            Expected::Token(e, v) => {
109                f.debug_tuple("Expected::Token").field(&e).field(&v).finish()
110            }
111            Expected::Slice(e, v) => {
112                f.debug_tuple("Expected::Slice").field(&e).field(&v).finish()
113            }
114            Expected::Eof(v) => {
115                f.debug_tuple("Expected::Eof").field(&v).finish()
116            }
117            Expected::Other(v) => {
118                f.debug_tuple("Expected::Other").field(&v).finish()
119            }
120            Expected::Elided => f.debug_tuple("Expected::Elided").finish()
121        }
122    }
123}
124
125impl<T: Clone, S: Clone> Clone for Expected<T, S> {
126    fn clone(&self) -> Self {
127        match self {
128            Expected::Token(e, f) => Expected::Token(e.clone(), f.clone()),
129            Expected::Slice(e, f) => Expected::Slice(e.clone(), f.clone()),
130            Expected::Eof(f) => Expected::Eof(f.clone()),
131            Expected::Other(v) => Expected::Other(v.clone()),
132            Expected::Elided => Expected::Elided,
133        }
134    }
135}
136
137impl<T: Show, S: Show> fmt::Display for Expected<T, S> {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        match *self {
140            Expected::Token(Some(ref expected), Some(ref found)) => {
141                let found = found as &dyn Show;
142                write!(f, "expected token {} but found {}", expected, found)
143            }
144            Expected::Token(None, Some(ref found)) => {
145                let found = found as &dyn Show;
146                write!(f, "unexpected token: {}", found)
147            }
148            Expected::Token(Some(ref expected), None) => {
149                write!(f, "unexpected EOF: expected token {}", expected)
150            }
151            Expected::Token(None, None) => {
152                write!(f, "unexpected EOF: expected some token")
153            }
154            Expected::Slice(Some(ref expected), Some(ref found)) => {
155                let found = found as &dyn Show;
156                write!(f, "expected slice {} but found {}", expected, found)
157            }
158            Expected::Slice(None, Some(ref found)) => {
159                let found = found as &dyn Show;
160                write!(f, "unexpected slice: {}", found)
161            }
162            Expected::Slice(Some(ref expected), None) => {
163                write!(f, "unexpected EOF: expected slice {}", expected)
164            }
165            Expected::Slice(None, None) => {
166                write!(f, "unexpected EOF: expected some slice")
167            }
168            Expected::Eof(None) => {
169                write!(f, "expected EOF but input remains")
170            }
171            Expected::Eof(Some(ref found)) => {
172                let found = found as &dyn Show;
173                write!(f, "unexpected token {}", found)
174            }
175            Expected::Other(ref other) => write!(f, "{}", other),
176            Expected::Elided => write!(f, "[ERROR ELIDED]")
177        }
178    }
179}
180
181#[cfg(test)]
182mod tests {
183    use super::Expected;
184
185    #[test]
186    fn test_into_owned() {
187        let expected: Expected<char, &str> = Expected::Slice(None, Some("hi"));
188        let _owned: Expected<char, String> = expected.into_owned();
189    }
190}