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
use {
crate::{Convert, Result, Value, ValueError},
std::cmp::min,
};
macro_rules! protect_null {
($protect: expr) => {
if matches!($protect, Value::Null) {
return Ok($protect);
}
};
}
impl Value {
pub fn if_null(self, alternative: Self) -> Self {
if !matches!(self, Value::Null) {
self
} else {
alternative
}
}
pub fn null_if(self, evaluate: Self) -> Result<Self> {
Ok(if self == evaluate { Value::Null } else { self })
}
pub fn iif(self, case_true: Self, case_false: Self) -> Result<Self> {
Ok(if self.convert()? {
case_true
} else {
case_false
})
}
pub fn to_uppercase(self) -> Result<Self> {
protect_null!(self);
let string: String = self.convert()?;
Ok(string.to_uppercase().into())
}
pub fn to_lowercase(self) -> Result<Self> {
protect_null!(self);
let string: String = self.convert()?;
Ok(string.to_lowercase().into())
}
pub fn left(self, length: Value) -> Result<Value> {
protect_null!(self);
protect_null!(length);
let length: i64 = length.convert()?;
if length < 0 {
return Err(ValueError::BadInput(length.into()).into());
}
let length: usize = length as usize;
let string: String = self.convert()?;
let truncated = string
.get(..length)
.map(|result| result.to_string())
.unwrap_or(string);
Ok(Value::Str(truncated))
}
pub fn right(self, length: Value) -> Result<Value> {
protect_null!(self);
protect_null!(length);
let length: i64 = length.convert()?;
if length < 0 {
return Err(ValueError::BadInput(length.into()).into());
}
let length: usize = length as usize;
let string: String = self.convert()?;
let truncated = string
.get(string.len() - min(string.len(), length)..)
.map(|result| result.to_string())
.unwrap_or(string);
Ok(Value::Str(truncated))
}
pub fn length(self) -> Result<Value> {
let string: String = self.convert()?;
Ok(Value::I64(string.len() as i64))
}
pub fn concat(self, strings: Vec<Value>) -> Result<Value> {
strings
.into_iter()
.try_fold(self, |all, this| all.string_concat(this))
}
pub fn replace(self, from: Value, to: Value) -> Result<Value> {
protect_null!(self);
let string: String = self.convert()?;
let from: String = from.convert()?;
let to: String = to.convert()?;
Ok(string.replace(&from, &to).into())
}
pub fn round(self, places: Value) -> Result<Value> {
if matches!(self, Value::Null) {
return Ok(self);
}
let value: f64 = self.convert()?;
let places: i64 = places.convert()?;
let raiser: f64 = 10_u32.pow(places as u32).into();
Ok(Value::F64((value * raiser).round() / raiser))
}
pub fn pow(self, power: Value) -> Result<Value> {
let value: f64 = self.convert()?;
let power: f64 = power.convert()?;
Ok(Value::F64(value.powf(power)))
}
}