multisql/data/value/methods/
utility.rs

1use {
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}