synthphonia/text/formatting/
mod.rs

1use crate::{expr::ops::Op1Enum, galloc, value::{consts_to_value, ConstValue, Value}};
2
3
4trait FormattingOp where Self: Sized {
5    fn format(&self, input: &'static str) -> Option<(Self, ConstValue, &'static str)>;
6    fn union(self, other: Self) -> Option<Self>;
7    fn bad_value() -> ConstValue;
8    fn format_all(&self, input: &'static [&'static str]) -> Option<(Self, Value, Value, Value)> {
9        let mut a = Vec::with_capacity(input.len());
10        let mut b = galloc::new_bvec(input.len());
11        let mut cond = galloc::new_bvec(input.len());
12        let mut newop: Option<Self> = None;
13        for i in input {
14            if let Some((op, x, y)) = self.format(i) {
15                if let Some(no) = newop {
16                    newop = no.union(op);
17                    newop.as_ref()?;
18                } else { newop = Some(op); }
19                a.push(x);
20                b.push(y);
21                cond.push(true);
22            } else {
23                a.push(Self::bad_value());
24                b.push(i);
25                cond.push(false);
26            }
27        }
28        newop.map(|no| (no, consts_to_value(a), Value::Str(b.into_bump_slice()), cond.into_bump_slice().into()))
29    }
30}
31
32use ext_trait::extension;
33pub mod int;
34pub use int::*;
35pub mod float;
36pub use float::*;
37pub mod time;
38pub use time::*;
39pub mod month;
40pub use month::*;
41
42pub mod weekday;
43pub use weekday::*;
44
45#[macro_export]
46macro_rules! for_all_formatting_op {
47    () => {
48        _do!(FormatInt);
49        _do!(FormatFloat);
50        _do!(FormatTime);
51        _do!(FormatMonth);
52        _do!(FormatWeekday);
53    };
54}
55
56
57impl Op1Enum {
58    pub fn is_formatting_op(&self) -> bool {
59        macro_rules! _do {($op:ident) => {
60            if let Self::$op(_) = self { return true }
61        };}
62        crate::for_all_formatting_op!();
63        false
64    }
65    pub fn format_all(&self, input: &'static [&'static str]) -> Option<(Op1Enum, Value, Value, Value)> {
66        macro_rules! _do {($op:ident) => {
67            if let Self::$op(op) = self { return op.format_all(input).map(|(a, b, c, d)| (a.into(), b, c, d)); }
68        };}
69        crate::for_all_formatting_op!();
70        panic!();
71    }
72}
73
74#[macro_export]
75macro_rules! impl_formatop {
76    ($opname:ident, $t:ident, $costf:expr) => {
77        impl $crate::expr::ops::Op1 for $opname {
78            fn cost(&self) -> usize {
79                $costf(self)
80            }
81            fn try_eval(&self,a1:$crate::value::Value) -> (bool, $crate::value::Value) {
82                match a1 {
83                    Value::$t(s) => (true, Value::Str(s.iter().map(|s1| {
84                        self.format_single(*s1).galloc_str()
85                    }).galloc_scollect())),
86                    _ => (false, Value::Null),
87                }
88            }
89        }
90    };
91}