-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathnumber.rs
More file actions
127 lines (111 loc) · 3.45 KB
/
number.rs
File metadata and controls
127 lines (111 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::ValueKind;
pub(super) fn to_int<'bp>(args: &[ValueKind<'bp>]) -> ValueKind<'bp> {
if args.len() != 1 {
return ValueKind::Null;
}
match &args[0] {
ValueKind::Int(i) => ValueKind::Int(*i),
ValueKind::Float(f) => ValueKind::Int(*f as i64),
ValueKind::Bool(b) if !b => ValueKind::Int(0),
ValueKind::Bool(_) => ValueKind::Int(1),
ValueKind::Char(c) => match c.to_digit(10) {
Some(i) => ValueKind::Int(i as i64),
None => ValueKind::Null,
},
ValueKind::Hex(hex) => ValueKind::Int(hex.as_u32() as i64),
ValueKind::Str(s) => match s.parse() {
Ok(i) => ValueKind::Int(i),
Err(_) => ValueKind::Null,
},
ValueKind::Color(_)
| ValueKind::Null
| ValueKind::Map
| ValueKind::Attributes
| ValueKind::List(_)
| ValueKind::DynList(_)
| ValueKind::DynMap(_)
| ValueKind::Range(..)
| ValueKind::Composite(_) => ValueKind::Null,
}
}
pub(super) fn to_float<'bp>(args: &[ValueKind<'bp>]) -> ValueKind<'bp> {
if args.len() != 1 {
return ValueKind::Null;
}
match &args[0] {
ValueKind::Int(i) => ValueKind::Float(*i as f64),
ValueKind::Float(f) => ValueKind::Float(*f),
ValueKind::Bool(b) if !b => ValueKind::Float(0.0),
ValueKind::Bool(_) => ValueKind::Float(1.0),
ValueKind::Char(c) => match c.to_digit(10) {
Some(i) => ValueKind::Float(i as f64),
None => ValueKind::Null,
},
ValueKind::Hex(hex) => ValueKind::Float(hex.as_u32() as f64),
ValueKind::Str(s) => match s.parse() {
Ok(i) => ValueKind::Float(i),
Err(_) => ValueKind::Null,
},
_ => ValueKind::Null,
}
}
pub(super) fn round<'bp>(args: &[ValueKind<'bp>]) -> ValueKind<'bp> {
if args.is_empty() || args.len() > 2 {
return ValueKind::Null;
}
let precision = match to_int(&args[1..]) {
ValueKind::Int(i) => i as usize,
_ => 0,
};
match &args[0] {
ValueKind::Float(f) => ValueKind::Str(format!("{f:.precision$}").into()),
_ => ValueKind::Null,
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::functions::test::value;
#[test]
fn str_to_int() {
let arg = value("123");
let output = to_int(&[arg]);
assert_eq!(ValueKind::Int(123), output);
let arg = value("not a number");
let output = to_int(&[arg]);
assert_eq!(ValueKind::Null, output);
}
#[test]
fn char_to_int() {
let arg = value('4');
let output = to_int(&[arg]);
assert_eq!(ValueKind::Int(4), output);
let arg = value('G');
let output = to_int(&[arg]);
assert_eq!(ValueKind::Null, output);
}
#[test]
fn float_to_int() {
let arg = value(1.1234);
let output = to_int(&[arg]);
assert_eq!(ValueKind::Int(1), output);
}
#[test]
fn rounding_default_zero() {
let args = [value(1.1234)];
let output = round(&args);
assert_eq!(value("1"), output);
}
#[test]
fn rounding_with_arg() {
let args = [value(1.1234), value(2)];
let output = round(&args);
assert_eq!(value("1.12"), output);
}
#[test]
fn invalid_rounding() {
let args = [value("1.1234"), value(2)];
let output = round(&args);
assert_eq!(ValueKind::Null, output);
}
}