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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::{
    bound_type::{Left, Right},
    traits::BoundaryOf,
    Bound, Interval,
};

/// Wrapper of `Option<T>` to implement `Sum` trait.
/// ```
/// use inter_val::{Nullable, Interval, Inclusive, Exclusive};
/// let a = Inclusive.at(0).to(Exclusive.at(3));  // [0, 3)
/// let b = Inclusive.at(1).to(Exclusive.at(5));  // [1, 5)
/// let c = Inclusive.at(8).to(Exclusive.at(10)); // [8, 10)
/// let span: Nullable<Interval<_, _, _>> = vec![a, b, c].into_iter().sum(); // [0, 10)
/// assert_eq!(span.as_ref().unwrap().left().limit, 0);
/// assert_eq!(span.as_ref().unwrap().right().limit, 10);
///
/// let hull: Nullable<Interval<i32>> = vec![1, 6, 2, 8, 3].into_iter().sum();
/// assert_eq!(hull.unwrap(), Interval::between(1, 8));
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Nullable<T>(pub Option<T>);

impl<T> std::ops::Deref for Nullable<T> {
    type Target = Option<T>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl<T> std::ops::DerefMut for Nullable<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T> From<Option<T>> for Nullable<T> {
    fn from(o: Option<T>) -> Self {
        Self(o)
    }
}
impl<T> From<T> for Nullable<T> {
    fn from(t: T) -> Self {
        Self(Some(t))
    }
}
impl<T> From<Nullable<T>> for Option<T> {
    fn from(n: Nullable<T>) -> Self {
        n.0
    }
}

impl<T> Nullable<T> {
    pub const NULL: Self = Self(None);

    pub fn into_option(self) -> Option<T> {
        self.0
    }
    pub fn from_option(o: Option<T>) -> Self {
        Self(o)
    }
    pub fn is_null(&self) -> bool {
        self.0.is_none()
    }
    pub fn unwrap(self) -> T {
        self.0.unwrap()
    }
}

/// ```
/// use inter_val::{Nullable, Interval, Inclusive, Exclusive};
/// let a = Inclusive.at(0).to(Exclusive.at(3));  // [0, 3)
/// let b = Inclusive.at(1).to(Exclusive.at(5));  // [1, 5)
/// let c = Inclusive.at(8).to(Exclusive.at(10)); // [8, 10)
/// let span: Nullable<Interval<_, _, _>> = vec![a, b, c].into_iter().sum(); // [0, 10)
/// assert_eq!(span.as_ref().unwrap().left().limit, 0);
/// assert_eq!(span.as_ref().unwrap().right().limit, 10);
/// ```
impl<T, L, R> std::iter::Sum<Interval<T, L, R>> for Nullable<Interval<T, L, R>>
where
    T: PartialOrd + Clone,
    L: BoundaryOf<Left>,
    R: BoundaryOf<Right>,
{
    fn sum<I: Iterator<Item = Interval<T, L, R>>>(iter: I) -> Self {
        Interval::span_many(iter).into()
    }
}

/// ```
/// use inter_val::{Interval, Nullable};
/// let a: Nullable<Interval<i32>> = vec![1, 6, 2, 8, 3].into_iter().sum();
/// assert_eq!(a.unwrap(), Interval::between(1, 8));
/// ```
impl<T, L, R> std::iter::Sum<T> for Nullable<Interval<T, L, R>>
where
    T: PartialOrd + Clone + Into<Bound<T, L>> + Into<Bound<T, R>>,
    L: BoundaryOf<Left>,
    R: BoundaryOf<Right>,
{
    fn sum<I: Iterator<Item = T>>(iter: I) -> Self {
        Interval::hull_many(iter).into()
    }
}

/// ```
/// use inter_val::{Interval, Nullable};
/// let a = vec![1, 6, 2, 8, 3].into_iter().collect::<Nullable<Interval<i32>>>();
/// assert_eq!(a.unwrap(), Interval::between(1, 8));
/// ```
impl<T, L, R> std::iter::FromIterator<T> for Nullable<Interval<T, L, R>>
where
    T: PartialOrd + Clone + Into<Bound<T, L>> + Into<Bound<T, R>>,
    L: BoundaryOf<Left>,
    R: BoundaryOf<Right>,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        Interval::hull_many(iter).into()
    }
}