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}