reductstore/storage/query/condition/operators/arithmetic/
div.rs1use crate::storage::query::condition::value::Div as DivTrait;
5use crate::storage::query::condition::value::Value;
6use crate::storage::query::condition::{Boxed, BoxedNode, Context, Node};
7use reduct_base::error::ReductError;
8use reduct_base::unprocessable_entity;
9
10pub(crate) struct Div {
12 operands: Vec<BoxedNode>,
13}
14
15impl Node for Div {
16 fn apply(&mut self, context: &Context) -> Result<Value, ReductError> {
17 let value_1 = self.operands[0].apply(context)?;
18 let value_2 = self.operands[1].apply(context)?;
19 value_1.divide(value_2)
20 }
21
22 fn print(&self) -> String {
23 format!("Div({:?}, {:?})", self.operands[0], self.operands[1])
24 }
25}
26
27impl Boxed for Div {
28 fn boxed(operands: Vec<BoxedNode>) -> Result<BoxedNode, ReductError> {
29 if operands.len() != 2 {
30 return Err(unprocessable_entity!("$div requires exactly two operands"));
31 }
32
33 Ok(Box::new(Div::new(operands)))
34 }
35}
36
37impl Div {
38 pub fn new(operands: Vec<BoxedNode>) -> Self {
39 Self { operands }
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use crate::storage::query::condition::constant::Constant;
47 use crate::storage::query::condition::value::Value;
48 use rstest::rstest;
49
50 #[rstest]
51 fn apply_ok() {
52 let mut sub = Div::new(vec![
53 Constant::boxed(Value::Int(1)),
54 Constant::boxed(Value::Int(2)),
55 ]);
56 assert_eq!(sub.apply(&Context::default()).unwrap(), Value::Float(0.5));
57 }
58
59 #[rstest]
60 fn apply_bad() {
61 let mut sub = Div::new(vec![
62 Constant::boxed(Value::Int(1)),
63 Constant::boxed(Value::String("foo".to_string())),
64 ]);
65 assert_eq!(
66 sub.apply(&Context::default()),
67 Err(unprocessable_entity!("Cannot divide by string"))
68 );
69 }
70
71 #[rstest]
72 fn apply_empty() {
73 let op = Div::boxed(vec![]);
74 assert_eq!(
75 op.err(),
76 Some(unprocessable_entity!("$div requires exactly two operands"))
77 );
78 }
79
80 #[rstest]
81 fn print() {
82 let op = Div::new(vec![
83 Constant::boxed(Value::Bool(true)),
84 Constant::boxed(Value::Bool(true)),
85 ]);
86 assert_eq!(op.print(), "Div(Bool(true), Bool(true))");
87 }
88}