1use fluent_syntax::ast::InlineExpression;
2use 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)]
8pub 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
25impl<T> From<&InlineExpression<T>> for ReferenceKind
26where
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)]
53pub enum ResolverError {
54 Reference(ReferenceKind),
55 NoValue(String),
56 MissingDefault,
57 Cyclic,
58 TooManyPlaceables,
59}
60
61impl 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
92impl<T> From<&InlineExpression<T>> for ResolverError
93where
94 T: ToString,
95{
96 fn from(exp: &InlineExpression<T>) -> Self {
97 Self::Reference(exp.into())
98 }
99}
100
101impl Error for ResolverError {}
102