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
pub fn escape(source: &str) -> String {
let mut out = String::with_capacity(source.len());
for character in source.chars() {
match character {
'<' => out.push_str("<"),
'>' => out.push_str(">"),
'&' => out.push_str("&"),
'"' => out.push_str("""),
'\'' => out.push_str("'"),
_ => out.push(character),
}
}
out
}
pub fn number(value: f64) -> String {
let size = value.abs();
let digits = if size >= 1.0 {
3
} else if size >= 0.1 {
4
} else if size >= 0.01 {
5
} else if size >= 0.001 {
6
} else {
8
};
let step = 10f64.powi(digits);
let rounded = (value * step).round() / step;
let positive_zero = if rounded == 0.0 { 0.0 } else { rounded };
let mut out = format!("{positive_zero:.*}", digits as usize);
while out.ends_with('0') {
out.pop();
}
if out.ends_with('.') {
out.pop();
}
out
}
pub fn spacing_mark(character: char) -> char {
match character {
'\u{300}' => '\u{60}',
'\u{301}' => '\u{b4}',
'\u{302}' => '\u{2c6}',
'\u{303}' => '\u{2dc}',
'\u{304}' => '\u{af}',
'\u{306}' => '\u{2d8}',
'\u{307}' => '\u{2d9}',
'\u{308}' => '\u{a8}',
'\u{30c}' => '\u{2c7}',
'\u{20d7}' => '\u{2192}',
other => other,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn escapes_markup() {
assert_eq!(escape("a<b & c>\"d\""), "a<b & c>"d"");
}
#[test]
fn trims_trailing_zeros() {
assert_eq!(number(1.5), "1.5");
assert_eq!(number(2.0), "2");
assert_eq!(number(-0.0), "0");
assert_eq!(number(1.23456), "1.235");
}
#[test]
fn small_values_keep_their_digits() {
assert_eq!(number(1.0 / 2048.0), "0.00048828");
assert_eq!(number(1.0 / 1000.0), "0.001");
assert_eq!(number(0.12345), "0.1235");
}
}