factorion_lib/
locale.rs

1#![doc = include_str!("../Locales.md")]
2use std::{borrow::Cow, collections::HashMap};
3
4#[cfg(any(feature = "serde", test))]
5use serde::{Deserialize, Serialize};
6
7#[cfg(any(feature = "serde", test))]
8pub fn get_en() -> Locale<'static> {
9    serde_json::de::from_str(include_str!("en.json")).unwrap()
10}
11#[cfg(any(feature = "serde", test))]
12pub fn get_de() -> Locale<'static> {
13    serde_json::de::from_str(include_str!("de.json")).unwrap()
14}
15#[cfg(any(feature = "serde", test))]
16pub fn get_ru() -> Locale<'static> {
17    serde_json::de::from_str(include_str!("ru.json")).unwrap()
18}
19#[cfg(any(feature = "serde", test))]
20pub fn get_it() -> Locale<'static> {
21    serde_json::de::from_str(include_str!("it.json")).unwrap()
22}
23#[cfg(any(feature = "serde", test))]
24pub fn get_all() -> [(&'static str, Locale<'static>); 4] {
25    [
26        ("en", get_en()),
27        ("de", get_de()),
28        ("ru", get_ru()),
29        ("it", get_it()),
30    ]
31}
32
33/// This can be used to retroactively add fields, that exist in all versions.
34macro_rules! get_field {
35    ($t:ty; $($var:ident),*; $field:ident: $ret:ty) => {
36        impl<'a> $t {
37            pub fn $field(&'a self) -> &'a $ret {
38                match self {
39                    $(Self::$var(this) => &this.$field),*
40                }
41            }
42        }
43    };
44}
45macro_rules! set_field {
46    ($t:ty; $($var:ident),*; $field:ident: $ret:ty) => {
47        concat_idents::concat_idents!(set_fn = set_, $field {
48            impl<'a> $t {
49                pub fn set_fn(&mut self, v: $ret) {
50                    match self {
51                        $(Self::$var(this) => this.$field = v),*
52                    }
53                }
54            }
55        });
56    };
57}
58/// This can be used to retroactively add fields, that may not exist in older versions. (currently unused)
59macro_rules! maybe_get_field {
60    ($t:ty; $($var_not:ident),*; $($var_do:ident),*; $field:ident: $ret:ty) => {
61        impl<'a> $t {
62            pub fn $field(&'a self) -> Option<&'a $ret> {
63                match self {
64                    $(Self::$var_do(this) => Some(&this.$field),)*
65                    $(Self::$var_not(_) => None,)*
66                }
67            }
68        }
69    };
70}
71macro_rules! maybe_set_field {
72    ($t:ty; $($var_not:ident),*; $($var_do:ident),*; $field:ident: $ret:ty) => {
73        concat_idents::concat_idents!(set_fn = set_, $field {
74            impl<'a> $t {
75                pub fn set_fn(&mut self, v: $ret) -> bool {
76                    match self {
77                        $(Self::$var_do(this) => {this.$field = v; true})*
78                        $(Self::$var_not(_) => false),*
79                    }
80                }
81            }
82        });
83    };
84}
85
86/// Versioned total locale
87///
88/// Use the getter methods to (maybe) access the fields or setters to (maybe) override them
89#[derive(Debug, Clone)]
90#[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
91#[non_exhaustive]
92pub enum Locale<'a> {
93    V1(v1::Locale<'a>),
94    V2(v2::Locale<'a>),
95}
96get_field!(Locale<'a>; V1, V2; bot_disclaimer: Cow<'a, str> );
97set_field!(Locale<'a>; V1, V2; bot_disclaimer: Cow<'a, str> );
98impl<'a> Locale<'a> {
99    pub fn notes(&'a self) -> Notes<'a> {
100        match self {
101            Self::V1(this) => Notes::V1(&this.notes),
102            Self::V2(this) => Notes::V2(&this.notes),
103        }
104    }
105    pub fn notes_mut(&'a mut self) -> NotesMut<'a> {
106        match self {
107            Self::V1(this) => NotesMut::V1(&mut this.notes),
108            Self::V2(this) => NotesMut::V2(&mut this.notes),
109        }
110    }
111    pub fn format(&'a self) -> Format<'a> {
112        match self {
113            Self::V1(this) => Format::V1(&this.format),
114            Self::V2(this) => Format::V1(&this.format),
115        }
116    }
117    pub fn format_mut(&'a mut self) -> FormatMut<'a> {
118        match self {
119            Self::V1(this) => FormatMut::V1(&mut this.format),
120            Self::V2(this) => FormatMut::V1(&mut this.format),
121        }
122    }
123}
124/// Versioned locale just for the notes at the beginning of posts
125///
126/// Use the getter methods to (maybe) access fields
127#[derive(Debug, Clone)]
128#[non_exhaustive]
129pub enum Notes<'a> {
130    V1(&'a v1::Notes<'a>),
131    V2(&'a v2::Notes<'a>),
132}
133get_field!(Notes<'a>; V1, V2; tower: Cow<'a, str>);
134get_field!(Notes<'a>; V1, V2; tower_mult: Cow<'a, str>);
135get_field!(Notes<'a>; V1, V2; digits: Cow<'a, str>);
136get_field!(Notes<'a>; V1, V2; digits_mult: Cow<'a, str>);
137get_field!(Notes<'a>; V1, V2; approx: Cow<'a, str>);
138get_field!(Notes<'a>; V1, V2; approx_mult: Cow<'a, str>);
139get_field!(Notes<'a>; V1, V2; round: Cow<'a, str>);
140get_field!(Notes<'a>; V1, V2; round_mult: Cow<'a, str>);
141get_field!(Notes<'a>; V1, V2; too_big: Cow<'a, str>);
142get_field!(Notes<'a>; V1, V2; too_big_mult: Cow<'a, str>);
143get_field!(Notes<'a>; V1, V2; remove: Cow<'a, str>);
144get_field!(Notes<'a>; V1, V2; tetration: Cow<'a, str>);
145get_field!(Notes<'a>; V1, V2; no_post: Cow<'a, str>);
146get_field!(Notes<'a>; V1, V2; mention: Cow<'a, str>);
147maybe_get_field!(Notes<'a>; V1; V2; limit_hit: Cow<'a, str>);
148/// Versioned locale for the notes at the beginning of posts
149///
150/// Use the setter methods to (possibly) override them
151#[derive(Debug)]
152#[non_exhaustive]
153pub enum NotesMut<'a> {
154    V1(&'a mut v1::Notes<'a>),
155    V2(&'a mut v2::Notes<'a>),
156}
157set_field!(NotesMut<'a>; V1, V2; tower: Cow<'a, str>);
158set_field!(NotesMut<'a>; V1, V2; tower_mult: Cow<'a, str>);
159set_field!(NotesMut<'a>; V1, V2; digits: Cow<'a, str>);
160set_field!(NotesMut<'a>; V1, V2; digits_mult: Cow<'a, str>);
161set_field!(NotesMut<'a>; V1, V2; approx: Cow<'a, str>);
162set_field!(NotesMut<'a>; V1, V2; approx_mult: Cow<'a, str>);
163set_field!(NotesMut<'a>; V1, V2; round: Cow<'a, str>);
164set_field!(NotesMut<'a>; V1, V2; round_mult: Cow<'a, str>);
165set_field!(NotesMut<'a>; V1, V2; too_big: Cow<'a, str>);
166set_field!(NotesMut<'a>; V1, V2; too_big_mult: Cow<'a, str>);
167set_field!(NotesMut<'a>; V1, V2; remove: Cow<'a, str>);
168set_field!(NotesMut<'a>; V1, V2; tetration: Cow<'a, str>);
169set_field!(NotesMut<'a>; V1, V2; no_post: Cow<'a, str>);
170set_field!(NotesMut<'a>; V1, V2; mention: Cow<'a, str>);
171maybe_set_field!(NotesMut<'a>; V1; V2; limit_hit: Cow<'a, str>);
172/// Versioned locale for the formatting of individual calculations
173///
174/// Use the getter methods to (maybe) access fields
175#[derive(Debug, Clone)]
176#[non_exhaustive]
177pub enum Format<'a> {
178    V1(&'a v1::Format<'a>),
179}
180get_field!(Format<'a>; V1; capitalize_calc: bool);
181get_field!(Format<'a>; V1; termial: Cow<'a, str>);
182get_field!(Format<'a>; V1; factorial: Cow<'a, str>);
183get_field!(Format<'a>; V1; uple: Cow<'a, str>);
184get_field!(Format<'a>; V1; sub: Cow<'a, str>);
185get_field!(Format<'a>; V1; negative: Cow<'a, str>);
186get_field!(Format<'a>; V1; num_overrides: HashMap<i32, Cow<'a, str>>);
187get_field!(Format<'a>; V1; force_num: bool);
188get_field!(Format<'a>; V1; nest: Cow<'a, str>);
189get_field!(Format<'a>; V1; rough_number: Cow<'a, str>);
190get_field!(Format<'a>; V1; exact: Cow<'a, str>);
191get_field!(Format<'a>; V1; rough: Cow<'a, str>);
192get_field!(Format<'a>; V1; approx: Cow<'a, str>);
193get_field!(Format<'a>; V1; digits: Cow<'a, str>);
194get_field!(Format<'a>; V1; order: Cow<'a, str>);
195get_field!(Format<'a>; V1; all_that: Cow<'a, str>);
196impl<'a> Format<'a> {
197    pub fn number_format(&'a self) -> NumFormat<'a> {
198        match self {
199            Self::V1(this) => NumFormat::V1(&this.number_format),
200        }
201    }
202}
203/// Versioned locale for the formatting of individual calculations
204///
205/// Use the setter methods to (possibly) override them
206#[derive(Debug)]
207#[non_exhaustive]
208pub enum FormatMut<'a> {
209    V1(&'a mut v1::Format<'a>),
210}
211set_field!(FormatMut<'a>; V1; capitalize_calc: bool);
212set_field!(FormatMut<'a>; V1; termial: Cow<'a, str>);
213set_field!(FormatMut<'a>; V1; factorial: Cow<'a, str>);
214set_field!(FormatMut<'a>; V1; uple: Cow<'a, str>);
215set_field!(FormatMut<'a>; V1; sub: Cow<'a, str>);
216set_field!(FormatMut<'a>; V1; negative: Cow<'a, str>);
217set_field!(FormatMut<'a>; V1; num_overrides: HashMap<i32, Cow<'a, str>>);
218set_field!(FormatMut<'a>; V1; force_num: bool);
219set_field!(FormatMut<'a>; V1; nest: Cow<'a, str>);
220set_field!(FormatMut<'a>; V1; rough_number: Cow<'a, str>);
221set_field!(FormatMut<'a>; V1; exact: Cow<'a, str>);
222set_field!(FormatMut<'a>; V1; rough: Cow<'a, str>);
223set_field!(FormatMut<'a>; V1; approx: Cow<'a, str>);
224set_field!(FormatMut<'a>; V1; digits: Cow<'a, str>);
225set_field!(FormatMut<'a>; V1; order: Cow<'a, str>);
226set_field!(FormatMut<'a>; V1; all_that: Cow<'a, str>);
227impl<'a> FormatMut<'a> {
228    pub fn number_format_mut(&'a mut self) -> NumFormatMut<'a> {
229        match self {
230            Self::V1(this) => NumFormatMut::V1(&mut this.number_format),
231        }
232    }
233}
234/// Versioned locale for how numbers are formatted
235///
236/// Use the getter methods to (maybe) access fields
237#[derive(Debug, Clone)]
238#[non_exhaustive]
239pub enum NumFormat<'a> {
240    V1(&'a v1::NumFormat),
241}
242get_field!(NumFormat<'a>; V1; decimal: char);
243/// Versioned locale for how numbers are formatted
244///
245/// Use the setter methods to (possibly) override them
246#[derive(Debug)]
247#[non_exhaustive]
248pub enum NumFormatMut<'a> {
249    V1(&'a mut v1::NumFormat),
250}
251get_field!(NumFormatMut<'a>; V1; decimal: char);
252
253/// v1 of locales
254pub mod v1 {
255    #[cfg(any(feature = "serde", test))]
256    use serde::{Deserialize, Serialize};
257    use std::{borrow::Cow, collections::HashMap};
258
259    #[derive(Debug, Clone)]
260    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
261    pub struct Locale<'a> {
262        pub bot_disclaimer: Cow<'a, str>,
263        pub notes: Notes<'a>,
264        pub format: Format<'a>,
265    }
266
267    #[derive(Debug, Clone)]
268    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
269    pub struct Notes<'a> {
270        pub tower: Cow<'a, str>,
271        pub tower_mult: Cow<'a, str>,
272        pub digits: Cow<'a, str>,
273        pub digits_mult: Cow<'a, str>,
274        pub approx: Cow<'a, str>,
275        pub approx_mult: Cow<'a, str>,
276        pub round: Cow<'a, str>,
277        pub round_mult: Cow<'a, str>,
278        pub too_big: Cow<'a, str>,
279        pub too_big_mult: Cow<'a, str>,
280        pub remove: Cow<'a, str>,
281        pub tetration: Cow<'a, str>,
282        pub no_post: Cow<'a, str>,
283        pub mention: Cow<'a, str>,
284    }
285
286    #[derive(Debug, Clone)]
287    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
288    pub struct Format<'a> {
289        pub capitalize_calc: bool,
290        pub termial: Cow<'a, str>,
291        pub factorial: Cow<'a, str>,
292        pub uple: Cow<'a, str>,
293        pub sub: Cow<'a, str>,
294        pub negative: Cow<'a, str>,
295        pub num_overrides: HashMap<i32, Cow<'a, str>>,
296        pub force_num: bool,
297        pub nest: Cow<'a, str>,
298        pub rough_number: Cow<'a, str>,
299        pub exact: Cow<'a, str>,
300        pub rough: Cow<'a, str>,
301        pub approx: Cow<'a, str>,
302        pub digits: Cow<'a, str>,
303        pub order: Cow<'a, str>,
304        pub all_that: Cow<'a, str>,
305        pub number_format: NumFormat,
306    }
307
308    #[derive(Debug, Clone)]
309    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
310    pub struct NumFormat {
311        pub decimal: char,
312    }
313}
314/// v1 of locales
315pub mod v2 {
316    #[cfg(any(feature = "serde", test))]
317    use serde::{Deserialize, Serialize};
318    use std::borrow::Cow;
319
320    #[derive(Debug, Clone)]
321    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
322    pub struct Locale<'a> {
323        pub bot_disclaimer: Cow<'a, str>,
324        pub notes: Notes<'a>,
325        pub format: super::v1::Format<'a>,
326    }
327
328    #[derive(Debug, Clone)]
329    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
330    pub struct Notes<'a> {
331        pub tower: Cow<'a, str>,
332        pub tower_mult: Cow<'a, str>,
333        pub digits: Cow<'a, str>,
334        pub digits_mult: Cow<'a, str>,
335        pub approx: Cow<'a, str>,
336        pub approx_mult: Cow<'a, str>,
337        pub round: Cow<'a, str>,
338        pub round_mult: Cow<'a, str>,
339        pub too_big: Cow<'a, str>,
340        pub too_big_mult: Cow<'a, str>,
341        pub remove: Cow<'a, str>,
342        pub tetration: Cow<'a, str>,
343        pub no_post: Cow<'a, str>,
344        pub mention: Cow<'a, str>,
345        pub limit_hit: Cow<'a, str>,
346    }
347}