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