1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! Helper traits commonly used to make API consistent and convenient.

/// Push `T` into `Self` in builder-style
pub trait PushOwned<T> {
    fn push(self, val: T) -> Self;

    fn try_push(self, val: Option<T>) -> Self
    where
        Self: Sized,
    {
        if let Some(val) = val {
            self.push(val)
        } else {
            self
        }
    }
}

/// Set `T` in `Self` in builder-style
pub trait SetOwned<T> {
    fn set(self, val: T) -> Self;

    fn try_set(self, val: Option<T>) -> Self
    where
        Self: Sized,
    {
        if let Some(val) = val {
            self.set(val)
        } else {
            self
        }
    }
}

/// Trait provide helper methods that makes working with `Self` kinda
/// declarative
pub trait DeclarativeConfig: Sized {
    /// This method accept closure that configure `self`
    ///
    /// ```no_test
    /// Foo::default()
    ///     .config(|conf| {
    ///         // config foo in this closure
    ///     });
    /// ```
    fn config(self, block: impl FnOnce(Self) -> Self) -> Self {
        block(self)
    }

    /// Same as `config` but will be called if `condition` is `true`
    fn config_if(self, condition: bool, block: impl FnOnce(Self) -> Self) -> Self {
        if condition {
            self.config(block)
        } else {
            self
        }
    }

    /// if `condition` is `true` then `block` will be called, otherwise
    /// `else_blcok` will be called
    fn config_if_else(
        self,
        condition: bool,
        block: impl FnOnce(Self) -> Self,
        else_block: impl FnOnce(Self) -> Self,
    ) -> Self {
        if condition {
            self.config(block)
        } else {
            self.config(else_block)
        }
    }
}