synthphonia/text/formatting/
int.rs1use std::cmp::max;
2
3use itertools::Format;
4use regex::Regex;
5
6use crate::forward::enumeration::Enumerator1;
7use crate::value::{ConstValue, Value};
8use crate::{ impl_name, impl_op1, parser::config::Config};
9
10use crate::galloc::{AllocForExactSizeIter, AllocForStr};
11
12use super::FormattingOp;
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub struct FormatInt(usize, usize);
15
16impl FormatInt {
17 pub fn from_config(config: &Config) -> Self {
18 Self(config.get_usize("cost").unwrap_or(1), config.get_usize("width").unwrap_or(1))
19 }
20 pub fn format_single(&self, value: i64) -> String {
21 if self.1 > 0 {
22 format!("{:0left$}", value, left= self.1)
23 } else { format!("{}", value) }
24 }
25 pub fn get_format(input: &str) -> Self {
26 let startzero = input.starts_with("+0") || input.starts_with("-0") || input.starts_with("0");
27 let before_dot = if startzero { input.len() } else { 0 };
28 Self(1, before_dot)
29 }
30}
31
32impl FormatInt {
33 pub fn name() -> &'static str {
34 "int.fmt"
35 }
36}
37
38impl std::fmt::Display for FormatInt {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(f, "int.fmt #left:{}", self.1)
41 }
42}
43
44impl Default for FormatInt {
45 fn default() -> Self {
46 Self::from_config(&Default::default())
47 }
48}
49
50impl Enumerator1 for FormatInt {
51 fn enumerate(&self, this: &'static crate::expr::ops::Op1Enum, exec: &'static crate::forward::executor::Executor, opnt: [usize; 1]) -> Result<(), ()> { Ok(()) }
52}
53
54crate::impl_formatop!(FormatInt, Int, |this: &FormatInt| this.0);
55
56fn conflict(a: usize, b: usize) -> Option<usize> {
57 if a > 0 && b > 0 && a != b { return None; }
58 Some(max(a, b))
59}
60
61impl FormattingOp for FormatInt {
62 fn format(&self, input: &'static str) -> Option<(Self, crate::value::ConstValue, &'static str)> {
63 let regex = Regex::new(r"^ *(\-|\+)? *\d+".to_string().as_str()).unwrap();
64 if let Some(a) = regex.find(input) {
65 let cv: ConstValue = a.as_str().parse::<i64>().ok()?.into();
66 Some((FormatInt::get_format(a.as_str()), cv, &input[a.as_str().len()..]))
67 } else { None }
68 }
69
70 fn union(self, other: Self) -> Option<Self> {
71 Some(Self(1, conflict(self.1, other.1)?))
72 }
73
74 fn bad_value() -> crate::value::ConstValue {
75 crate::value::ConstValue::Int(0)
76 }
77}