script_format/
engine.rs

1use std::any::TypeId;
2use std::cell::RefCell;
3use std::iter::once;
4use std::ops::Deref;
5use std::ops::DerefMut;
6use std::path::Path;
7use std::rc::Rc;
8
9use rhai::CustomType;
10use rhai::{
11    packages::{CorePackage, Package},
12    Dynamic, Engine, EvalAltResult, ImmutableString, Scope, Variant, FLOAT, INT,
13};
14
15use crate::internal::ToBe;
16
17/// A type alias for the result of script execution within the `FormattingEngine`.
18///
19/// This alias simplifies error handling when executing Rhai scripts, encapsulating
20/// either a successful result (`T`) or an error (`Box<EvalAltResult>`).
21///
22/// # Examples
23///
24/// ```rust
25/// use script_format::{
26///     FormattingEngine,
27///     ScriptResult,
28/// };
29///
30/// fn execute_script(script: &str) -> ScriptResult<()> {
31///     let mut engine = FormattingEngine::new(false);
32///     engine.format("data", 42, script)?;
33///     Ok(())
34/// }
35/// ```
36///
37/// # Type Parameters
38///
39/// * `T` - The type of the successful result.
40pub type ScriptResult<T> = Result<T, Box<EvalAltResult>>;
41
42/// A wrapper around the Rhai `Engine` for formatting data using a dsl based on rhai.
43///
44/// `FormattingEngine` allows you to register custom types and format them using a custom dsl based on rhai.
45///
46/// # Examples
47///
48/// ```rust
49/// use script_format::FormattingEngine;
50///
51/// let mut engine = FormattingEngine::new(false);
52/// let result = engine.format("name", "World", "~ `Hello, ${name}!`");
53/// assert_eq!(result.unwrap(), "Hello, World!");
54/// ```
55///
56/// # Features
57///
58/// - Custom type registration
59/// - Script execution with data binding
60/// - Debug support for script evaluation
61pub struct FormattingEngine {
62    engine: Engine,
63    messages: Rc<RefCell<Vec<String>>>,
64}
65
66impl Deref for FormattingEngine {
67    type Target = Engine;
68
69    fn deref(&self) -> &Self::Target {
70        &self.engine
71    }
72}
73
74impl DerefMut for FormattingEngine {
75    fn deref_mut(&mut self) -> &mut Self::Target {
76        &mut self.engine
77    }
78}
79
80impl FormattingEngine {
81    fn register_value<T: Variant + Clone + std::fmt::Display>(&mut self) {
82        self.engine
83            .register_fn("++", move |a: T, b: serde_value::Value| {
84                vec![a.to_string(), serde_json::to_string(&b).unwrap()]
85            });
86        self.engine
87            .register_fn("++", move |a: serde_value::Value, b: T| {
88                vec![serde_json::to_string(&a).unwrap(), b.to_string()]
89            });
90    }
91
92    fn register_string_concat_void<T: Variant + Clone + std::fmt::Display>(&mut self) {
93        self.engine
94            .register_fn("++", move |a: T, _b: ()| vec![a.to_string()]);
95        self.engine
96            .register_fn("++", move |_a: (), b: T| vec![b.to_string()]);
97    }
98
99    fn register_string_concat<T: Variant + Clone + std::fmt::Display>(&mut self) {
100        self.engine.register_fn("++", move |a: T, b: &str| {
101            vec![a.to_string(), b.to_string()]
102        });
103        self.engine.register_fn("++", move |a: &str, b: T| {
104            vec![a.to_string(), b.to_string()]
105        });
106        self.engine
107            .register_fn("++", move |a: T, b: T| vec![a.to_string(), b.to_string()]);
108    }
109
110    fn register_string_concat_vec<T: Variant + Clone + std::fmt::Display>(&mut self) {
111        self.engine.register_fn("++", move |a: Vec<T>, b: &str| {
112            a.iter()
113                .map(ToString::to_string)
114                .chain(once(b.to_owned()))
115                .collect::<Vec<_>>()
116        });
117        self.engine.register_fn("++", move |a: &str, b: Vec<T>| {
118            b.iter()
119                .map(ToString::to_string)
120                .chain(once(a.to_owned()))
121                .collect::<Vec<_>>()
122        });
123        self.engine.register_fn("++", move |a: Vec<T>, b: Vec<T>| {
124            a.iter()
125                .map(ToString::to_string)
126                .chain(b.iter().map(ToString::to_string))
127                .collect::<Vec<_>>()
128        });
129    }
130
131    fn register_concat<T: Variant + Clone + std::fmt::Display>(&mut self) {
132        self.register_string_concat::<T>();
133        self.register_string_concat_vec::<T>();
134        self.register_string_concat_void::<T>();
135    }
136
137    fn register_msg<T: Variant + Clone + std::fmt::Display>(&mut self) {
138        self.register_msg_single::<T>();
139        self.register_msg_multi::<T, &str>();
140        self.register_msg_multi::<T, String>();
141        self.register_msg_multi::<T, bool>();
142        self.register_msg_multi::<T, i64>();
143        self.register_msg_multi::<T, u64>();
144        self.register_msg_multi::<T, i32>();
145        self.register_msg_multi::<T, u32>();
146        self.register_msg_multi::<T, i16>();
147        self.register_msg_multi::<T, u16>();
148        self.register_msg_multi::<T, i8>();
149        self.register_msg_multi::<T, u8>();
150        self.register_msg_multi::<T, usize>();
151        self.register_msg_multi::<T, isize>();
152        self.register_msg_multi::<T, i128>();
153        self.register_msg_multi::<T, u128>();
154        self.register_msg_multi::<T, f32>();
155        self.register_msg_multi::<T, f64>();
156    }
157
158    fn register_msg_multi<
159        A: Variant + Clone + std::fmt::Display,
160        B: Variant + Clone + std::fmt::Display,
161    >(
162        &mut self,
163    ) {
164        self.engine
165            .register_fn("++", move |a: A, b: B| vec![a.to_string(), b.to_string()]);
166
167        self.engine
168            .register_fn("++", move |b: B, a: A| vec![b.to_string(), a.to_string()]);
169
170        self.engine.register_fn("++", move |a: Option<A>, b: B| {
171            if let Some(a) = a {
172                vec![a.to_string(), b.to_string()]
173            } else {
174                vec![b.to_string()]
175            }
176        });
177
178        self.engine.register_fn("++", move |a: A, b: Option<B>| {
179            if let Some(b) = b {
180                vec![a.to_string(), b.to_string()]
181            } else {
182                vec![a.to_string()]
183            }
184        });
185
186        self.engine
187            .register_fn("++", move |a: Option<A>, b: Option<B>| match (a, b) {
188                (Some(a), Some(b)) => vec![a.to_string(), b.to_string()],
189                (Some(a), None) => vec![a.to_string()],
190                (None, Some(b)) => vec![b.to_string()],
191                (None, None) => vec![],
192            });
193    }
194
195    fn register_msg_single<T: Variant + Clone + std::fmt::Display>(&mut self) {
196        self.engine.register_fn("++", move |a: Option<T>, _: ()| {
197            if let Some(a) = a {
198                vec![a.to_string()]
199            } else {
200                vec![]
201            }
202        });
203
204        self.engine.register_fn("++", move |_: (), a: Option<T>| {
205            if let Some(a) = a {
206                vec![a.to_string()]
207            } else {
208                vec![]
209            }
210        });
211    }
212
213    fn register_vec<T: Variant + Clone>(&mut self) {
214        self.engine
215            .register_type::<Vec<T>>()
216            .register_fn("len", |v: Vec<T>| v.len())
217            .register_iterator::<Vec<T>>()
218            .register_iterator::<&Vec<&T>>()
219            .register_iterator::<Vec<T>>()
220            .register_iterator::<&Vec<&T>>()
221            .register_indexer_get(|v: &mut Vec<T>, i: i64| {
222                v[usize::try_from(i).unwrap()].to_owned()
223            });
224    }
225
226    fn register_vec_printable<T: Variant + Clone + std::fmt::Display>(&mut self) {
227        self.register_vec::<T>();
228        self.engine.register_fn("++", move |a: Vec<T>| {
229            a.iter().map(ToString::to_string).collect::<Vec<_>>()
230        });
231
232        self.register_vec_printable_single::<T, &str>();
233        self.register_vec_printable_single::<T, String>();
234        self.register_vec_printable_single::<T, bool>();
235        self.register_vec_printable_single::<T, i64>();
236        self.register_vec_printable_single::<T, u64>();
237        self.register_vec_printable_single::<T, i32>();
238        self.register_vec_printable_single::<T, u32>();
239        self.register_vec_printable_single::<T, i16>();
240        self.register_vec_printable_single::<T, u16>();
241        self.register_vec_printable_single::<T, i8>();
242        self.register_vec_printable_single::<T, u8>();
243        self.register_vec_printable_single::<T, usize>();
244        self.register_vec_printable_single::<T, isize>();
245        self.register_vec_printable_single::<T, i128>();
246        self.register_vec_printable_single::<T, u128>();
247        self.register_vec_printable_single::<T, f32>();
248        self.register_vec_printable_single::<T, f64>();
249
250        self.register_vec_printable_multi::<T, &str>();
251        self.register_vec_printable_multi::<T, String>();
252        self.register_vec_printable_multi::<T, bool>();
253        self.register_vec_printable_multi::<T, i64>();
254        self.register_vec_printable_multi::<T, u64>();
255        self.register_vec_printable_multi::<T, i32>();
256        self.register_vec_printable_multi::<T, u32>();
257        self.register_vec_printable_multi::<T, i16>();
258        self.register_vec_printable_multi::<T, u16>();
259        self.register_vec_printable_multi::<T, i8>();
260        self.register_vec_printable_multi::<T, u8>();
261        self.register_vec_printable_multi::<T, usize>();
262        self.register_vec_printable_multi::<T, isize>();
263        self.register_vec_printable_multi::<T, i128>();
264        self.register_vec_printable_multi::<T, u128>();
265        self.register_vec_printable_multi::<T, f32>();
266        self.register_vec_printable_multi::<T, f64>();
267
268        self.register_vec_printable_void::<&str>();
269        self.register_vec_printable_void::<String>();
270        self.register_vec_printable_void::<bool>();
271        self.register_vec_printable_void::<i64>();
272        self.register_vec_printable_void::<u64>();
273        self.register_vec_printable_void::<i32>();
274        self.register_vec_printable_void::<u32>();
275        self.register_vec_printable_void::<i16>();
276        self.register_vec_printable_void::<u16>();
277        self.register_vec_printable_void::<i8>();
278        self.register_vec_printable_void::<u8>();
279        self.register_vec_printable_void::<usize>();
280        self.register_vec_printable_void::<isize>();
281        self.register_vec_printable_void::<i128>();
282        self.register_vec_printable_void::<u128>();
283        self.register_vec_printable_void::<f32>();
284        self.register_vec_printable_void::<f64>();
285    }
286
287    fn register_vec_printable_void<T: Variant + Clone + std::fmt::Display>(&mut self) {
288        self.engine.register_fn("++", move |a: Vec<T>, _b: ()| {
289            a.iter().map(ToString::to_string).collect::<Vec<_>>()
290        });
291        self.engine.register_fn("++", move |_a: (), b: Vec<T>| {
292            b.iter().map(ToString::to_string).collect::<Vec<_>>()
293        });
294        self.engine
295            .register_fn("++", move |a: Option<Vec<T>>, _b: ()| {
296                a.unwrap_or_default()
297                    .iter()
298                    .map(ToString::to_string)
299                    .collect::<Vec<_>>()
300            });
301        self.engine
302            .register_fn("++", move |_a: (), b: Option<Vec<T>>| {
303                b.unwrap_or_default()
304                    .iter()
305                    .map(ToString::to_string)
306                    .collect::<Vec<_>>()
307            });
308    }
309
310    fn register_vec_printable_multi<
311        A: Variant + Clone + std::fmt::Display,
312        B: Variant + Clone + std::fmt::Display,
313    >(
314        &mut self,
315    ) {
316        self.engine.register_fn("++", move |a: Vec<A>, b: Vec<B>| {
317            a.iter()
318                .map(ToString::to_string)
319                .chain(b.iter().map(ToString::to_string))
320                .collect::<Vec<_>>()
321        });
322
323        self.engine
324            .register_fn("++", move |a: Option<Vec<A>>, b: Vec<B>| {
325                let a: Vec<A> = a.unwrap_or_default();
326                a.iter()
327                    .map(ToString::to_string)
328                    .chain(b.iter().map(ToString::to_string))
329                    .collect::<Vec<_>>()
330            });
331        self.engine
332            .register_fn("++", move |a: Vec<A>, b: Option<Vec<B>>| {
333                let b: Vec<B> = b.unwrap_or_default();
334                a.iter()
335                    .map(ToString::to_string)
336                    .chain(b.iter().map(ToString::to_string))
337                    .collect::<Vec<_>>()
338            });
339    }
340
341    fn register_vec_printable_single<
342        A: Variant + Clone + std::fmt::Display,
343        B: Variant + Clone + std::fmt::Display,
344    >(
345        &mut self,
346    ) {
347        self.engine.register_fn("++", move |a: Vec<A>, b: B| {
348            a.iter()
349                .map(ToString::to_string)
350                .chain(once(b.to_string()))
351                .collect::<Vec<_>>()
352        });
353        self.engine.register_fn("++", move |a: A, b: Vec<B>| {
354            once(a.to_string())
355                .chain(b.iter().map(ToString::to_string))
356                .collect::<Vec<_>>()
357        });
358
359        self.engine
360            .register_fn("++", move |a: Option<Vec<A>>, b: B| {
361                let a: Vec<A> = a.unwrap_or_default();
362                a.iter()
363                    .map(ToString::to_string)
364                    .chain(once(b.to_string()))
365                    .collect::<Vec<_>>()
366            });
367        self.engine
368            .register_fn("++", move |a: A, b: Option<Vec<B>>| {
369                let b: Vec<B> = b.unwrap_or_default();
370                once(a.to_string())
371                    .chain(b.iter().map(ToString::to_string))
372                    .collect::<Vec<_>>()
373            });
374
375        self.engine
376            .register_fn("++", move |a: Vec<A>, b: Option<B>| {
377                let mut res = a.iter().map(ToString::to_string).collect::<Vec<_>>();
378                if let Some(b) = b {
379                    res.push(b.to_string());
380                }
381                res
382            });
383        self.engine
384            .register_fn("++", move |a: Option<A>, b: Vec<B>| {
385                a.iter()
386                    .map(ToString::to_string)
387                    .chain(b.iter().map(ToString::to_string))
388                    .collect::<Vec<_>>()
389            });
390    }
391
392    fn register_type_dynamic<T: Variant + Clone + 'static, C: From<T> + PartialEq + 'static>(
393        &mut self,
394        is_call: fn(&Dynamic) -> bool,
395        as_call: fn(&Dynamic) -> Result<C, &'static str>,
396    ) {
397        self.engine
398            .register_fn("any", move |arr: rhai::Array, v: T| {
399                let value: C = v.into();
400                arr.iter()
401                    .filter(|a| is_call(a))
402                    .map(|a| {
403                        let a: C = as_call(&a).unwrap().into();
404                        a
405                    })
406                    .filter(|a| *a == value)
407                    .into_iter()
408                    .count()
409                    > 0
410            });
411        self.engine
412            .register_fn("all", move |arr: rhai::Array, v: T| {
413                let value: C = v.into();
414                let expected = arr.len();
415                arr.iter()
416                    .filter(|a| is_call(a))
417                    .map(|a| {
418                        let a: C = as_call(&a).unwrap().into();
419                        a
420                    })
421                    .filter(|a| *a == value)
422                    .into_iter()
423                    .count()
424                    == expected
425            });
426        self.engine
427            .register_fn("none", move |arr: rhai::Array, v: T| {
428                let value: C = v.into();
429                arr.iter()
430                    .filter(|a| is_call(a))
431                    .map(|a| {
432                        let a: C = as_call(&a).unwrap().into();
433                        a
434                    })
435                    .filter(|a| *a == value)
436                    .into_iter()
437                    .count()
438                    == 0
439            });
440    }
441
442    fn register_comparison<
443        A: Variant + Clone + AsCast<C>,
444        B: Variant + Clone + AsCast<C>,
445        C: PartialEq + PartialOrd,
446    >(
447        &mut self,
448    ) {
449        self.engine
450            .register_fn(">", |left: A, right: B| left.as_cast() > right.as_cast());
451        self.engine
452            .register_fn(">=", |left: A, right: B| left.as_cast() >= right.as_cast());
453        self.engine
454            .register_fn("<", |left: A, right: B| left.as_cast() < right.as_cast());
455        self.engine
456            .register_fn("<=", |left: A, right: B| left.as_cast() <= right.as_cast());
457        self.engine
458            .register_fn("!=", |left: A, right: B| left.as_cast() != right.as_cast());
459        self.engine
460            .register_fn("==", |left: A, right: B| left.as_cast() == right.as_cast());
461
462        self.engine
463            .register_fn(">", |left: B, right: A| left.as_cast() > right.as_cast());
464        self.engine
465            .register_fn(">=", |left: B, right: A| left.as_cast() >= right.as_cast());
466        self.engine
467            .register_fn("<", |left: B, right: A| left.as_cast() < right.as_cast());
468        self.engine
469            .register_fn("<=", |left: B, right: A| left.as_cast() <= right.as_cast());
470        self.engine
471            .register_fn("!=", |left: B, right: A| left.as_cast() != right.as_cast());
472        self.engine
473            .register_fn("==", |left: B, right: A| left.as_cast() == right.as_cast());
474    }
475
476    fn register_options<T: Variant + Clone>(&mut self) {
477        self.engine
478            .register_fn("is_some", crate::internal::script_is_some::<T>)
479            .register_fn("unwrap", crate::internal::script_unwrap::<T>)
480            .register_fn("unwrap_or", crate::internal::script_unwrap_or::<T>);
481    }
482}
483
484impl FormattingEngine {
485    /// Creates a new `FormattingEngine` instance.
486    ///
487    /// # Arguments
488    ///
489    /// * `debug` - A boolean indicating whether to enable debug functions inside Rhai.
490    ///
491    /// # Returns
492    ///
493    /// A new, pre-configured, `FormattingEngine` instance.
494    #[must_use]
495    pub fn new(debug: bool) -> Self {
496        build_engine(debug)
497    }
498
499    /// Registers a custom type with the Rhai engine.
500    ///
501    /// This method also registers the `is_some`, `unwrap`, and `unwrap_or` methods for the custom type,
502    /// as well as the necessary functions for using the type inside a `Vec<T>`.
503    ///
504    /// # Type Parameters
505    ///
506    /// * `T` - The type to register, which must implement `Variant` and `Clone`.
507    ///
508    /// # Returns
509    ///
510    /// A mutable reference to `self` to allow method chaining.
511    pub fn register_type<T: Variant + Clone>(&mut self) -> &mut Self {
512        self.engine.register_type::<T>();
513        self.register_vec::<T>();
514        self.register_options::<T>();
515
516        self
517    }
518
519    /// Makes a custom type comparable.
520    ///
521    /// This method also registers the `any`, `none` and `all` methods for the custom type,
522    /// as well as the necessary functions for using the type inside a `Vec<T>`.
523    ///
524    /// # Type Parameters
525    ///
526    /// * `T` - The type to register, which must implement `Variant` and `Clone`.
527    ///
528    /// # Returns
529    ///
530    /// A mutable reference to `self` to allow method chaining.
531    pub fn make_comparable<T: Variant + PartialEq + Clone>(&mut self) -> &mut Self {
532        self.register_type::<T>();
533        self.register_options::<T>();
534        self.register_vec::<T>();
535        self.register_fn("any", crate::internal::script_any_type::<T>)
536            .register_fn("all", crate::internal::script_all_type::<T>)
537            .register_fn("none", crate::internal::script_none_type::<T>);
538        self
539    }
540
541    /// Builds and registers a custom type with the Rhai engine.
542    ///
543    /// This function initializes the custom type using `build_type` and then registers it
544    /// with the Rhai engine, making it accessible within the DSL scripts.
545    ///
546    /// # Type Parameters
547    ///
548    /// * `T` - The custom type to build and register, which must implement `Variant`, `CustomType`, and `Clone`.
549    ///
550    /// # Returns
551    ///
552    /// A mutable reference to `self` to allow method chaining.
553    ///
554    /// # Example
555    ///
556    /// ```rust
557    /// use script_format::{
558    ///     rhai::{CustomType, TypeBuilder},
559    ///     FormattingEngine,
560    /// };
561    ///
562    /// #[derive(Clone, CustomType)]
563    /// struct Person {
564    ///     name: String,
565    ///     age: i32,
566    /// }
567    ///
568    /// let mut engine = FormattingEngine::new(false);
569    /// engine.build_type::<Person>();
570    /// ```
571    pub fn build_type<T: Variant + CustomType + Clone>(&mut self) -> &mut Self {
572        self.engine.build_type::<T>();
573        self.register_type::<T>();
574        self
575    }
576
577    /// Runs the formatting script with the provided scope.
578    ///
579    /// Use the scope to pass data to the script.
580    /// **You must register (`build_type` / `register_type`) each custom type that should be accessed beforehand so that rhai can properly access it.**
581    ///
582    /// # Arguments
583    ///
584    /// * `scope` - The Rhai `Scope` to be used during script evaluation.
585    /// * `script` - The script to execute for formatting.
586    ///
587    /// # Errors
588    ///
589    /// Returns an error if script execution fails.
590    ///
591    /// # Returns
592    ///
593    /// A formatted string result.
594    pub fn format_with_scope(&mut self, scope: &mut Scope, script: &str) -> ScriptResult<String> {
595        scope.push_constant("NL", "\n");
596
597        self.messages.borrow_mut().clear();
598        self.engine.run_with_scope(scope, script)?;
599
600        Ok(self.messages.borrow().join(""))
601    }
602
603    /// Formats an object using a script from a file with the provided scope.
604    ///
605    /// Use the scope to pass data to the script.
606    /// **You must register (`build_type` / `register_type`) each custom type that should be accessed beforehand so that rhai can properly access it.**
607    ///
608    /// # Arguments
609    ///
610    /// * `scope` - The Rhai `Scope` to be used during script evaluation.
611    /// * `script` - The file path of the script to execute.
612    ///
613    /// # Errors
614    ///
615    /// Returns an error if file reading or script execution fails.
616    ///
617    /// # Returns
618    ///
619    /// A formatted string result.
620    #[cfg(not(feature = "web"))]
621    pub fn format_from_file_with_scope<P: AsRef<Path>>(
622        &mut self,
623        scope: &mut Scope,
624        script: P,
625    ) -> ScriptResult<String> {
626        match std::fs::read_to_string(script.as_ref()) {
627            Ok(script) => self.format_with_scope(scope, &script),
628            Err(e) => Err(e.to_string().into()),
629        }
630    }
631
632    /// Clones the messages buffer.
633    ///
634    /// This can be useful if you want to register a custom function that needs to access the messages buffer.
635    ///
636    /// # Returns
637    ///
638    /// A reference-counted pointer to the messages buffer.
639    pub fn clone_messages(&self) -> Rc<RefCell<Vec<String>>> {
640        self.messages.clone()
641    }
642
643    /// Formats an object using a script.
644    ///
645    /// **You must register (`build_type` / `register_type`) each custom type that should be accessed beforehand so that rhai can properly access it.**
646    ///
647    /// # Arguments
648    ///
649    /// * `name` - The name of the data variable in the script.
650    /// * `data` - The data object to format.
651    /// * `script` - The script to execute for formatting.
652    ///
653    /// # Errors
654    ///
655    /// Returns an error if script execution fails.
656    ///
657    /// # Returns
658    ///
659    /// A formatted string result.
660    pub fn format<T: Variant + Clone>(
661        &mut self,
662        name: &str,
663        data: T,
664        script: &str,
665    ) -> ScriptResult<String> {
666        self.register_type::<T>();
667
668        let mut scope = Scope::new();
669        scope.push_constant(name, data);
670
671        self.format_with_scope(&mut scope, script)
672    }
673
674    /// Formats an object using a script from a file.
675    ///
676    /// **You must register (`build_type` / `register_type`) each custom type that should be accessed beforehand so that rhai can properly access it.**
677    ///
678    /// # Arguments
679    ///
680    /// * `name` - The name of the data variable in the script.
681    /// * `data` - The data object to format.
682    /// * `script` - The file path of the script to execute.
683    ///
684    /// # Errors
685    ///
686    /// Returns an error if file reading or script execution fails.
687    ///
688    /// # Returns
689    ///
690    /// A formatted string result.
691    #[cfg(not(feature = "web"))]
692    pub fn format_from_file<T: Variant + Clone, P: AsRef<Path>>(
693        &mut self,
694        name: &str,
695        data: T,
696        script: P,
697    ) -> ScriptResult<String> {
698        match std::fs::read_to_string(script.as_ref()) {
699            Ok(script) => self.format(name, data, &script),
700            Err(e) => Err(e.to_string().into()),
701        }
702    }
703}
704
705fn option_to_string<T: std::fmt::Display>(value: Option<T>) -> Option<String> {
706    if let Some(v) = value {
707        Some(format!("{v}"))
708    } else {
709        None
710    }
711}
712
713fn dynamic_to_string(v: Dynamic) -> ScriptResult<Option<String>> {
714    let t = v.type_id();
715    if t == TypeId::of::<()>() {
716        Ok(None)
717    } else if v.is_array() {
718        let flattened = flatten_dynamic(v)?;
719        if flattened.len() > 0 {
720            Ok(Some(flattened.join("")))
721        } else {
722            Ok(None)
723        }
724    } else if t == TypeId::of::<Option<&str>>() {
725        Ok(option_to_string::<&str>(v.cast()))
726    } else if t == TypeId::of::<Option<bool>>() {
727        Ok(option_to_string::<bool>(v.cast()))
728    } else if t == TypeId::of::<Option<i8>>() {
729        Ok(option_to_string::<i8>(v.cast()))
730    } else if t == TypeId::of::<Option<i16>>() {
731        Ok(option_to_string::<i16>(v.cast()))
732    } else if t == TypeId::of::<Option<i32>>() {
733        Ok(option_to_string::<i32>(v.cast()))
734    } else if t == TypeId::of::<Option<i64>>() {
735        Ok(option_to_string::<i64>(v.cast()))
736    } else if t == TypeId::of::<Option<i128>>() {
737        Ok(option_to_string::<i128>(v.cast()))
738    } else if t == TypeId::of::<Option<u8>>() {
739        Ok(option_to_string::<u8>(v.cast()))
740    } else if t == TypeId::of::<Option<u16>>() {
741        Ok(option_to_string::<u16>(v.cast()))
742    } else if t == TypeId::of::<Option<u32>>() {
743        Ok(option_to_string::<u32>(v.cast()))
744    } else if t == TypeId::of::<Option<u64>>() {
745        Ok(option_to_string::<u64>(v.cast()))
746    } else if t == TypeId::of::<Option<f32>>() {
747        Ok(option_to_string::<f32>(v.cast()))
748    } else if t == TypeId::of::<Option<f64>>() {
749        Ok(option_to_string::<f64>(v.cast()))
750    } else if t == TypeId::of::<Option<u128>>() {
751        Ok(option_to_string::<u128>(v.cast()))
752    } else if t == TypeId::of::<Option<char>>() {
753        Ok(option_to_string::<char>(v.cast()))
754    } else if t == TypeId::of::<Option<String>>() {
755        Ok(if let Some(v) = v.cast::<Option<String>>() {
756            Some(v)
757        } else {
758            None
759        })
760    } else if t == TypeId::of::<Option<Dynamic>>() {
761        Ok(if let Some(v) = v.cast::<Option<Dynamic>>() {
762            dynamic_to_string(v)?
763        } else {
764            None
765        })
766    } else if t == TypeId::of::<bool>() {
767        Ok(Some(v.as_bool()?.to_string()))
768    } else if t == TypeId::of::<ImmutableString>() {
769        Ok(Some(v.into_immutable_string()?.to_string()))
770    } else if t == TypeId::of::<char>() {
771        Ok(Some(v.as_char()?.to_string()))
772    } else if t == TypeId::of::<INT>() {
773        Ok(Some(v.as_int()?.to_string()))
774    } else if t == TypeId::of::<FLOAT>() {
775        Ok(Some(v.as_float()?.to_string()))
776    } else {
777        eprintln!("{}", v.type_name());
778        Err("unsupported type".into())
779    }
780}
781
782fn flatten_dynamic(vs: Dynamic) -> Result<Vec<String>, Box<EvalAltResult>> {
783    let mut res = Vec::new();
784    if vs.is_array() {
785        for v in vs.into_array()? {
786            if v.is_array() {
787                let mut values = flatten_dynamic(v)?;
788                res.append(&mut values);
789            } else {
790                if let Some(s) = dynamic_to_string(v)? {
791                    res.push(s);
792                }
793            }
794        }
795    } else if vs.type_id() == TypeId::of::<Option<Vec<String>>>() {
796        if let Some(mut vs) = vs.cast::<Option<Vec<String>>>() {
797            res.append(&mut vs);
798        }
799    } else if vs.type_id() == TypeId::of::<Vec<String>>() {
800        let mut vs = vs.cast::<Vec<String>>();
801        res.append(&mut vs);
802    } else if let Some(s) = dynamic_to_string(vs)? {
803        res.push(s);
804    }
805    Ok(res)
806}
807
808#[allow(clippy::too_many_lines)]
809fn build_engine(debug: bool) -> FormattingEngine {
810    let mut engine = FormattingEngine {
811        engine: rhai::Engine::new(),
812        messages: Rc::new(RefCell::new(Vec::new())),
813    };
814    engine.set_max_expr_depths(128, 64);
815
816    let package = CorePackage::new();
817
818    engine.register_global_module(package.as_shared_module());
819
820    // Register the custom syntax
821    {
822        let messages = engine.clone_messages();
823        engine
824            .register_custom_syntax(
825                ["~", "$expr$"],
826                true,
827                move |context: &mut rhai::EvalContext,
828                      inputs: &[rhai::Expression]|
829                      -> ScriptResult<Dynamic> {
830                    for e in inputs {
831                        let result = context.eval_expression_tree(&e)?;
832                        let mut m = flatten_dynamic(result)?;
833                        messages.borrow_mut().append(&mut m);
834                    }
835                    Ok(Dynamic::UNIT)
836                },
837            )
838            .unwrap();
839    }
840
841    let indent = Rc::new(RefCell::new("    ".to_owned()));
842
843    {
844        let indent = indent.clone();
845
846        // This isn't deprecated, the api is just volatile and may change
847        #[allow(deprecated)]
848        engine.on_var(move |name, _, _| match name {
849            "IND" => Ok(Some(indent.borrow().clone().into())),
850            _ => Ok(None),
851        });
852    }
853
854    {
855        let indent = indent.clone();
856        #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
857        engine.register_fn("IND", move |count: i64| {
858            indent.borrow().repeat(count as usize)
859        });
860    }
861
862    {
863        let indent = indent.clone();
864        #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
865        engine.register_fn("SET_INDENT", move |value: &str| {
866            value.clone_into(&mut indent.borrow_mut());
867        });
868    }
869
870    {
871        let indent = indent.clone();
872        #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
873        engine.register_fn("SET_INDENT", move |value: &str, count: i64| {
874            *indent.borrow_mut() = value.repeat(count as usize)
875        });
876    }
877
878    {
879        let indent = indent.clone();
880        #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
881        engine.register_fn("SET_INDENT", move |count: i64| {
882            *indent.borrow_mut() = " ".repeat(count as usize)
883        });
884    }
885
886    #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
887    engine.register_fn("NL", |count: i64| "\n".repeat(count as usize));
888
889    engine.register_iterator::<Vec<serde_value::Value>>();
890
891    engine.register_options::<&str>();
892    engine.register_options::<String>();
893    engine.register_options::<bool>();
894    engine.register_options::<i64>();
895    engine.register_options::<u64>();
896    engine.register_options::<i32>();
897    engine.register_options::<u32>();
898    engine.register_options::<i16>();
899    engine.register_options::<u16>();
900    engine.register_options::<i8>();
901    engine.register_options::<u8>();
902    engine.register_options::<usize>();
903    engine.register_options::<isize>();
904    engine.register_options::<i128>();
905    engine.register_options::<u128>();
906    engine.register_options::<f32>();
907    engine.register_options::<f64>();
908
909    engine.register_type_dynamic::<i8, i64>(Dynamic::is_int, Dynamic::as_int);
910    engine.register_type_dynamic::<i16, i64>(Dynamic::is_int, Dynamic::as_int);
911    engine.register_type_dynamic::<i32, i64>(Dynamic::is_int, Dynamic::as_int);
912    engine.register_type_dynamic::<i64, i64>(Dynamic::is_int, Dynamic::as_int);
913
914    engine.register_type_dynamic::<u8, i64>(Dynamic::is_int, Dynamic::as_int);
915    engine.register_type_dynamic::<u16, i64>(Dynamic::is_int, Dynamic::as_int);
916    engine.register_type_dynamic::<u32, i64>(Dynamic::is_int, Dynamic::as_int);
917
918    engine.register_type_dynamic::<f32, f64>(Dynamic::is_float, Dynamic::as_float);
919    engine.register_type_dynamic::<f64, f64>(Dynamic::is_float, Dynamic::as_float);
920
921    engine.register_type_dynamic::<bool, bool>(Dynamic::is_bool, Dynamic::as_bool);
922
923    fn dynamic_as_string(dynamic: &Dynamic) -> Result<String, &'static str> {
924        dynamic.to_owned().into_string()
925    }
926
927    engine.register_type_dynamic::<String, String>(Dynamic::is_string, dynamic_as_string);
928    engine.register_type_dynamic::<&str, String>(Dynamic::is_string, dynamic_as_string);
929
930    engine
931        .register_fn("join", crate::internal::script_join)
932        .register_fn("split", crate::internal::script_split)
933        .register_fn("splitn", crate::internal::script_splitn)
934        .register_fn("rsplitn", crate::internal::script_rsplitn)
935        .register_fn("is_empty", crate::internal::script_string_is_empty)
936        .register_fn("is_empty", crate::internal::script_array_is_empty)
937        .register_fn("starts_with", crate::internal::script_starts_with)
938        .register_fn("ends_with", crate::internal::script_ends_with)
939        .register_fn("trim", crate::internal::script_trim)
940        .register_fn("is_string", crate::internal::script_is_no_string)
941        .register_fn("is_string", crate::internal::script_is_string);
942
943    // DSL
944    engine.build_type::<ToBe>();
945    engine
946        .register_custom_operator("zip", 65)
947        .unwrap()
948        .register_custom_operator("to_be", 60)
949        .unwrap()
950        .register_custom_operator("and", 60)
951        .unwrap()
952        .register_fn("and", |a: bool, b: bool| a && b)
953        .register_custom_operator("or", 30)
954        .unwrap()
955        .register_fn("or", |a: bool, b: bool| a || b)
956        .register_custom_operator("xor", 30)
957        .unwrap()
958        .register_fn("xor", |a: bool, b: bool| a ^ b)
959        .register_custom_operator("contains", 25)
960        .unwrap()
961        .register_custom_operator("equals", 25)
962        .unwrap()
963        .register_custom_operator("require", 25)
964        .unwrap()
965        .register_custom_operator("any", 25)
966        .unwrap()
967        .register_custom_operator("all", 25)
968        .unwrap()
969        .register_custom_operator("none", 25)
970        .unwrap()
971        .register_fn("contains", crate::internal::script_map_contains)
972        .register_fn("contains", crate::internal::script_string_contains)
973        .register_fn("equals", crate::internal::script_map_equals)
974        .register_fn("equals", crate::internal::script_value_equals)
975        .register_fn("equals", crate::internal::script_array_equals)
976        .register_fn("contains", crate::internal::script_array_contains)
977        .register_fn("require", crate::internal::script_require)
978        .register_fn("to_be", crate::internal::script_to_be)
979        .register_fn("any", crate::internal::script_any)
980        .register_fn("any", crate::internal::script_any_void)
981        .register_fn("all", crate::internal::script_all)
982        .register_fn("all", crate::internal::script_all_void)
983        .register_fn("none", crate::internal::script_none)
984        .register_fn("none", crate::internal::script_none_void);
985
986    engine.register_msg_single::<&str>();
987    engine.register_msg_single::<String>();
988    engine.register_msg_single::<bool>();
989    engine.register_msg_single::<i64>();
990    engine.register_msg_single::<u64>();
991    engine.register_msg_single::<i32>();
992    engine.register_msg_single::<u32>();
993    engine.register_msg_single::<i16>();
994    engine.register_msg_single::<u16>();
995    engine.register_msg_single::<i8>();
996    engine.register_msg_single::<u8>();
997    engine.register_msg_single::<usize>();
998    engine.register_msg_single::<isize>();
999    engine.register_msg_single::<i128>();
1000    engine.register_msg_single::<u128>();
1001    engine.register_msg_single::<f32>();
1002    engine.register_msg_single::<f64>();
1003
1004    engine.register_msg::<&str>();
1005    engine.register_msg::<String>();
1006    engine.register_msg::<bool>();
1007    engine.register_msg::<i64>();
1008    engine.register_msg::<u64>();
1009    engine.register_msg::<i32>();
1010    engine.register_msg::<u32>();
1011    engine.register_msg::<i16>();
1012    engine.register_msg::<u16>();
1013    engine.register_msg::<i8>();
1014    engine.register_msg::<u8>();
1015    engine.register_msg::<usize>();
1016    engine.register_msg::<isize>();
1017    engine.register_msg::<i128>();
1018    engine.register_msg::<u128>();
1019    engine.register_msg::<f32>();
1020    engine.register_msg::<f64>();
1021
1022    engine.register_comparison::<u8, u8, u8>();
1023    engine.register_comparison::<u8, u16, u16>();
1024    engine.register_comparison::<u8, u32, u32>();
1025    engine.register_comparison::<u8, u64, u64>();
1026    engine.register_comparison::<u8, usize, u128>();
1027    engine.register_comparison::<u8, u128, u128>();
1028
1029    engine.register_comparison::<u16, u16, u16>();
1030    engine.register_comparison::<u16, u32, u32>();
1031    engine.register_comparison::<u16, u64, u64>();
1032    engine.register_comparison::<u16, usize, u128>();
1033    engine.register_comparison::<u16, u128, u128>();
1034
1035    engine.register_comparison::<u32, u32, u32>();
1036    engine.register_comparison::<u32, u64, u64>();
1037    engine.register_comparison::<u32, usize, u128>();
1038    engine.register_comparison::<u32, u128, u128>();
1039
1040    engine.register_comparison::<u64, u64, u64>();
1041    engine.register_comparison::<u64, usize, u128>();
1042    engine.register_comparison::<u64, u128, u128>();
1043
1044    engine.register_comparison::<usize, usize, u128>();
1045    engine.register_comparison::<usize, u128, u128>();
1046
1047    engine.register_comparison::<u128, u128, u128>();
1048
1049    engine.register_comparison::<i8, i8, i8>();
1050    engine.register_comparison::<i8, i16, i16>();
1051    engine.register_comparison::<i8, i32, i32>();
1052    engine.register_comparison::<i8, i64, i64>();
1053    engine.register_comparison::<i8, isize, i128>();
1054    engine.register_comparison::<i8, i128, i128>();
1055
1056    engine.register_comparison::<i16, i16, i16>();
1057    engine.register_comparison::<i16, i32, i32>();
1058    engine.register_comparison::<i16, i64, i64>();
1059    engine.register_comparison::<i8, isize, i128>();
1060    engine.register_comparison::<i16, i128, i128>();
1061
1062    engine.register_comparison::<i32, i32, i32>();
1063    engine.register_comparison::<i32, i64, i64>();
1064    engine.register_comparison::<i32, isize, i128>();
1065    engine.register_comparison::<i32, i128, i128>();
1066
1067    engine.register_comparison::<i64, i64, i64>();
1068    engine.register_comparison::<i64, isize, i128>();
1069    engine.register_comparison::<i64, i128, i128>();
1070
1071    engine.register_comparison::<isize, isize, i128>();
1072    engine.register_comparison::<isize, i128, i128>();
1073
1074    engine.register_comparison::<i128, i128, i128>();
1075
1076    engine.register_comparison::<f32, f32, f32>();
1077    engine.register_comparison::<f32, f64, f64>();
1078
1079    engine.register_comparison::<u8, f32, f32>();
1080    engine.register_comparison::<u16, f32, f32>();
1081    engine.register_comparison::<u32, f64, f64>();
1082
1083    engine.register_comparison::<i8, f32, f32>();
1084    engine.register_comparison::<i16, f32, f32>();
1085    engine.register_comparison::<i32, f64, f64>();
1086
1087    engine.register_value::<&str>();
1088    engine.register_value::<String>();
1089    engine.register_value::<bool>();
1090    engine.register_value::<i64>();
1091    engine.register_value::<u64>();
1092    engine.register_value::<i32>();
1093    engine.register_value::<u32>();
1094    engine.register_value::<i16>();
1095    engine.register_value::<u16>();
1096    engine.register_value::<i8>();
1097    engine.register_value::<u8>();
1098    engine.register_value::<usize>();
1099    engine.register_value::<isize>();
1100    engine.register_value::<i128>();
1101    engine.register_value::<u128>();
1102    engine.register_value::<f32>();
1103    engine.register_value::<f64>();
1104
1105    engine.register_fn("++", move |a: serde_value::Value, b: serde_value::Value| {
1106        vec![
1107            serde_json::to_string(&a).unwrap(),
1108            serde_json::to_string(&b).unwrap(),
1109        ]
1110    });
1111
1112    engine.register_concat::<&str>();
1113    engine.register_concat::<String>();
1114    engine.register_concat::<bool>();
1115    engine.register_concat::<i64>();
1116    engine.register_concat::<u64>();
1117    engine.register_concat::<i32>();
1118    engine.register_concat::<u32>();
1119    engine.register_concat::<i16>();
1120    engine.register_concat::<u16>();
1121    engine.register_concat::<i8>();
1122    engine.register_concat::<u8>();
1123    engine.register_concat::<usize>();
1124    engine.register_concat::<isize>();
1125    engine.register_concat::<i128>();
1126    engine.register_concat::<u128>();
1127    engine.register_concat::<f32>();
1128    engine.register_concat::<f64>();
1129
1130    engine.register_vec_printable::<&str>();
1131    engine.register_vec_printable::<String>();
1132    engine.register_vec_printable::<bool>();
1133    engine.register_vec_printable::<i64>();
1134    engine.register_vec_printable::<u64>();
1135    engine.register_vec_printable::<i32>();
1136    engine.register_vec_printable::<u32>();
1137    engine.register_vec_printable::<i16>();
1138    engine.register_vec_printable::<u16>();
1139    engine.register_vec_printable::<i8>();
1140    engine.register_vec_printable::<u8>();
1141    engine.register_vec_printable::<usize>();
1142    engine.register_vec_printable::<isize>();
1143    engine.register_vec_printable::<i128>();
1144    engine.register_vec_printable::<u128>();
1145    engine.register_vec_printable::<f32>();
1146    engine.register_vec_printable::<f64>();
1147
1148    engine.register_vec::<()>();
1149
1150    engine
1151        .register_fn("any", crate::internal::script_any_type::<bool>)
1152        .register_fn("all", crate::internal::script_any_type::<bool>)
1153        .register_fn("none", crate::internal::script_any_type::<bool>)
1154        .register_fn("++", move |(): (), b: &str| vec![b.to_owned()])
1155        .register_fn("++", move |(): (), b: usize| vec![b.to_string()]);
1156    engine
1157        .register_custom_operator("++", 15)
1158        .unwrap()
1159        .register_custom_operator("then_emit", 20)
1160        .unwrap()
1161        .register_fn(
1162            "then_emit",
1163            move |a: bool, msg: &str| {
1164                if a {
1165                    Some(msg.to_owned())
1166                } else {
1167                    None
1168                }
1169            },
1170        )
1171        .register_fn(
1172            "then_emit",
1173            move |a: bool, msg: Vec<String>| {
1174                if a {
1175                    msg
1176                } else {
1177                    Vec::new()
1178                }
1179            },
1180        )
1181        .register_custom_operator("or_emit", 20)
1182        .unwrap()
1183        .register_fn(
1184            "or_emit",
1185            move |a: bool, msg: &str| {
1186                if !a {
1187                    Some(msg.to_owned())
1188                } else {
1189                    None
1190                }
1191            },
1192        )
1193        .register_fn(
1194            "or_emit",
1195            move |a: bool, msg: Vec<String>| {
1196                if a {
1197                    msg
1198                } else {
1199                    Vec::new()
1200                }
1201            },
1202        );
1203    // END DSL
1204
1205    if debug {
1206        engine.on_print(move |x| eprintln!("INFO => {x}"));
1207        engine.on_debug(move |x, _, pos| eprintln!("DEBUG({pos:?}) => {x}"));
1208    } else {
1209        engine.on_print(|_| ());
1210        engine.on_debug(|_, _, _| ());
1211    }
1212
1213    engine.disable_symbol("eval");
1214
1215    engine
1216}
1217
1218trait AsCast<T> {
1219    fn as_cast(self) -> T;
1220}
1221
1222impl AsCast<u8> for u8 {
1223    fn as_cast(self) -> u8 {
1224        self as u8
1225    }
1226}
1227impl AsCast<u16> for u8 {
1228    fn as_cast(self) -> u16 {
1229        self as u16
1230    }
1231}
1232impl AsCast<u32> for u8 {
1233    fn as_cast(self) -> u32 {
1234        self as u32
1235    }
1236}
1237impl AsCast<u64> for u8 {
1238    fn as_cast(self) -> u64 {
1239        self as u64
1240    }
1241}
1242impl AsCast<u128> for u8 {
1243    fn as_cast(self) -> u128 {
1244        self as u128
1245    }
1246}
1247impl AsCast<usize> for u8 {
1248    fn as_cast(self) -> usize {
1249        self as usize
1250    }
1251}
1252impl AsCast<i8> for i8 {
1253    fn as_cast(self) -> i8 {
1254        self as i8
1255    }
1256}
1257impl AsCast<i16> for i8 {
1258    fn as_cast(self) -> i16 {
1259        self as i16
1260    }
1261}
1262impl AsCast<i32> for i8 {
1263    fn as_cast(self) -> i32 {
1264        self as i32
1265    }
1266}
1267impl AsCast<i64> for i8 {
1268    fn as_cast(self) -> i64 {
1269        self as i64
1270    }
1271}
1272impl AsCast<i128> for i8 {
1273    fn as_cast(self) -> i128 {
1274        self as i128
1275    }
1276}
1277impl AsCast<isize> for i8 {
1278    fn as_cast(self) -> isize {
1279        self as isize
1280    }
1281}
1282
1283impl AsCast<u16> for u16 {
1284    fn as_cast(self) -> u16 {
1285        self as u16
1286    }
1287}
1288impl AsCast<u32> for u16 {
1289    fn as_cast(self) -> u32 {
1290        self as u32
1291    }
1292}
1293impl AsCast<u64> for u16 {
1294    fn as_cast(self) -> u64 {
1295        self as u64
1296    }
1297}
1298impl AsCast<u128> for u16 {
1299    fn as_cast(self) -> u128 {
1300        self as u128
1301    }
1302}
1303impl AsCast<usize> for u16 {
1304    fn as_cast(self) -> usize {
1305        self as usize
1306    }
1307}
1308impl AsCast<i16> for i16 {
1309    fn as_cast(self) -> i16 {
1310        self as i16
1311    }
1312}
1313impl AsCast<i32> for i16 {
1314    fn as_cast(self) -> i32 {
1315        self as i32
1316    }
1317}
1318impl AsCast<i64> for i16 {
1319    fn as_cast(self) -> i64 {
1320        self as i64
1321    }
1322}
1323impl AsCast<i128> for i16 {
1324    fn as_cast(self) -> i128 {
1325        self as i128
1326    }
1327}
1328impl AsCast<isize> for i16 {
1329    fn as_cast(self) -> isize {
1330        self as isize
1331    }
1332}
1333
1334impl AsCast<u32> for u32 {
1335    fn as_cast(self) -> u32 {
1336        self as u32
1337    }
1338}
1339impl AsCast<u64> for u32 {
1340    fn as_cast(self) -> u64 {
1341        self as u64
1342    }
1343}
1344impl AsCast<u128> for u32 {
1345    fn as_cast(self) -> u128 {
1346        self as u128
1347    }
1348}
1349impl AsCast<usize> for u32 {
1350    fn as_cast(self) -> usize {
1351        self as usize
1352    }
1353}
1354impl AsCast<i32> for i32 {
1355    fn as_cast(self) -> i32 {
1356        self as i32
1357    }
1358}
1359impl AsCast<i64> for i32 {
1360    fn as_cast(self) -> i64 {
1361        self as i64
1362    }
1363}
1364impl AsCast<i128> for i32 {
1365    fn as_cast(self) -> i128 {
1366        self as i128
1367    }
1368}
1369impl AsCast<isize> for i32 {
1370    fn as_cast(self) -> isize {
1371        self as isize
1372    }
1373}
1374
1375impl AsCast<u64> for u64 {
1376    fn as_cast(self) -> u64 {
1377        self as u64
1378    }
1379}
1380impl AsCast<u128> for u64 {
1381    fn as_cast(self) -> u128 {
1382        self as u128
1383    }
1384}
1385impl AsCast<i64> for i64 {
1386    fn as_cast(self) -> i64 {
1387        self as i64
1388    }
1389}
1390impl AsCast<i128> for i64 {
1391    fn as_cast(self) -> i128 {
1392        self as i128
1393    }
1394}
1395
1396impl AsCast<usize> for usize {
1397    fn as_cast(self) -> usize {
1398        self as usize
1399    }
1400}
1401impl AsCast<u128> for usize {
1402    fn as_cast(self) -> u128 {
1403        self as u128
1404    }
1405}
1406impl AsCast<isize> for isize {
1407    fn as_cast(self) -> isize {
1408        self as isize
1409    }
1410}
1411impl AsCast<i128> for isize {
1412    fn as_cast(self) -> i128 {
1413        self as i128
1414    }
1415}
1416
1417impl AsCast<u128> for u128 {
1418    fn as_cast(self) -> u128 {
1419        self as u128
1420    }
1421}
1422impl AsCast<i128> for i128 {
1423    fn as_cast(self) -> i128 {
1424        self as i128
1425    }
1426}
1427
1428impl AsCast<f32> for f32 {
1429    fn as_cast(self) -> f32 {
1430        self as f32
1431    }
1432}
1433impl AsCast<f64> for f32 {
1434    fn as_cast(self) -> f64 {
1435        self as f64
1436    }
1437}
1438impl AsCast<f64> for f64 {
1439    fn as_cast(self) -> f64 {
1440        self as f64
1441    }
1442}
1443
1444impl AsCast<f32> for u8 {
1445    fn as_cast(self) -> f32 {
1446        self as f32
1447    }
1448}
1449impl AsCast<f64> for u8 {
1450    fn as_cast(self) -> f64 {
1451        self as f64
1452    }
1453}
1454impl AsCast<f32> for u16 {
1455    fn as_cast(self) -> f32 {
1456        self as f32
1457    }
1458}
1459impl AsCast<f64> for u16 {
1460    fn as_cast(self) -> f64 {
1461        self as f64
1462    }
1463}
1464impl AsCast<f64> for u32 {
1465    fn as_cast(self) -> f64 {
1466        self as f64
1467    }
1468}
1469
1470impl AsCast<f32> for i8 {
1471    fn as_cast(self) -> f32 {
1472        self as f32
1473    }
1474}
1475impl AsCast<f64> for i8 {
1476    fn as_cast(self) -> f64 {
1477        self as f64
1478    }
1479}
1480impl AsCast<f32> for i16 {
1481    fn as_cast(self) -> f32 {
1482        self as f32
1483    }
1484}
1485impl AsCast<f64> for i16 {
1486    fn as_cast(self) -> f64 {
1487        self as f64
1488    }
1489}
1490impl AsCast<f64> for i32 {
1491    fn as_cast(self) -> f64 {
1492        self as f64
1493    }
1494}