Skip to main content

ferrocat_icu/
ast.rs

1/// Parsed ICU message.
2#[derive(Debug, Clone, PartialEq, Eq, Default)]
3pub struct IcuMessage {
4    /// Top-level AST nodes in source order.
5    pub nodes: Vec<IcuNode>,
6}
7
8/// Distinguishes cardinal and ordinal plural forms.
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
10pub enum IcuPluralKind {
11    /// Cardinal plural categories such as `one` and `other`.
12    Cardinal,
13    /// Ordinal plural categories such as `one`, `two`, `few`, and `other`.
14    Ordinal,
15}
16
17/// A selector branch inside a plural or select expression.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct IcuOption {
20    /// Raw selector label such as `one`, `other`, or `=0`.
21    pub selector: String,
22    /// Nested nodes rendered when the selector matches.
23    pub value: Vec<IcuNode>,
24}
25
26/// AST node emitted by the ICU parser.
27///
28/// This enum is non-exhaustive so additional ICU formatters or syntax nodes can
29/// be added without forcing downstream callers to rewrite every `match`.
30#[derive(Debug, Clone, PartialEq, Eq)]
31#[non_exhaustive]
32pub enum IcuNode {
33    /// Literal text content.
34    Literal(String),
35    /// Simple argument substitution such as `{name}`.
36    Argument {
37        /// Argument identifier.
38        name: String,
39    },
40    /// Number formatter such as `{count, number}`.
41    Number {
42        /// Argument identifier.
43        name: String,
44        /// Optional formatter style segment.
45        style: Option<String>,
46    },
47    /// Date formatter such as `{createdAt, date, short}`.
48    Date {
49        /// Argument identifier.
50        name: String,
51        /// Optional formatter style segment.
52        style: Option<String>,
53    },
54    /// Time formatter such as `{createdAt, time, short}`.
55    Time {
56        /// Argument identifier.
57        name: String,
58        /// Optional formatter style segment.
59        style: Option<String>,
60    },
61    /// List formatter such as `{items, list}`.
62    List {
63        /// Argument identifier.
64        name: String,
65        /// Optional formatter style segment.
66        style: Option<String>,
67    },
68    /// Duration formatter such as `{elapsed, duration}`.
69    Duration {
70        /// Argument identifier.
71        name: String,
72        /// Optional formatter style segment.
73        style: Option<String>,
74    },
75    /// Relative-time "ago" formatter.
76    Ago {
77        /// Argument identifier.
78        name: String,
79        /// Optional formatter style segment.
80        style: Option<String>,
81    },
82    /// Name formatter.
83    Name {
84        /// Argument identifier.
85        name: String,
86        /// Optional formatter style segment.
87        style: Option<String>,
88    },
89    /// Select expression with labeled branches.
90    Select {
91        /// Argument identifier.
92        name: String,
93        /// Available selector branches.
94        options: Vec<IcuOption>,
95    },
96    /// Cardinal or ordinal plural expression.
97    Plural {
98        /// Argument identifier.
99        name: String,
100        /// Whether the plural expression is cardinal or ordinal.
101        kind: IcuPluralKind,
102        /// Parsed plural offset value.
103        offset: u32,
104        /// Available plural branches.
105        options: Vec<IcuOption>,
106    },
107    /// `#` placeholder inside plural branches.
108    Pound,
109    /// Rich-text style tag with nested children.
110    Tag {
111        /// Tag name without angle brackets.
112        name: String,
113        /// Nested child nodes inside the tag body.
114        ///
115        /// A self-closing tag (`<name/>`) is represented as an empty `children`
116        /// vector; the serializer renders any empty tag in the compact
117        /// `<name/>` form.
118        children: Vec<Self>,
119    },
120}