1use std::collections::BTreeSet;
5use std::fmt;
6use std::mem;
7use std::sync::Arc;
8
9use move_core_types::annotated_visitor as AV;
10use move_core_types::language_storage::TypeTag;
11use sui_types::object::option_visitor as OV;
12use sui_types::object::rpc_visitor as RV;
13
14use crate::v2::lexer::Lexeme;
15use crate::v2::lexer::OwnedLexeme;
16use crate::v2::lexer::Token;
17use crate::v2::peek::Peekable2Ext;
18
19#[derive(thiserror::Error, Debug)]
24pub enum Error {
25 #[error("Duplicate name {0:?}")]
26 NameDuplicate(String),
27
28 #[error("Name pattern {0:?} produced no output")]
29 NameEmpty(String),
30
31 #[error("Name pattern {0:?} did not evaluate to a string")]
32 NameInvalid(String),
33
34 #[error("Error evaluating name pattern {0:?}: {1}")]
35 NameEvaluation(String, FormatError),
36
37 #[error("Display contains too many elements")]
38 TooBig,
39
40 #[error("Display tries to load too many objects")]
41 TooManyLoads,
42
43 #[error("Display produces too much output")]
44 TooMuchOutput,
45}
46
47#[derive(thiserror::Error, Debug, Clone)]
49pub enum FormatError {
50 #[error("BCS error: {0}")]
51 Bcs(#[from] bcs::Error),
52
53 #[error("Hex {0} contains invalid character")]
54 InvalidHexCharacter(OwnedLexeme),
55
56 #[error("Invalid {0}")]
57 InvalidIdentifier(OwnedLexeme),
58
59 #[error("Invalid {what} at byte offset {offset}: {err}")]
60 InvalidNumber {
61 what: &'static str,
62 offset: usize,
63 err: String,
64 },
65
66 #[error("Odd number of characters in hex {0}")]
67 OddHexLiteral(OwnedLexeme),
68
69 #[error("Storage error: {0}")]
70 Store(Arc<anyhow::Error>),
71
72 #[error("Display contains too many elements")]
73 TooBig,
74
75 #[error("Format is nested too deeply")]
76 TooDeep,
77
78 #[error("Display tries to load too many objects")]
79 TooManyLoads,
80
81 #[error("Display produces too much output")]
82 TooMuchOutput,
83
84 #[error("Invalid transform: {0}")]
85 TransformInvalid(&'static str),
86
87 #[error("Invalid transform for expression at byte offset {offset}: {reason}")]
89 TransformInvalid_ { offset: usize, reason: &'static str },
90
91 #[error("Unexpected end-of-string, expected {expect}")]
92 UnexpectedEos { expect: ExpectedSet },
93
94 #[error("Unexpected {0}, expected end-of-string")]
95 UnexpectedRemaining(OwnedLexeme),
96
97 #[error("Unexpected {actual}, expected {expect}")]
98 UnexpectedToken {
99 actual: OwnedLexeme,
100 expect: ExpectedSet,
101 },
102
103 #[error("Vector at byte offset {offset} requires 1 type parameter, found {arity}")]
104 VectorArity { offset: usize, arity: usize },
105
106 #[error("Internal error: vector without element type")]
107 VectorNoType,
108
109 #[error(
110 "Vector at byte offset {offset}, could have element type {} or {}",
111 .this.to_canonical_display(true),
112 .that.to_canonical_display(true),
113 )]
114 VectorTypeMismatch {
115 offset: usize,
116 this: TypeTag,
117 that: TypeTag,
118 },
119
120 #[error("Deserialization error: {0}")]
121 Visitor(#[from] AV::Error),
122}
123
124#[derive(Debug, Clone)]
128pub struct ExpectedSet {
129 prev: Vec<ExpectedSet>,
131
132 tried: &'static [Expected],
134}
135
136#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
137pub(crate) enum Expected {
138 Literal(&'static str),
140 Token(Token),
142}
143
144#[derive(Clone)]
147pub(crate) enum Match<T> {
148 Found(T),
149 Tried(Option<usize>, ExpectedSet),
150}
151
152impl Error {
153 pub fn is_internal_error(&self) -> bool {
155 matches!(self, Self::NameEvaluation(_, e) if e.is_internal_error())
156 }
157
158 pub fn is_resource_limit_error(&self) -> bool {
160 matches!(self, Self::NameEvaluation(_, e) if e.is_resource_limit_error())
161 || matches!(
162 self,
163 Self::TooBig | Self::TooManyLoads | Self::TooMuchOutput
164 )
165 }
166}
167
168impl FormatError {
169 pub fn is_internal_error(&self) -> bool {
171 matches!(self, Self::Bcs(_) | Self::Store(_) | Self::Visitor(_))
172 }
173
174 pub fn is_resource_limit_error(&self) -> bool {
176 matches!(
177 self,
178 Self::TooBig | Self::TooDeep | Self::TooManyLoads | Self::TooMuchOutput
179 )
180 }
181
182 pub(crate) fn for_expr_at_offset(self, offset: usize) -> Self {
184 match self {
185 FormatError::TransformInvalid(reason) => {
186 FormatError::TransformInvalid_ { offset, reason }
187 }
188 error => error,
189 }
190 }
191
192 pub(crate) fn also_tried(self, offset: Option<usize>, tried: ExpectedSet) -> Self {
195 match (offset, self) {
196 (Some(offset), FormatError::UnexpectedToken { actual, expect })
197 if offset == actual.2 =>
198 {
199 FormatError::UnexpectedToken {
200 actual,
201 expect: expect.union(tried),
202 }
203 }
204
205 (None, FormatError::UnexpectedEos { expect }) => FormatError::UnexpectedEos {
206 expect: expect.union(tried),
207 },
208
209 (_, error) => error,
210 }
211 }
212}
213
214impl ExpectedSet {
215 pub(crate) fn new(tried: &'static [Expected]) -> Self {
216 Self {
217 prev: vec![],
218 tried,
219 }
220 }
221
222 pub(crate) fn with_prev(mut self, prev: ExpectedSet) -> Self {
223 self.prev.push(prev);
224 self
225 }
226
227 pub(crate) fn union(mut self, mut other: ExpectedSet) -> Self {
228 if self.prev.len() < other.prev.len() {
232 mem::swap(&mut self, &mut other);
233 }
234
235 self.prev.append(&mut other.prev);
236 self.prev.push(other);
237 self
238 }
239
240 pub(crate) fn into_error(self, actual: Option<&Lexeme<'_>>) -> FormatError {
241 if let Some(actual) = actual {
242 FormatError::UnexpectedToken {
243 actual: actual.detach(),
244 expect: self,
245 }
246 } else {
247 FormatError::UnexpectedEos { expect: self }
248 }
249 }
250}
251
252impl<T> Match<T> {
253 pub(crate) fn is_not_found(&self) -> bool {
254 matches!(self, Match::Tried(_, _))
255 }
256}
257
258impl fmt::Display for Expected {
259 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260 match self {
261 Expected::Token(token) => write!(f, "{token}"),
262 Expected::Literal(s) => write!(f, "'{s}'"),
263 }
264 }
265}
266
267impl fmt::Display for ExpectedSet {
268 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
269 let mut expected = BTreeSet::new();
271 let mut stack = vec![self];
272 while let Some(set) = stack.pop() {
273 expected.extend(set.tried);
274 stack.extend(&set.prev);
275 }
276
277 if expected.is_empty() {
278 return write!(f, "nothing");
279 }
280
281 let mut tokens = expected.into_iter().peekable2();
282 let mut prefix = if tokens.peek2().is_some() {
283 "one of "
284 } else {
285 ""
286 };
287
288 while let Some(token) = tokens.next() {
289 write!(f, "{prefix}{token}")?;
290 prefix = if tokens.peek2().is_some() {
291 ", "
292 } else {
293 ", or "
294 };
295 }
296
297 Ok(())
298 }
299}
300
301impl From<RV::Error> for FormatError {
302 fn from(error: RV::Error) -> Self {
303 match error {
304 RV::Error::Visitor(err) => err.into(),
305 RV::Error::Option(err) => err.into(),
306 RV::Error::Meter(err) => err.into(),
307 RV::Error::UnexpectedType => {
308 FormatError::Bcs(bcs::Error::Custom("unexpected type".to_string()))
309 }
310 }
311 }
312}
313
314impl From<RV::MeterError> for FormatError {
315 fn from(error: RV::MeterError) -> Self {
316 match error {
317 RV::MeterError::TooBig => FormatError::TooBig,
318 RV::MeterError::TooDeep => FormatError::TooDeep,
319 }
320 }
321}
322
323impl From<OV::Error> for FormatError {
324 fn from(OV::Error: OV::Error) -> Self {
325 FormatError::Bcs(bcs::Error::ExpectedOption)
326 }
327}
328
329impl From<std::fmt::Error> for FormatError {
330 fn from(_: std::fmt::Error) -> Self {
331 FormatError::TooMuchOutput
332 }
333}