1 | use fluent_syntax::ast::InlineExpression; |
2 | use std::error::Error; |
3 | |
4 | /// Maps an [`InlineExpression`] into the kind of reference, with owned strings |
5 | /// that identify the expression. This makes it so that the [`InlineExpression`] can |
6 | /// be used to generate an error string. |
7 | #[derive (Debug, PartialEq, Eq, Clone)] |
8 | pub enum ReferenceKind { |
9 | Function { |
10 | id: String, |
11 | }, |
12 | Message { |
13 | id: String, |
14 | attribute: Option<String>, |
15 | }, |
16 | Term { |
17 | id: String, |
18 | attribute: Option<String>, |
19 | }, |
20 | Variable { |
21 | id: String, |
22 | }, |
23 | } |
24 | |
25 | impl<T> From<&InlineExpression<T>> for ReferenceKind |
26 | where |
27 | T: ToString, |
28 | { |
29 | fn from(exp: &InlineExpression<T>) -> Self { |
30 | match exp { |
31 | InlineExpression::FunctionReference { id: &Identifier, .. } => Self::Function { |
32 | id: id.name.to_string(), |
33 | }, |
34 | InlineExpression::MessageReference { id: &Identifier, attribute: &Option> } => Self::Message { |
35 | id: id.name.to_string(), |
36 | attribute: attribute.as_ref().map(|i: &Identifier| i.name.to_string()), |
37 | }, |
38 | InlineExpression::TermReference { id: &Identifier, attribute: &Option>, .. } => Self::Term { |
39 | id: id.name.to_string(), |
40 | attribute: attribute.as_ref().map(|i: &Identifier| i.name.to_string()), |
41 | }, |
42 | InlineExpression::VariableReference { id: &Identifier, .. } => Self::Variable { |
43 | id: id.name.to_string(), |
44 | }, |
45 | _ => unreachable!(), |
46 | } |
47 | } |
48 | } |
49 | |
50 | /// Errors generated during the process of resolving a fluent message into a string. |
51 | /// This process takes place in the `write` method of the `WriteValue` trait. |
52 | #[derive (Debug, PartialEq, Eq, Clone)] |
53 | pub enum ResolverError { |
54 | Reference(ReferenceKind), |
55 | NoValue(String), |
56 | MissingDefault, |
57 | Cyclic, |
58 | TooManyPlaceables, |
59 | } |
60 | |
61 | impl std::fmt::Display for ResolverError { |
62 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
63 | match self { |
64 | Self::Reference(exp) => match exp { |
65 | ReferenceKind::Function { id } => write!(f, "Unknown function: {}()" , id), |
66 | ReferenceKind::Message { |
67 | id, |
68 | attribute: None, |
69 | } => write!(f, "Unknown message: {}" , id), |
70 | ReferenceKind::Message { |
71 | id, |
72 | attribute: Some(attribute), |
73 | } => write!(f, "Unknown attribute: {}. {}" , id, attribute), |
74 | ReferenceKind::Term { |
75 | id, |
76 | attribute: None, |
77 | } => write!(f, "Unknown term: - {}" , id), |
78 | ReferenceKind::Term { |
79 | id, |
80 | attribute: Some(attribute), |
81 | } => write!(f, "Unknown attribute: - {}. {}" , id, attribute), |
82 | ReferenceKind::Variable { id } => write!(f, "Unknown variable: $ {}" , id), |
83 | }, |
84 | Self::NoValue(id) => write!(f, "No value: {}" , id), |
85 | Self::MissingDefault => f.write_str("No default" ), |
86 | Self::Cyclic => f.write_str("Cyclical dependency detected" ), |
87 | Self::TooManyPlaceables => f.write_str("Too many placeables" ), |
88 | } |
89 | } |
90 | } |
91 | |
92 | impl<T> From<&InlineExpression<T>> for ResolverError |
93 | where |
94 | T: ToString, |
95 | { |
96 | fn from(exp: &InlineExpression<T>) -> Self { |
97 | Self::Reference(exp.into()) |
98 | } |
99 | } |
100 | |
101 | impl Error for ResolverError {} |
102 | |