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
80#[inline(always)]
81fn minus_deprecation() {
82 eprintln!(
83 "Using '-' for printing is deprecated and will be removed in future versions. Use '~' instead."
84 )
85}
86
87impl FormattingEngine {
88 fn register_value<T: Variant + Clone + std::fmt::Display>(&mut self) {
89 self.engine
90 .register_fn("++", move |a: T, b: serde_value::Value| {
91 vec![a.to_string(), serde_json::to_string(&b).unwrap()]
92 });
93 self.engine
94 .register_fn("++", move |a: serde_value::Value, b: T| {
95 vec![serde_json::to_string(&a).unwrap(), b.to_string()]
96 });
97 }
98
99 fn register_string_concat_void<T: Variant + Clone + std::fmt::Display>(&mut self) {
100 self.engine
101 .register_fn("++", move |a: T, _b: ()| vec![a.to_string()]);
102 self.engine
103 .register_fn("++", move |_a: (), b: T| vec![b.to_string()]);
104 }
105
106 fn register_string_concat<T: Variant + Clone + std::fmt::Display>(&mut self) {
107 self.engine.register_fn("++", move |a: T, b: &str| {
108 vec![a.to_string(), b.to_string()]
109 });
110 self.engine.register_fn("++", move |a: &str, b: T| {
111 vec![a.to_string(), b.to_string()]
112 });
113 self.engine
114 .register_fn("++", move |a: T, b: T| vec![a.to_string(), b.to_string()]);
115 }
116
117 fn register_string_concat_vec<T: Variant + Clone + std::fmt::Display>(&mut self) {
118 self.engine.register_fn("++", move |a: Vec<T>, b: &str| {
119 a.iter()
120 .map(ToString::to_string)
121 .chain(once(b.to_owned()))
122 .collect::<Vec<_>>()
123 });
124 self.engine.register_fn("++", move |a: &str, b: Vec<T>| {
125 b.iter()
126 .map(ToString::to_string)
127 .chain(once(a.to_owned()))
128 .collect::<Vec<_>>()
129 });
130 self.engine.register_fn("++", move |a: Vec<T>, b: Vec<T>| {
131 a.iter()
132 .map(ToString::to_string)
133 .chain(b.iter().map(ToString::to_string))
134 .collect::<Vec<_>>()
135 });
136 }
137
138 fn register_concat<T: Variant + Clone + std::fmt::Display>(&mut self) {
139 self.register_string_concat::<T>();
140 self.register_string_concat_vec::<T>();
141 self.register_string_concat_void::<T>();
142 }
143
144 fn register_msg<T: Variant + Clone + std::fmt::Display>(&mut self) {
145 self.register_msg_single::<T>();
146 self.register_msg_multi::<T, &str>();
147 self.register_msg_multi::<T, String>();
148 self.register_msg_multi::<T, bool>();
149 self.register_msg_multi::<T, i64>();
150 self.register_msg_multi::<T, u64>();
151 self.register_msg_multi::<T, i32>();
152 self.register_msg_multi::<T, u32>();
153 self.register_msg_multi::<T, i16>();
154 self.register_msg_multi::<T, u16>();
155 self.register_msg_multi::<T, i8>();
156 self.register_msg_multi::<T, u8>();
157 self.register_msg_multi::<T, usize>();
158 self.register_msg_multi::<T, isize>();
159 self.register_msg_multi::<T, i128>();
160 self.register_msg_multi::<T, u128>();
161 self.register_msg_multi::<T, f32>();
162 self.register_msg_multi::<T, f64>();
163 }
164
165 fn register_msg_multi<
166 A: Variant + Clone + std::fmt::Display,
167 B: Variant + Clone + std::fmt::Display,
168 >(
169 &mut self,
170 ) {
171 self.engine
172 .register_fn("++", move |a: A, b: B| vec![a.to_string(), b.to_string()]);
173
174 self.engine
175 .register_fn("++", move |b: B, a: A| vec![b.to_string(), a.to_string()]);
176
177 self.engine.register_fn("++", move |a: Option<A>, b: B| {
178 if let Some(a) = a {
179 vec![a.to_string(), b.to_string()]
180 } else {
181 vec![b.to_string()]
182 }
183 });
184
185 self.engine.register_fn("++", move |a: A, b: Option<B>| {
186 if let Some(b) = b {
187 vec![a.to_string(), b.to_string()]
188 } else {
189 vec![a.to_string()]
190 }
191 });
192
193 self.engine
194 .register_fn("++", move |a: Option<A>, b: Option<B>| match (a, b) {
195 (Some(a), Some(b)) => vec![a.to_string(), b.to_string()],
196 (Some(a), None) => vec![a.to_string()],
197 (None, Some(b)) => vec![b.to_string()],
198 (None, None) => vec![],
199 });
200 }
201
202 fn register_msg_single<T: Variant + Clone + std::fmt::Display>(&mut self) {
203 {
204 let messages = self.clone_messages();
205 self.engine.register_fn("-", move |msg: T| {
206 minus_deprecation();
207 messages.borrow_mut().push(msg.to_string());
208 });
209 }
210
211 {
212 let messages = self.clone_messages();
213 self.engine.register_fn("-", move |msg: Option<T>| {
214 minus_deprecation();
215 if let Some(msg) = msg {
216 messages.borrow_mut().push(msg.to_string());
217 }
218 });
219 }
220 }
221
222 fn register_vec<T: Variant + Clone>(&mut self) {
223 self.engine
224 .register_type::<Vec<T>>()
225 .register_fn("len", |v: Vec<T>| v.len())
226 .register_iterator::<Vec<T>>()
227 .register_iterator::<&Vec<&T>>()
228 .register_iterator::<Vec<T>>()
229 .register_iterator::<&Vec<&T>>()
230 .register_indexer_get(|v: &mut Vec<T>, i: i64| {
231 v[usize::try_from(i).unwrap()].to_owned()
232 });
233 }
234
235 fn register_vec_printable<T: Variant + Clone + std::fmt::Display>(&mut self) {
236 self.engine.register_fn("++", move |a: Vec<T>| {
237 a.iter().map(ToString::to_string).collect::<Vec<_>>()
238 });
239
240 self.register_vec_printable_single::<T, &str>();
241 self.register_vec_printable_single::<T, String>();
242 self.register_vec_printable_single::<T, bool>();
243 self.register_vec_printable_single::<T, i64>();
244 self.register_vec_printable_single::<T, u64>();
245 self.register_vec_printable_single::<T, i32>();
246 self.register_vec_printable_single::<T, u32>();
247 self.register_vec_printable_single::<T, i16>();
248 self.register_vec_printable_single::<T, u16>();
249 self.register_vec_printable_single::<T, i8>();
250 self.register_vec_printable_single::<T, u8>();
251 self.register_vec_printable_single::<T, usize>();
252 self.register_vec_printable_single::<T, isize>();
253 self.register_vec_printable_single::<T, i128>();
254 self.register_vec_printable_single::<T, u128>();
255 self.register_vec_printable_single::<T, f32>();
256 self.register_vec_printable_single::<T, f64>();
257
258 self.register_vec_printable_multi::<T, &str>();
259 self.register_vec_printable_multi::<T, String>();
260 self.register_vec_printable_multi::<T, bool>();
261 self.register_vec_printable_multi::<T, i64>();
262 self.register_vec_printable_multi::<T, u64>();
263 self.register_vec_printable_multi::<T, i32>();
264 self.register_vec_printable_multi::<T, u32>();
265 self.register_vec_printable_multi::<T, i16>();
266 self.register_vec_printable_multi::<T, u16>();
267 self.register_vec_printable_multi::<T, i8>();
268 self.register_vec_printable_multi::<T, u8>();
269 self.register_vec_printable_multi::<T, usize>();
270 self.register_vec_printable_multi::<T, isize>();
271 self.register_vec_printable_multi::<T, i128>();
272 self.register_vec_printable_multi::<T, u128>();
273 self.register_vec_printable_multi::<T, f32>();
274 self.register_vec_printable_multi::<T, f64>();
275
276 self.register_vec_printable_void::<&str>();
277 self.register_vec_printable_void::<String>();
278 self.register_vec_printable_void::<bool>();
279 self.register_vec_printable_void::<i64>();
280 self.register_vec_printable_void::<u64>();
281 self.register_vec_printable_void::<i32>();
282 self.register_vec_printable_void::<u32>();
283 self.register_vec_printable_void::<i16>();
284 self.register_vec_printable_void::<u16>();
285 self.register_vec_printable_void::<i8>();
286 self.register_vec_printable_void::<u8>();
287 self.register_vec_printable_void::<usize>();
288 self.register_vec_printable_void::<isize>();
289 self.register_vec_printable_void::<i128>();
290 self.register_vec_printable_void::<u128>();
291 self.register_vec_printable_void::<f32>();
292 self.register_vec_printable_void::<f64>();
293 }
294
295 fn register_vec_printable_void<T: Variant + Clone + std::fmt::Display>(&mut self) {
296 self.engine.register_fn("++", move |a: Vec<T>, _b: ()| {
297 a.iter().map(ToString::to_string).collect::<Vec<_>>()
298 });
299 self.engine.register_fn("++", move |_a: (), b: Vec<T>| {
300 b.iter().map(ToString::to_string).collect::<Vec<_>>()
301 });
302 self.engine
303 .register_fn("++", move |a: Option<Vec<T>>, _b: ()| {
304 a.unwrap_or_default()
305 .iter()
306 .map(ToString::to_string)
307 .collect::<Vec<_>>()
308 });
309 self.engine
310 .register_fn("++", move |_a: (), b: Option<Vec<T>>| {
311 b.unwrap_or_default()
312 .iter()
313 .map(ToString::to_string)
314 .collect::<Vec<_>>()
315 });
316 }
317
318 fn register_vec_printable_multi<
319 A: Variant + Clone + std::fmt::Display,
320 B: Variant + Clone + std::fmt::Display,
321 >(
322 &mut self,
323 ) {
324 self.engine.register_fn("++", move |a: Vec<A>, b: Vec<B>| {
325 a.iter()
326 .map(ToString::to_string)
327 .chain(b.iter().map(ToString::to_string))
328 .collect::<Vec<_>>()
329 });
330
331 self.engine
332 .register_fn("++", move |a: Option<Vec<A>>, b: Vec<B>| {
333 let a: Vec<A> = a.unwrap_or_default();
334 a.iter()
335 .map(ToString::to_string)
336 .chain(b.iter().map(ToString::to_string))
337 .collect::<Vec<_>>()
338 });
339 self.engine
340 .register_fn("++", move |a: Vec<A>, b: Option<Vec<B>>| {
341 let b: Vec<B> = b.unwrap_or_default();
342 a.iter()
343 .map(ToString::to_string)
344 .chain(b.iter().map(ToString::to_string))
345 .collect::<Vec<_>>()
346 });
347 }
348
349 fn register_vec_printable_single<
350 A: Variant + Clone + std::fmt::Display,
351 B: Variant + Clone + std::fmt::Display,
352 >(
353 &mut self,
354 ) {
355 self.engine.register_fn("++", move |a: Vec<A>, b: B| {
356 a.iter()
357 .map(ToString::to_string)
358 .chain(once(b.to_string()))
359 .collect::<Vec<_>>()
360 });
361 self.engine.register_fn("++", move |a: A, b: Vec<B>| {
362 once(a.to_string())
363 .chain(b.iter().map(ToString::to_string))
364 .collect::<Vec<_>>()
365 });
366
367 self.engine
368 .register_fn("++", move |a: Option<Vec<A>>, b: B| {
369 let a: Vec<A> = a.unwrap_or_default();
370 a.iter()
371 .map(ToString::to_string)
372 .chain(once(b.to_string()))
373 .collect::<Vec<_>>()
374 });
375 self.engine
376 .register_fn("++", move |a: A, b: Option<Vec<B>>| {
377 let b: Vec<B> = b.unwrap_or_default();
378 once(a.to_string())
379 .chain(b.iter().map(ToString::to_string))
380 .collect::<Vec<_>>()
381 });
382
383 self.engine
384 .register_fn("++", move |a: Vec<A>, b: Option<B>| {
385 let mut res = a.iter().map(ToString::to_string).collect::<Vec<_>>();
386 if let Some(b) = b {
387 res.push(b.to_string());
388 }
389 res
390 });
391 self.engine
392 .register_fn("++", move |a: Option<A>, b: Vec<B>| {
393 a.iter()
394 .map(ToString::to_string)
395 .chain(b.iter().map(ToString::to_string))
396 .collect::<Vec<_>>()
397 });
398 }
399
400 fn register_type_dynamic<T: Variant + Clone + 'static, C: From<T> + PartialEq + 'static>(
401 &mut self,
402 is_call: fn(&Dynamic) -> bool,
403 as_call: fn(&Dynamic) -> Result<C, &'static str>,
404 ) {
405 self.engine
406 .register_fn("any", move |arr: rhai::Array, v: T| {
407 let value: C = v.into();
408 arr.iter()
409 .filter(|a| is_call(a))
410 .map(|a| {
411 let a: C = as_call(&a).unwrap().into();
412 a
413 })
414 .filter(|a| *a == value)
415 .into_iter()
416 .count()
417 > 0
418 });
419 self.engine
420 .register_fn("all", move |arr: rhai::Array, v: T| {
421 let value: C = v.into();
422 let expected = arr.len();
423 arr.iter()
424 .filter(|a| is_call(a))
425 .map(|a| {
426 let a: C = as_call(&a).unwrap().into();
427 a
428 })
429 .filter(|a| *a == value)
430 .into_iter()
431 .count()
432 == expected
433 });
434 self.engine
435 .register_fn("none", move |arr: rhai::Array, v: T| {
436 let value: C = v.into();
437 arr.iter()
438 .filter(|a| is_call(a))
439 .map(|a| {
440 let a: C = as_call(&a).unwrap().into();
441 a
442 })
443 .filter(|a| *a == value)
444 .into_iter()
445 .count()
446 == 0
447 });
448 }
449
450 fn register_comparison<
451 A: Variant + Clone + AsCast<C>,
452 B: Variant + Clone + AsCast<C>,
453 C: PartialEq + PartialOrd,
454 >(
455 &mut self,
456 ) {
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 self.engine
468 .register_fn("==", |left: A, right: B| left.as_cast() == right.as_cast());
469
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 self.engine
481 .register_fn("==", |left: B, right: A| left.as_cast() == right.as_cast());
482 }
483
484 fn register_options<T: Variant + Clone>(&mut self) {
485 self.engine
486 .register_fn("is_some", crate::internal::script_is_some::<T>)
487 .register_fn("unwrap", crate::internal::script_unwrap::<T>)
488 .register_fn("unwrap_or", crate::internal::script_unwrap_or::<T>);
489 }
490}
491
492impl FormattingEngine {
493 #[must_use]
503 pub fn new(debug: bool) -> Self {
504 build_engine(debug)
505 }
506
507 pub fn register_type<T: Variant + Clone>(&mut self) -> &mut Self {
520 self.engine.register_type::<T>();
521 self.register_vec::<T>();
522 self.register_options::<T>();
523
524 self
525 }
526
527 pub fn make_comparable<T: Variant + PartialEq + Clone>(&mut self) -> &mut Self {
540 self.register_type::<T>();
541 self.register_options::<T>();
542 self.register_vec::<T>();
543 self.register_fn("any", crate::internal::script_any_type::<T>)
544 .register_fn("all", crate::internal::script_all_type::<T>)
545 .register_fn("none", crate::internal::script_none_type::<T>);
546 self
547 }
548
549 pub fn build_type<T: Variant + CustomType + Clone>(&mut self) -> &mut Self {
580 self.engine.build_type::<T>();
581 self.register_type::<T>();
582 self
583 }
584
585 pub fn format_with_scope(&mut self, scope: &mut Scope, script: &str) -> ScriptResult<String> {
603 scope.push_constant("NL", "\n");
604
605 self.messages.borrow_mut().clear();
606 self.engine.run_with_scope(scope, script)?;
607
608 Ok(self.messages.borrow().join(""))
609 }
610
611 #[cfg(not(feature = "web"))]
629 pub fn format_from_file_with_scope<P: AsRef<Path>>(
630 &mut self,
631 scope: &mut Scope,
632 script: P,
633 ) -> ScriptResult<String> {
634 match std::fs::read_to_string(script.as_ref()) {
635 Ok(script) => self.format_with_scope(scope, &script),
636 Err(e) => Err(e.to_string().into()),
637 }
638 }
639
640 pub fn clone_messages(&self) -> Rc<RefCell<Vec<String>>> {
648 self.messages.clone()
649 }
650
651 pub fn format<T: Variant + Clone>(
669 &mut self,
670 name: &str,
671 data: T,
672 script: &str,
673 ) -> ScriptResult<String> {
674 self.register_type::<T>();
675
676 let mut scope = Scope::new();
677 scope.push_constant(name, data);
678
679 self.format_with_scope(&mut scope, script)
680 }
681
682 #[cfg(not(feature = "web"))]
700 pub fn format_from_file<T: Variant + Clone, P: AsRef<Path>>(
701 &mut self,
702 name: &str,
703 data: T,
704 script: P,
705 ) -> ScriptResult<String> {
706 match std::fs::read_to_string(script.as_ref()) {
707 Ok(script) => self.format(name, data, &script),
708 Err(e) => Err(e.to_string().into()),
709 }
710 }
711}
712
713fn option_to_string<T: std::fmt::Display>(value: Option<T>) -> Option<String> {
714 if let Some(v) = value {
715 Some(format!("{v}"))
716 } else {
717 None
718 }
719}
720
721fn dynamic_to_string(v: Dynamic) -> ScriptResult<Option<String>> {
722 let t = v.type_id();
723 if t == TypeId::of::<()>() {
724 Ok(None)
725 } else if v.is_array() {
726 let flattened = flatten_dynamic(v)?;
727 if flattened.len() > 0 {
728 Ok(Some(flattened.join("")))
729 } else {
730 Ok(None)
731 }
732 } else if t == TypeId::of::<Option<&str>>() {
733 Ok(option_to_string::<&str>(v.cast()))
734 } else if t == TypeId::of::<Option<bool>>() {
735 Ok(option_to_string::<bool>(v.cast()))
736 } else if t == TypeId::of::<Option<i8>>() {
737 Ok(option_to_string::<i8>(v.cast()))
738 } else if t == TypeId::of::<Option<i16>>() {
739 Ok(option_to_string::<i16>(v.cast()))
740 } else if t == TypeId::of::<Option<i32>>() {
741 Ok(option_to_string::<i32>(v.cast()))
742 } else if t == TypeId::of::<Option<i64>>() {
743 Ok(option_to_string::<i64>(v.cast()))
744 } else if t == TypeId::of::<Option<i128>>() {
745 Ok(option_to_string::<i128>(v.cast()))
746 } else if t == TypeId::of::<Option<u8>>() {
747 Ok(option_to_string::<u8>(v.cast()))
748 } else if t == TypeId::of::<Option<u16>>() {
749 Ok(option_to_string::<u16>(v.cast()))
750 } else if t == TypeId::of::<Option<u32>>() {
751 Ok(option_to_string::<u32>(v.cast()))
752 } else if t == TypeId::of::<Option<u64>>() {
753 Ok(option_to_string::<u64>(v.cast()))
754 } else if t == TypeId::of::<Option<f32>>() {
755 Ok(option_to_string::<f32>(v.cast()))
756 } else if t == TypeId::of::<Option<f64>>() {
757 Ok(option_to_string::<f64>(v.cast()))
758 } else if t == TypeId::of::<Option<u128>>() {
759 Ok(option_to_string::<u128>(v.cast()))
760 } else if t == TypeId::of::<Option<char>>() {
761 Ok(option_to_string::<char>(v.cast()))
762 } else if t == TypeId::of::<Option<String>>() {
763 Ok(if let Some(v) = v.cast::<Option<String>>() {
764 Some(v)
765 } else {
766 None
767 })
768 } else if t == TypeId::of::<Option<Dynamic>>() {
769 Ok(if let Some(v) = v.cast::<Option<Dynamic>>() {
770 dynamic_to_string(v)?
771 } else {
772 None
773 })
774 } else if t == TypeId::of::<bool>() {
775 Ok(Some(v.as_bool()?.to_string()))
776 } else if t == TypeId::of::<ImmutableString>() {
777 Ok(Some(v.into_immutable_string()?.to_string()))
778 } else if t == TypeId::of::<char>() {
779 Ok(Some(v.as_char()?.to_string()))
780 } else if t == TypeId::of::<INT>() {
781 Ok(Some(v.as_int()?.to_string()))
782 } else if t == TypeId::of::<FLOAT>() {
783 Ok(Some(v.as_float()?.to_string()))
784 } else {
785 eprintln!("{}", v.type_name());
786 Err("unsupported type".into())
787 }
788}
789
790fn flatten_dynamic(vs: Dynamic) -> Result<Vec<String>, Box<EvalAltResult>> {
791 let mut res = Vec::new();
792 if vs.is_array() {
793 for v in vs.into_array()? {
794 if v.is_array() {
795 let mut values = flatten_dynamic(v)?;
796 res.append(&mut values);
797 } else {
798 if let Some(s) = dynamic_to_string(v)? {
799 res.push(s);
800 }
801 }
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
822 engine.register_global_module(package.as_shared_module());
823
824 {
826 let messages = engine.clone_messages();
827 engine
828 .register_custom_syntax(
829 ["~", "$expr$"],
830 true,
831 move |context: &mut rhai::EvalContext,
832 inputs: &[rhai::Expression]|
833 -> ScriptResult<Dynamic> {
834 for e in inputs {
835 let result = context.eval_expression_tree(&e)?;
836 let mut m = flatten_dynamic(result)?;
837 messages.borrow_mut().append(&mut m);
838 }
839 Ok(Dynamic::UNIT)
840 },
841 )
842 .unwrap();
843 }
844
845 let indent = Rc::new(RefCell::new(" ".to_owned()));
846
847 {
848 let indent = indent.clone();
849
850 #[allow(deprecated)]
852 engine.on_var(move |name, _, _| match name {
853 "IND" => Ok(Some(indent.borrow().clone().into())),
854 _ => Ok(None),
855 });
856 }
857
858 {
859 let indent = indent.clone();
860 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
861 engine.register_fn("IND", move |count: i64| {
862 indent.borrow().repeat(count as usize)
863 });
864 }
865
866 {
867 let indent = indent.clone();
868 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
869 engine.register_fn("SET_INDENT", move |value: &str| {
870 value.clone_into(&mut indent.borrow_mut());
871 });
872 }
873
874 {
875 let indent = indent.clone();
876 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
877 engine.register_fn("SET_INDENT", move |value: &str, count: i64| {
878 *indent.borrow_mut() = value.repeat(count as usize)
879 });
880 }
881
882 {
883 let indent = indent.clone();
884 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
885 engine.register_fn("SET_INDENT", move |count: i64| {
886 *indent.borrow_mut() = " ".repeat(count as usize)
887 });
888 }
889
890 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
891 engine.register_fn("NL", |count: i64| "\n".repeat(count as usize));
892
893 engine.register_iterator::<Vec<serde_value::Value>>();
894
895 engine.register_options::<&str>();
896 engine.register_options::<String>();
897 engine.register_options::<bool>();
898 engine.register_options::<i64>();
899 engine.register_options::<u64>();
900 engine.register_options::<i32>();
901 engine.register_options::<u32>();
902 engine.register_options::<i16>();
903 engine.register_options::<u16>();
904 engine.register_options::<i8>();
905 engine.register_options::<u8>();
906 engine.register_options::<usize>();
907 engine.register_options::<isize>();
908 engine.register_options::<i128>();
909 engine.register_options::<u128>();
910 engine.register_options::<f32>();
911 engine.register_options::<f64>();
912
913 engine.register_type_dynamic::<i8, i64>(Dynamic::is_int, Dynamic::as_int);
914 engine.register_type_dynamic::<i16, i64>(Dynamic::is_int, Dynamic::as_int);
915 engine.register_type_dynamic::<i32, i64>(Dynamic::is_int, Dynamic::as_int);
916 engine.register_type_dynamic::<i64, i64>(Dynamic::is_int, Dynamic::as_int);
917
918 engine.register_type_dynamic::<u8, i64>(Dynamic::is_int, Dynamic::as_int);
919 engine.register_type_dynamic::<u16, i64>(Dynamic::is_int, Dynamic::as_int);
920 engine.register_type_dynamic::<u32, i64>(Dynamic::is_int, Dynamic::as_int);
921
922 engine.register_type_dynamic::<f32, f64>(Dynamic::is_float, Dynamic::as_float);
923 engine.register_type_dynamic::<f64, f64>(Dynamic::is_float, Dynamic::as_float);
924
925 engine.register_type_dynamic::<bool, bool>(Dynamic::is_bool, Dynamic::as_bool);
926
927 fn dynamic_as_string(dynamic: &Dynamic) -> Result<String, &'static str> {
928 dynamic.to_owned().into_string()
929 }
930
931 engine.register_type_dynamic::<String, String>(Dynamic::is_string, dynamic_as_string);
932 engine.register_type_dynamic::<&str, String>(Dynamic::is_string, dynamic_as_string);
933
934 engine
935 .register_fn("join", crate::internal::script_join)
936 .register_fn("split", crate::internal::script_split)
937 .register_fn("splitn", crate::internal::script_splitn)
938 .register_fn("rsplitn", crate::internal::script_rsplitn)
939 .register_fn("is_empty", crate::internal::script_string_is_empty)
940 .register_fn("is_empty", crate::internal::script_array_is_empty)
941 .register_fn("starts_with", crate::internal::script_starts_with)
942 .register_fn("ends_with", crate::internal::script_ends_with)
943 .register_fn("trim", crate::internal::script_trim)
944 .register_fn("is_string", crate::internal::script_is_no_string)
945 .register_fn("is_string", crate::internal::script_is_string);
946
947 engine.build_type::<ToBe>();
949 engine
950 .register_custom_operator("zip", 65)
951 .unwrap()
952 .register_custom_operator("to_be", 60)
953 .unwrap()
954 .register_custom_operator("and", 60)
955 .unwrap()
956 .register_fn("and", |a: bool, b: bool| a && b)
957 .register_custom_operator("or", 30)
958 .unwrap()
959 .register_fn("or", |a: bool, b: bool| a || b)
960 .register_custom_operator("xor", 30)
961 .unwrap()
962 .register_fn("xor", |a: bool, b: bool| a ^ b)
963 .register_custom_operator("contains", 25)
964 .unwrap()
965 .register_custom_operator("equals", 25)
966 .unwrap()
967 .register_custom_operator("require", 25)
968 .unwrap()
969 .register_custom_operator("any", 25)
970 .unwrap()
971 .register_custom_operator("all", 25)
972 .unwrap()
973 .register_custom_operator("none", 25)
974 .unwrap()
975 .register_fn("contains", crate::internal::script_map_contains)
976 .register_fn("contains", crate::internal::script_string_contains)
977 .register_fn("equals", crate::internal::script_map_equals)
978 .register_fn("equals", crate::internal::script_value_equals)
979 .register_fn("equals", crate::internal::script_array_equals)
980 .register_fn("contains", crate::internal::script_array_contains)
981 .register_fn("require", crate::internal::script_require)
982 .register_fn("to_be", crate::internal::script_to_be)
983 .register_fn("any", crate::internal::script_any)
984 .register_fn("any", crate::internal::script_any_void)
985 .register_fn("all", crate::internal::script_all)
986 .register_fn("all", crate::internal::script_all_void)
987 .register_fn("none", crate::internal::script_none)
988 .register_fn("none", crate::internal::script_none_void);
989
990 engine.register_msg_single::<&str>();
991 engine.register_msg_single::<String>();
992 engine.register_msg_single::<bool>();
993 engine.register_msg_single::<i64>();
994 engine.register_msg_single::<u64>();
995 engine.register_msg_single::<i32>();
996 engine.register_msg_single::<u32>();
997 engine.register_msg_single::<i16>();
998 engine.register_msg_single::<u16>();
999 engine.register_msg_single::<i8>();
1000 engine.register_msg_single::<u8>();
1001 engine.register_msg_single::<usize>();
1002 engine.register_msg_single::<isize>();
1003 engine.register_msg_single::<i128>();
1004 engine.register_msg_single::<u128>();
1005 engine.register_msg_single::<f32>();
1006 engine.register_msg_single::<f64>();
1007
1008 engine.register_msg::<&str>();
1009 engine.register_msg::<String>();
1010 engine.register_msg::<bool>();
1011 engine.register_msg::<i64>();
1012 engine.register_msg::<u64>();
1013 engine.register_msg::<i32>();
1014 engine.register_msg::<u32>();
1015 engine.register_msg::<i16>();
1016 engine.register_msg::<u16>();
1017 engine.register_msg::<i8>();
1018 engine.register_msg::<u8>();
1019 engine.register_msg::<usize>();
1020 engine.register_msg::<isize>();
1021 engine.register_msg::<i128>();
1022 engine.register_msg::<u128>();
1023 engine.register_msg::<f32>();
1024 engine.register_msg::<f64>();
1025
1026 engine.register_comparison::<u8, u8, u8>();
1027 engine.register_comparison::<u8, u16, u16>();
1028 engine.register_comparison::<u8, u32, u32>();
1029 engine.register_comparison::<u8, u64, u64>();
1030 engine.register_comparison::<u8, usize, u128>();
1031 engine.register_comparison::<u8, u128, u128>();
1032
1033 engine.register_comparison::<u16, u16, u16>();
1034 engine.register_comparison::<u16, u32, u32>();
1035 engine.register_comparison::<u16, u64, u64>();
1036 engine.register_comparison::<u16, usize, u128>();
1037 engine.register_comparison::<u16, u128, u128>();
1038
1039 engine.register_comparison::<u32, u32, u32>();
1040 engine.register_comparison::<u32, u64, u64>();
1041 engine.register_comparison::<u32, usize, u128>();
1042 engine.register_comparison::<u32, u128, u128>();
1043
1044 engine.register_comparison::<u64, u64, u64>();
1045 engine.register_comparison::<u64, usize, u128>();
1046 engine.register_comparison::<u64, u128, u128>();
1047
1048 engine.register_comparison::<usize, usize, u128>();
1049 engine.register_comparison::<usize, u128, u128>();
1050
1051 engine.register_comparison::<u128, u128, u128>();
1052
1053 engine.register_comparison::<i8, i8, i8>();
1054 engine.register_comparison::<i8, i16, i16>();
1055 engine.register_comparison::<i8, i32, i32>();
1056 engine.register_comparison::<i8, i64, i64>();
1057 engine.register_comparison::<i8, isize, i128>();
1058 engine.register_comparison::<i8, i128, i128>();
1059
1060 engine.register_comparison::<i16, i16, i16>();
1061 engine.register_comparison::<i16, i32, i32>();
1062 engine.register_comparison::<i16, i64, i64>();
1063 engine.register_comparison::<i8, isize, i128>();
1064 engine.register_comparison::<i16, i128, i128>();
1065
1066 engine.register_comparison::<i32, i32, i32>();
1067 engine.register_comparison::<i32, i64, i64>();
1068 engine.register_comparison::<i32, isize, i128>();
1069 engine.register_comparison::<i32, i128, i128>();
1070
1071 engine.register_comparison::<i64, i64, i64>();
1072 engine.register_comparison::<i64, isize, i128>();
1073 engine.register_comparison::<i64, i128, i128>();
1074
1075 engine.register_comparison::<isize, isize, i128>();
1076 engine.register_comparison::<isize, i128, i128>();
1077
1078 engine.register_comparison::<i128, i128, i128>();
1079
1080 engine.register_comparison::<f32, f32, f32>();
1081 engine.register_comparison::<f32, f64, f64>();
1082
1083 engine.register_comparison::<u8, f32, f32>();
1084 engine.register_comparison::<u16, f32, f32>();
1085 engine.register_comparison::<u32, f64, f64>();
1086
1087 engine.register_comparison::<i8, f32, f32>();
1088 engine.register_comparison::<i16, f32, f32>();
1089 engine.register_comparison::<i32, f64, f64>();
1090
1091 engine.register_value::<&str>();
1092 engine.register_value::<String>();
1093 engine.register_value::<bool>();
1094 engine.register_value::<i64>();
1095 engine.register_value::<u64>();
1096 engine.register_value::<i32>();
1097 engine.register_value::<u32>();
1098 engine.register_value::<i16>();
1099 engine.register_value::<u16>();
1100 engine.register_value::<i8>();
1101 engine.register_value::<u8>();
1102 engine.register_value::<usize>();
1103 engine.register_value::<isize>();
1104 engine.register_value::<i128>();
1105 engine.register_value::<u128>();
1106 engine.register_value::<f32>();
1107 engine.register_value::<f64>();
1108
1109 {
1110 let messages = engine.clone_messages();
1111 engine.register_fn("-", move |msg: Dynamic| -> ScriptResult<()> {
1112 minus_deprecation();
1113 if msg.is_array() {
1114 let arr = msg.into_array().unwrap();
1115 for m in arr {
1116 if let Some(msg) = dynamic_to_string(m)? {
1117 messages.borrow_mut().push(msg);
1118 }
1119 }
1120 } else {
1121 if let Some(msg) = dynamic_to_string(msg)? {
1122 messages.borrow_mut().push(msg);
1123 }
1124 }
1125 Ok(())
1126 });
1127 }
1128
1129 {
1130 let messages = engine.clone_messages();
1131 engine.register_fn("-", move |msg: serde_value::Value| {
1132 minus_deprecation();
1133 messages
1134 .borrow_mut()
1135 .push(serde_json::to_string(&msg).unwrap());
1136 });
1137 }
1138
1139 engine.register_fn("++", move |a: serde_value::Value, b: serde_value::Value| {
1140 vec![
1141 serde_json::to_string(&a).unwrap(),
1142 serde_json::to_string(&b).unwrap(),
1143 ]
1144 });
1145
1146 engine.register_concat::<&str>();
1147 engine.register_concat::<String>();
1148 engine.register_concat::<bool>();
1149 engine.register_concat::<i64>();
1150 engine.register_concat::<u64>();
1151 engine.register_concat::<i32>();
1152 engine.register_concat::<u32>();
1153 engine.register_concat::<i16>();
1154 engine.register_concat::<u16>();
1155 engine.register_concat::<i8>();
1156 engine.register_concat::<u8>();
1157 engine.register_concat::<usize>();
1158 engine.register_concat::<isize>();
1159 engine.register_concat::<i128>();
1160 engine.register_concat::<u128>();
1161 engine.register_concat::<f32>();
1162 engine.register_concat::<f64>();
1163
1164 engine.register_vec_printable::<&str>();
1165 engine.register_vec_printable::<String>();
1166 engine.register_vec_printable::<bool>();
1167 engine.register_vec_printable::<i64>();
1168 engine.register_vec_printable::<u64>();
1169 engine.register_vec_printable::<i32>();
1170 engine.register_vec_printable::<u32>();
1171 engine.register_vec_printable::<i16>();
1172 engine.register_vec_printable::<u16>();
1173 engine.register_vec_printable::<i8>();
1174 engine.register_vec_printable::<u8>();
1175 engine.register_vec_printable::<usize>();
1176 engine.register_vec_printable::<isize>();
1177 engine.register_vec_printable::<i128>();
1178 engine.register_vec_printable::<u128>();
1179 engine.register_vec_printable::<f32>();
1180 engine.register_vec_printable::<f64>();
1181
1182 engine.register_vec::<()>();
1183
1184 engine
1185 .register_fn("any", crate::internal::script_any_type::<bool>)
1186 .register_fn("all", crate::internal::script_any_type::<bool>)
1187 .register_fn("none", crate::internal::script_any_type::<bool>)
1188 .register_fn("++", move |(): (), b: &str| vec![b.to_owned()])
1189 .register_fn("++", move |(): (), b: usize| vec![b.to_string()])
1190 .register_custom_operator("++", 15)
1191 .unwrap()
1192 .register_custom_operator("then_emit", 20)
1193 .unwrap()
1194 .register_fn(
1195 "then_emit",
1196 move |a: bool, msg: &str| {
1197 if a {
1198 Some(msg.to_owned())
1199 } else {
1200 None
1201 }
1202 },
1203 )
1204 .register_custom_operator("or_emit", 20)
1205 .unwrap()
1206 .register_fn(
1207 "or_emit",
1208 move |a: bool, msg: &str| {
1209 if !a {
1210 Some(msg.to_owned())
1211 } else {
1212 None
1213 }
1214 },
1215 );
1216 if debug {
1219 engine.on_print(move |x| eprintln!("INFO => {x}"));
1220 engine.on_debug(move |x, _, pos| eprintln!("DEBUG({pos:?}) => {x}"));
1221 } else {
1222 engine.on_print(|_| ());
1223 engine.on_debug(|_, _, _| ());
1224 }
1225
1226 engine.disable_symbol("eval");
1227
1228 engine
1229}
1230
1231macro_rules! impl_as_cast {
1232 ($A: ty, ($($B: ty),*)) => {
1233 $(
1234 impl AsCast<$B> for $A {
1235 fn as_cast(self) -> $B {
1236 self as $B
1237 }
1238 }
1239 )*
1240 }
1241}
1242
1243trait AsCast<T> {
1244 fn as_cast(self) -> T;
1245}
1246
1247impl_as_cast!(u8, (u8, u16, u32, u64, u128, usize));
1248impl_as_cast!(i8, (i8, i16, i32, i64, i128, isize));
1249
1250impl_as_cast!(u16, (u16, u32, u64, u128, usize));
1251impl_as_cast!(i16, (i16, i32, i64, i128, isize));
1252
1253impl_as_cast!(u32, (u32, u64, u128, usize));
1254impl_as_cast!(i32, (i32, i64, i128, isize));
1255
1256impl_as_cast!(u64, (u64, u128));
1257impl_as_cast!(i64, (i64, i128));
1258
1259impl_as_cast!(usize, (usize, u128));
1260impl_as_cast!(isize, (isize, i128));
1261
1262impl_as_cast!(u128, (u128));
1263impl_as_cast!(i128, (i128));
1264
1265impl_as_cast!(f32, (f32, f64));
1266impl_as_cast!(f64, (f64));
1267
1268impl_as_cast!(u8, (f32, f64));
1269impl_as_cast!(u16, (f32, f64));
1270impl_as_cast!(u32, (f64));
1271
1272impl_as_cast!(i8, (f32, f64));
1273impl_as_cast!(i16, (f32, f64));
1274impl_as_cast!(i32, (f64));