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