multisql/data/value/methods/
utility.rs1use {
2 crate::{Convert, Result, Value, ValueError},
3 std::cmp::min,
4};
5
6macro_rules! protect_null {
7 ($protect: expr) => {
8 if matches!($protect, Value::Null) {
9 return Ok($protect);
10 }
11 };
12}
13
14impl Value {
15 pub fn if_null(self, alternative: Self) -> Self {
16 if !matches!(self, Value::Null) {
17 self
18 } else {
19 alternative
20 }
21 }
22 pub fn null_if(self, evaluate: Self) -> Result<Self> {
23 Ok(if self == evaluate { Value::Null } else { self })
24 }
25 pub fn iif(self, case_true: Self, case_false: Self) -> Result<Self> {
26 Ok(if self.convert()? {
27 case_true
28 } else {
29 case_false
30 })
31 }
32
33 pub fn to_uppercase(self) -> Result<Self> {
34 protect_null!(self);
35 let string: String = self.convert()?;
36 Ok(string.to_uppercase().into())
37 }
38 pub fn to_lowercase(self) -> Result<Self> {
39 protect_null!(self);
40 let string: String = self.convert()?;
41 Ok(string.to_lowercase().into())
42 }
43 pub fn left(self, length: Value) -> Result<Value> {
44 protect_null!(self);
45 protect_null!(length);
46 let length: i64 = length.convert()?;
47 if length < 0 {
48 return Err(ValueError::BadInput(length.into()).into());
49 }
50 let length: usize = length as usize;
51 let string: String = self.convert()?;
52
53 let truncated = string
54 .get(..length)
55 .map(|result| result.to_string())
56 .unwrap_or(string);
57 Ok(Value::Str(truncated))
58 }
59 pub fn right(self, length: Value) -> Result<Value> {
60 protect_null!(self);
61 protect_null!(length);
62 let length: i64 = length.convert()?;
63 if length < 0 {
64 return Err(ValueError::BadInput(length.into()).into());
65 }
66 let length: usize = length as usize;
67 let string: String = self.convert()?;
68
69 let truncated = string
70 .get(string.len() - min(string.len(), length)..)
71 .map(|result| result.to_string())
72 .unwrap_or(string);
73 Ok(Value::Str(truncated))
74 }
75 pub fn length(self) -> Result<Value> {
76 let string: String = self.convert()?;
77 Ok(Value::I64(string.len() as i64))
78 }
79
80 pub fn concat(self, strings: Vec<Value>) -> Result<Value> {
81 strings
82 .into_iter()
83 .try_fold(self, |all, this| all.string_concat(this))
84 }
85
86 pub fn replace(self, from: Value, to: Value) -> Result<Value> {
87 protect_null!(self);
88 let string: String = self.convert()?;
89 let from: String = from.convert()?;
90 let to: String = to.convert()?;
91
92 Ok(string.replace(&from, &to).into())
93 }
94
95 pub fn round(self, places: Value) -> Result<Value> {
96 if matches!(self, Value::Null) {
97 return Ok(self);
98 }
99 let value: f64 = self.convert()?;
100 let places: i64 = places.convert()?;
101 let raiser: f64 = 10_u32.pow(places as u32).into();
102 Ok(Value::F64((value * raiser).round() / raiser))
103 }
104 pub fn pow(self, power: Value) -> Result<Value> {
105 let value: f64 = self.convert()?;
106 let power: f64 = power.convert()?;
107 Ok(Value::F64(value.powf(power)))
108 }
109}