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}