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)
51#[allow(unused_macros)]
52macro_rules! maybe_get_field {
53    ($t:ty; $($var_not:ident),*; $($var_do:ident),*; $field:ident: $ret:ty) => {
54        impl<'a> $t {
55            pub fn $field(&'a self) -> Option<&'a $ret> {
56                match self {
57                    $(Self::$var_do(this) => Some(&this.$field),)*
58                    $(Self::$var_not(_) => None,)*
59                }
60            }
61        }
62    };
63}
64#[allow(unused_macros)]
65macro_rules! maybe_set_field {
66    ($t:ty; $($var_not:ident),*; $($var_do:ident),*; $field:ident: $ret:ty) => {
67        concat_idents::concat_idents!(set_fn = set_, $field {
68            impl<'a> $t {
69                pub fn set_fn(&mut self, v: $ret) -> bool {
70                    match self {
71                        $(Self::$var_do(this) => {this.$field = v; true})*
72                        $(Self::$var_not(_) => false),*
73                    }
74                }
75            }
76        });
77    };
78}
79
80/// Versioned total locale
81///
82/// Use the getter methods to (maybe) access the fields or setters to (maybe) override them
83#[derive(Debug, Clone)]
84#[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
85pub enum Locale<'a> {
86    V1(v1::Locale<'a>),
87}
88get_field!(Locale<'a>; V1; bot_disclaimer: Cow<'a, str> );
89set_field!(Locale<'a>; V1; 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        }
95    }
96    pub fn notes_mut(&'a mut self) -> NotesMut<'a> {
97        match self {
98            Self::V1(this) => NotesMut::V1(&mut this.notes),
99        }
100    }
101    pub fn format(&'a self) -> Format<'a> {
102        match self {
103            Self::V1(this) => Format::V1(&this.format),
104        }
105    }
106    pub fn format_mut(&'a mut self) -> FormatMut<'a> {
107        match self {
108            Self::V1(this) => FormatMut::V1(&mut this.format),
109        }
110    }
111}
112/// Versioned locale just for the notes at the beginning of posts
113///
114/// Use the getter methods to (maybe) access fields
115#[derive(Debug, Clone)]
116pub enum Notes<'a> {
117    V1(&'a v1::Notes<'a>),
118}
119get_field!(Notes<'a>; V1; tower: Cow<'a, str>);
120get_field!(Notes<'a>; V1; tower_mult: Cow<'a, str>);
121get_field!(Notes<'a>; V1; digits: Cow<'a, str>);
122get_field!(Notes<'a>; V1; digits_mult: Cow<'a, str>);
123get_field!(Notes<'a>; V1; approx: Cow<'a, str>);
124get_field!(Notes<'a>; V1; approx_mult: Cow<'a, str>);
125get_field!(Notes<'a>; V1; round: Cow<'a, str>);
126get_field!(Notes<'a>; V1; round_mult: Cow<'a, str>);
127get_field!(Notes<'a>; V1; too_big: Cow<'a, str>);
128get_field!(Notes<'a>; V1; too_big_mult: Cow<'a, str>);
129get_field!(Notes<'a>; V1; remove: Cow<'a, str>);
130get_field!(Notes<'a>; V1; tetration: Cow<'a, str>);
131get_field!(Notes<'a>; V1; no_post: Cow<'a, str>);
132get_field!(Notes<'a>; V1; mention: Cow<'a, str>);
133/// Versioned locale for the notes at the beginning of posts
134///
135/// Use the setter methods to (possibly) override them
136#[derive(Debug)]
137pub enum NotesMut<'a> {
138    V1(&'a mut v1::Notes<'a>),
139}
140set_field!(NotesMut<'a>; V1; tower: Cow<'a, str>);
141set_field!(NotesMut<'a>; V1; tower_mult: Cow<'a, str>);
142set_field!(NotesMut<'a>; V1; digits: Cow<'a, str>);
143set_field!(NotesMut<'a>; V1; digits_mult: Cow<'a, str>);
144set_field!(NotesMut<'a>; V1; approx: Cow<'a, str>);
145set_field!(NotesMut<'a>; V1; approx_mult: Cow<'a, str>);
146set_field!(NotesMut<'a>; V1; round: Cow<'a, str>);
147set_field!(NotesMut<'a>; V1; round_mult: Cow<'a, str>);
148set_field!(NotesMut<'a>; V1; too_big: Cow<'a, str>);
149set_field!(NotesMut<'a>; V1; too_big_mult: Cow<'a, str>);
150set_field!(NotesMut<'a>; V1; remove: Cow<'a, str>);
151set_field!(NotesMut<'a>; V1; tetration: Cow<'a, str>);
152set_field!(NotesMut<'a>; V1; no_post: Cow<'a, str>);
153set_field!(NotesMut<'a>; V1; mention: Cow<'a, str>);
154/// Versioned locale for the formatting of individual calculations
155///
156/// Use the getter methods to (maybe) access fields
157#[derive(Debug, Clone)]
158pub enum Format<'a> {
159    V1(&'a v1::Format<'a>),
160}
161get_field!(Format<'a>; V1; capitalize_calc: bool);
162get_field!(Format<'a>; V1; termial: Cow<'a, str>);
163get_field!(Format<'a>; V1; factorial: Cow<'a, str>);
164get_field!(Format<'a>; V1; uple: Cow<'a, str>);
165get_field!(Format<'a>; V1; sub: Cow<'a, str>);
166get_field!(Format<'a>; V1; negative: Cow<'a, str>);
167get_field!(Format<'a>; V1; num_overrides: HashMap<i32, Cow<'a, str>>);
168get_field!(Format<'a>; V1; force_num: bool);
169get_field!(Format<'a>; V1; nest: Cow<'a, str>);
170get_field!(Format<'a>; V1; rough_number: Cow<'a, str>);
171get_field!(Format<'a>; V1; exact: Cow<'a, str>);
172get_field!(Format<'a>; V1; rough: Cow<'a, str>);
173get_field!(Format<'a>; V1; approx: Cow<'a, str>);
174get_field!(Format<'a>; V1; digits: Cow<'a, str>);
175get_field!(Format<'a>; V1; order: Cow<'a, str>);
176get_field!(Format<'a>; V1; all_that: Cow<'a, str>);
177impl<'a> Format<'a> {
178    pub fn number_format(&'a self) -> NumFormat<'a> {
179        match self {
180            Self::V1(this) => NumFormat::V1(&this.number_format),
181        }
182    }
183}
184/// Versioned locale for the formatting of individual calculations
185///
186/// Use the setter methods to (possibly) override them
187#[derive(Debug)]
188pub enum FormatMut<'a> {
189    V1(&'a mut v1::Format<'a>),
190}
191set_field!(FormatMut<'a>; V1; capitalize_calc: bool);
192set_field!(FormatMut<'a>; V1; termial: Cow<'a, str>);
193set_field!(FormatMut<'a>; V1; factorial: Cow<'a, str>);
194set_field!(FormatMut<'a>; V1; uple: Cow<'a, str>);
195set_field!(FormatMut<'a>; V1; sub: Cow<'a, str>);
196set_field!(FormatMut<'a>; V1; negative: Cow<'a, str>);
197set_field!(FormatMut<'a>; V1; num_overrides: HashMap<i32, Cow<'a, str>>);
198set_field!(FormatMut<'a>; V1; force_num: bool);
199set_field!(FormatMut<'a>; V1; nest: Cow<'a, str>);
200set_field!(FormatMut<'a>; V1; rough_number: Cow<'a, str>);
201set_field!(FormatMut<'a>; V1; exact: Cow<'a, str>);
202set_field!(FormatMut<'a>; V1; rough: Cow<'a, str>);
203set_field!(FormatMut<'a>; V1; approx: Cow<'a, str>);
204set_field!(FormatMut<'a>; V1; digits: Cow<'a, str>);
205set_field!(FormatMut<'a>; V1; order: Cow<'a, str>);
206set_field!(FormatMut<'a>; V1; all_that: Cow<'a, str>);
207impl<'a> FormatMut<'a> {
208    pub fn number_format_mut(&'a mut self) -> NumFormatMut<'a> {
209        match self {
210            Self::V1(this) => NumFormatMut::V1(&mut this.number_format),
211        }
212    }
213}
214/// Versioned locale for how numbers are formatted
215///
216/// Use the getter methods to (maybe) access fields
217#[derive(Debug, Clone)]
218pub enum NumFormat<'a> {
219    V1(&'a v1::NumFormat),
220}
221get_field!(NumFormat<'a>; V1; decimal: char);
222/// Versioned locale for how numbers are formatted
223///
224/// Use the setter methods to (possibly) override them
225#[derive(Debug)]
226pub enum NumFormatMut<'a> {
227    V1(&'a mut v1::NumFormat),
228}
229get_field!(NumFormatMut<'a>; V1; decimal: char);
230
231/// v1 of locales
232pub mod v1 {
233    #[cfg(any(feature = "serde", test))]
234    use serde::{Deserialize, Serialize};
235    use std::{borrow::Cow, collections::HashMap};
236
237    #[derive(Debug, Clone)]
238    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
239    pub struct Locale<'a> {
240        pub bot_disclaimer: Cow<'a, str>,
241        pub notes: Notes<'a>,
242        pub format: Format<'a>,
243    }
244
245    #[derive(Debug, Clone)]
246    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
247    pub struct Notes<'a> {
248        pub tower: Cow<'a, str>,
249        pub tower_mult: Cow<'a, str>,
250        pub digits: Cow<'a, str>,
251        pub digits_mult: Cow<'a, str>,
252        pub approx: Cow<'a, str>,
253        pub approx_mult: Cow<'a, str>,
254        pub round: Cow<'a, str>,
255        pub round_mult: Cow<'a, str>,
256        pub too_big: Cow<'a, str>,
257        pub too_big_mult: Cow<'a, str>,
258        pub remove: Cow<'a, str>,
259        pub tetration: Cow<'a, str>,
260        pub no_post: Cow<'a, str>,
261        pub mention: Cow<'a, str>,
262    }
263
264    #[derive(Debug, Clone)]
265    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
266    pub struct Format<'a> {
267        pub capitalize_calc: bool,
268        pub termial: Cow<'a, str>,
269        pub factorial: Cow<'a, str>,
270        pub uple: Cow<'a, str>,
271        pub sub: Cow<'a, str>,
272        pub negative: Cow<'a, str>,
273        pub num_overrides: HashMap<i32, Cow<'a, str>>,
274        pub force_num: bool,
275        pub nest: Cow<'a, str>,
276        pub rough_number: Cow<'a, str>,
277        pub exact: Cow<'a, str>,
278        pub rough: Cow<'a, str>,
279        pub approx: Cow<'a, str>,
280        pub digits: Cow<'a, str>,
281        pub order: Cow<'a, str>,
282        pub all_that: Cow<'a, str>,
283        pub number_format: NumFormat,
284    }
285
286    #[derive(Debug, Clone)]
287    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
288    pub struct NumFormat {
289        pub decimal: char,
290    }
291}