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
17pub type ScriptResult<T> = Result<T, Box<EvalAltResult>>;
41
42pub 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 #[must_use]
495 pub fn new(debug: bool) -> Self {
496 build_engine(debug)
497 }
498
499 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 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 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 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 #[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 pub fn clone_messages(&self) -> Rc<RefCell<Vec<String>>> {
640 self.messages.clone()
641 }
642
643 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 #[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 {
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 #[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 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 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}