hypercpu/
cond.rs

1use crate::Moment;
2use async_trait::async_trait;
3
4/// A conditional calculation.
5/// 
6/// This struct allows you to branch calculations based
7/// on a condition. Both sides are still optimized, but
8/// only one side will be fully resolved.
9#[derive(Clone)]
10pub struct If<C: Moment<Value = bool>, T: Moment, F: Moment> {
11  pub(crate) condition: C,
12  pub(crate) then: T,
13  pub(crate) otherwise: F,
14}
15
16impl<C: Moment<Value = bool>, T: Moment, F: Moment> If<C, T, F> {
17  /// Create a new `If` struct.
18  /// 
19  /// This will branch the calculation based on the
20  /// condition. If the condition is true, the `then`
21  /// calculation will be resolved. Otherwise, the
22  /// `otherwise` calculation will be resolved.
23  pub fn new(condition: C, then: T, otherwise: F) -> Self {
24    Self {
25      condition,
26      then,
27      otherwise,
28    }
29  }
30
31  /// Tries to get the `then` calculation.
32  pub async fn to_then(self) -> Option<T> {
33    if self.condition.resolve().await {
34      Some(self.then)
35    } else {
36      None
37    }
38  }
39
40  /// Tries to get the `otherwise` calculation.
41  pub async fn to_otherwise(self) -> Option<F> {
42    if !self.condition.resolve().await {
43      Some(self.otherwise)
44    } else {
45      None
46    }
47  }
48}
49
50#[async_trait]
51impl<C, T, F> Moment for If<C, T, F>
52where
53  C: Moment<Value = bool>,
54  T: Moment,
55  F: Moment
56{
57  type Value = If<C, T::Value, F::Value>;
58
59  async fn resolve(self) -> Self::Value {
60    If::new(
61      self.condition,
62      self.then.resolve().await,
63      self.otherwise.resolve().await,
64    )
65  }
66}