#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::*;
#[derive(Clone)]
pub struct When {
condition: Expr,
}
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Then {
condition: Expr,
statement: Expr,
}
#[derive(Clone)]
pub struct ChainedWhen {
conditions: Vec<Expr>,
statements: Vec<Expr>,
}
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ChainedThen {
conditions: Vec<Expr>,
statements: Vec<Expr>,
}
impl When {
pub fn then<E: Into<Expr>>(self, expr: E) -> Then {
Then {
condition: self.condition,
statement: expr.into(),
}
}
}
impl Then {
pub fn when<E: Into<Expr>>(self, condition: E) -> ChainedWhen {
ChainedWhen {
conditions: vec![self.condition, condition.into()],
statements: vec![self.statement],
}
}
pub fn otherwise<E: Into<Expr>>(self, statement: E) -> Expr {
ternary_expr(self.condition, self.statement, statement.into())
}
}
impl ChainedWhen {
pub fn then<E: Into<Expr>>(mut self, statement: E) -> ChainedThen {
self.statements.push(statement.into());
ChainedThen {
conditions: self.conditions,
statements: self.statements,
}
}
}
impl ChainedThen {
pub fn when<E: Into<Expr>>(mut self, condition: E) -> ChainedWhen {
self.conditions.push(condition.into());
ChainedWhen {
conditions: self.conditions,
statements: self.statements,
}
}
pub fn otherwise<E: Into<Expr>>(self, expr: E) -> Expr {
let conditions_iter = self.conditions.into_iter().rev();
let mut statements_iter = self.statements.into_iter().rev();
let mut otherwise = expr.into();
for e in conditions_iter {
otherwise = ternary_expr(
e,
statements_iter
.next()
.expect("expr expected, did you call when().then().otherwise?"),
otherwise,
);
}
otherwise
}
}
pub fn when<E: Into<Expr>>(condition: E) -> When {
When {
condition: condition.into(),
}
}
pub fn ternary_expr(predicate: Expr, truthy: Expr, falsy: Expr) -> Expr {
Expr::Ternary {
predicate: Arc::new(predicate),
truthy: Arc::new(truthy),
falsy: Arc::new(falsy),
}
}
pub fn binary_expr(l: Expr, op: Operator, r: Expr) -> Expr {
Expr::BinaryExpr {
left: Arc::new(l),
op,
right: Arc::new(r),
}
}