gcollections/wrappers/
optional.rs

1// Copyright 2015 Pierre Talbot (IRCAM)
2
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use kind::*;
10use ops::*;
11use std::ops::*;
12
13fn binary_map_unwrap_or<T, U, R, F>(x: &Optional<T>, y: &Optional<U>, default: R, f: F) -> R where
14 F: FnOnce(&T, &U) -> R
15{
16  if let Some(ref x) = x.as_ref() {
17    if let Some(ref y) = y.as_ref() {
18      return f(x, y)
19    }
20  }
21  default
22}
23
24fn binary_value_map_unwrap_or<T, U, R, F>(x: &Optional<T>, y: &U, default: R, f: F) -> R where
25 F: FnOnce(&T, &U) -> R
26{
27  x.as_ref().map_or(default, |x| f(x, y))
28}
29
30fn binary_value_map<T, U, R, F>(x: Optional<T>, y: U, f: F) -> Optional<R> where
31 F: FnOnce(T, U) -> R
32{
33  x.unwrap().map_or(Optional::empty(), |x|
34      Optional::singleton(f(x, y)))
35}
36
37fn binary_map<T, U, R, F>(x: Optional<T>, y: Optional<U>, f: F) -> Optional<R> where
38 F: FnOnce(T, U) -> R
39{
40  x.unwrap().map_or(Optional::empty(), |x|
41    y.unwrap().map_or(Optional::empty(), |y|
42      Optional::singleton(f(x, y))))
43}
44
45#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
46pub struct Optional<T>
47{
48  value: Option<T>
49}
50
51impl<T> Optional<T>
52{
53  pub fn wrap(value: Option<T>) -> Optional<T> {
54    Optional {
55      value: value
56    }
57  }
58
59  pub fn unwrap(self) -> Option<T> {
60    self.value
61  }
62}
63
64impl<T> Collection for Optional<T> {
65  type Item = T;
66}
67
68impl<T> Deref for Optional<T>
69{
70  type Target = Option<T>;
71
72  fn deref<'a>(&'a self) -> &'a Option<T> {
73    &self.value
74  }
75}
76
77impl<T> DerefMut for Optional<T>
78{
79  fn deref_mut<'a>(&'a mut self) -> &'a mut Option<T> {
80    &mut self.value
81  }
82}
83
84impl<T> Cardinality for Optional<T>
85{
86  type Size = usize;
87  fn size(&self) -> usize {
88    self.is_some() as usize
89  }
90}
91
92impl<T> Singleton for Optional<T>
93{
94  fn singleton(value: T) -> Optional<T> {
95    Optional::wrap(Some(value))
96  }
97}
98
99impl<T> Empty for Optional<T>
100{
101  fn empty() -> Optional<T> {
102    Optional::wrap(None)
103  }
104}
105
106impl<T> Intersection<Optional<T>> for Optional<T> where
107 T: Clone + PartialEq
108{
109  type Output = Optional<T>;
110
111  fn intersection(&self, other: &Optional<T>) -> Self::Output {
112    if self.is_empty() || other.is_empty() || self != other {
113      Optional::empty()
114    }
115    else {
116      self.clone()
117    }
118  }
119}
120
121impl<T> Intersection<T> for Optional<T> where
122 T: Clone + PartialEq
123{
124  type Output = Optional<T>;
125
126  fn intersection(&self, other: &T) -> Self::Output {
127    if self.is_empty() || self.as_ref().unwrap() != other {
128      Optional::empty()
129    }
130    else {
131      self.clone()
132    }
133  }
134}
135
136macro_rules! primitive_optional_intersection_operation
137{
138  ( $( $source:ty ),* ) =>
139  {$(
140    impl Intersection<Optional<$source>> for $source
141    {
142      type Output = Optional<$source>;
143
144      fn intersection(&self, other: &Optional<$source>) -> Self::Output {
145        other.intersection(self)
146      }
147    }
148  )*}
149}
150
151primitive_optional_intersection_operation!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize,f32,f64,bool,char);
152
153impl<T> Difference<Optional<T>> for Optional<T> where
154 T: Clone + PartialEq
155{
156  type Output = Optional<T>;
157
158  fn difference(&self, other: &Optional<T>) -> Self::Output {
159    if self.is_empty() || self == other {
160      Optional::empty()
161    }
162    else {
163      self.clone()
164    }
165  }
166}
167
168impl<T> Difference<T> for Optional<T> where
169 T: Clone + PartialEq
170{
171  type Output = Optional<T>;
172
173  fn difference(&self, other: &T) -> Self::Output {
174    if self.is_empty() || self.as_ref().unwrap() == other {
175      Optional::empty()
176    }
177    else {
178      self.clone()
179    }
180  }
181}
182
183macro_rules! primitive_optional_difference_operation
184{
185  ( $( $source:ty ),* ) =>
186  {$(
187    impl Difference<Optional<$source>> for $source
188    {
189      type Output = Optional<$source>;
190
191      fn difference(&self, other: &Optional<$source>) -> Self::Output {
192        if other.is_empty() || self != other.as_ref().unwrap() {
193          Optional::singleton(self.clone())
194        }
195        else {
196          Optional::empty()
197        }
198      }
199    }
200  )*}
201}
202
203primitive_optional_difference_operation!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize,f32,f64,bool,char);
204
205impl<T, U> Disjoint<Optional<U>> for Optional<T> where
206 T: Disjoint<U>
207{
208  fn is_disjoint(&self, other: &Optional<U>) -> bool {
209    self.is_empty() || other.is_empty() ||
210    self.as_ref().unwrap().is_disjoint(other.as_ref().unwrap())
211  }
212}
213
214impl<T, U> Disjoint<U> for Optional<T> where
215 T: Disjoint<U>,
216 U: GroundType
217{
218  fn is_disjoint(&self, other: &U) -> bool {
219    self.is_empty() ||
220    self.as_ref().unwrap().is_disjoint(other)
221  }
222}
223
224macro_rules! primitive_optional_disjoint_operation
225{
226  ( $( $source:ty ),* ) =>
227  {$(
228    impl<T> Disjoint<Optional<T>> for $source where
229     T: Disjoint<$source>
230    {
231      fn is_disjoint(&self, other: &Optional<T>) -> bool {
232        other.is_disjoint(self)
233      }
234    }
235  )*}
236}
237
238primitive_optional_disjoint_operation!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize,f32,f64,bool,char);
239
240impl<T> Contains for Optional<T> where
241  T: Eq
242{
243  fn contains(&self, value: &T) -> bool {
244    self.as_ref().map_or(false, |x| x == value)
245  }
246}
247
248impl<T> Subset<Optional<T>> for Optional<T> where
249 T: Subset
250{
251  fn is_subset(&self, other: &Optional<T>) -> bool {
252    if self.is_empty() { true }
253    else if other.is_empty() { false }
254    else {
255      self.as_ref().unwrap().is_subset(other.as_ref().unwrap())
256    }
257  }
258}
259
260impl<T> ProperSubset<Optional<T>> for Optional<T> where
261 T: Subset + PartialEq
262{
263  fn is_proper_subset(&self, other: &Optional<T>) -> bool {
264    self.is_subset(other) && self != other
265  }
266}
267
268impl<T, U> Overlap<Optional<U>> for Optional<T> where
269 T: Overlap<U>
270{
271  fn overlap(&self, other: &Optional<U>) -> bool {
272    binary_map_unwrap_or(self, other, false, T::overlap)
273  }
274}
275
276impl<T, U> Overlap<U> for Optional<T> where
277 T: Overlap<U>,
278 U: GroundType
279{
280  fn overlap(&self, other: &U) -> bool {
281    binary_value_map_unwrap_or(self, other, false, T::overlap)
282  }
283}
284
285macro_rules! primitive_optional_overlap_operation
286{
287  ( $( $source:ty ),* ) =>
288  {$(
289    impl<T> Overlap<Optional<T>> for $source where
290     T: Overlap<$source>
291    {
292      fn overlap(&self, other: &Optional<T>) -> bool {
293        other.overlap(self)
294      }
295    }
296  )*}
297}
298
299primitive_optional_overlap_operation!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize,f32,f64,bool,char);
300
301impl<T, U, R> Add<Optional<U>> for Optional<T> where
302 T: Add<U, Output=R>
303{
304  type Output = Optional<R>;
305
306  fn add(self, other: Optional<U>) -> Self::Output {
307    binary_map(self, other, T::add)
308  }
309}
310
311impl<T, U, R> Add<U> for Optional<T> where
312 T: Add<U, Output=R>,
313 U: GroundType
314{
315  type Output = Optional<R>;
316
317  fn add(self, other: U) -> Self::Output {
318    binary_value_map(self, other, T::add)
319  }
320}
321
322macro_rules! add_optional_arithmetics
323{
324  ( $( $source:ty ),* ) =>
325  {$(
326    impl<T, R> Add<Optional<T>> for $source where
327     T: Add<$source, Output=R>
328    {
329      type Output = Optional<R>;
330
331      fn add(self, rhs: Optional<T>) -> Self::Output {
332        rhs + self
333      }
334    }
335  )*}
336}
337
338add_optional_arithmetics!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize,f32,f64,bool,char);
339
340impl<T, U, R> Sub<Optional<U>> for Optional<T> where
341 T: Sub<U, Output=R>
342{
343  type Output = Optional<R>;
344
345  fn sub(self, other: Optional<U>) -> Self::Output {
346    binary_map(self, other, T::sub)
347  }
348}
349
350impl<T, U, R> Sub<U> for Optional<T> where
351 T: Sub<U, Output=R>,
352 U: GroundType
353{
354  type Output = Optional<R>;
355
356  fn sub(self, other: U) -> Self::Output {
357    binary_value_map(self, other, T::sub)
358  }
359}
360
361macro_rules! sub_optional_arithmetics
362{
363  ( $( $source:ty ),* ) =>
364  {$(
365    impl Sub<Optional<$source>> for $source
366    {
367      type Output = Optional<$source>;
368
369      fn sub(self, other: Optional<$source>) -> Self::Output {
370        binary_value_map(other, self, |x, y| y - x)
371      }
372    }
373  )*}
374}
375
376sub_optional_arithmetics!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize,f32,f64);
377
378impl<T, U, R> Mul<Optional<U>> for Optional<T> where
379 T: Mul<U, Output=R>
380{
381  type Output = Optional<R>;
382
383  fn mul(self, other: Optional<U>) -> Self::Output {
384    binary_map(self, other, T::mul)
385  }
386}
387
388impl<T, U, R> Mul<U> for Optional<T> where
389 T: Mul<U, Output=R>,
390 U: GroundType
391{
392  type Output = Optional<R>;
393
394  fn mul(self, other: U) -> Self::Output {
395    binary_value_map(self, other, T::mul)
396  }
397}
398
399macro_rules! mul_optional_arithmetics
400{
401  ( $( $source:ty ),* ) =>
402  {$(
403    impl<T, R> Mul<Optional<T>> for $source where
404     T: Mul<$source, Output=R>
405    {
406      type Output = Optional<R>;
407
408      fn mul(self, other: Optional<T>) -> Self::Output {
409        other.mul(self)
410      }
411    }
412  )*}
413}
414
415mul_optional_arithmetics!(i8,u8,i16,u16,i32,u32,i64,u64,isize,usize,f32,f64,bool,char);
416
417#[allow(non_upper_case_globals)]
418#[cfg(test)]
419mod tests {
420  use super::*;
421
422  const empty: Optional<i32> = Optional { value: None };
423  const zero: Optional<i32> = Optional { value: Some(0) };
424  const ten: Optional<i32> = Optional { value: Some(10) };
425
426  #[test]
427  fn cardinality_test() {
428    assert_eq!(empty.size(), 0);
429    assert_eq!(zero.size(), 1);
430    assert_eq!(ten.size(), 1);
431    assert!(empty.is_empty());
432    assert!(!empty.is_singleton());
433    assert!(!zero.is_empty());
434    assert!(zero.is_singleton());
435  }
436
437  #[test]
438  fn constructors_test() {
439    assert_eq!(empty, Empty::empty());
440    assert_eq!(zero, Singleton::singleton(0));
441  }
442
443  #[test]
444  fn intersection_test() {
445    let sym_cases = vec![
446      (empty, empty, empty),
447      (empty, zero, empty),
448      (zero, zero, zero),
449      (zero, ten, empty),
450      (ten, ten, ten)
451    ];
452
453    for (x,y,r) in sym_cases.into_iter() {
454      assert!(x.intersection(&y) == r, "{:?} intersection {:?} is not equal to {:?}", x, y, r);
455      assert!(y.intersection(&x) == r, "{:?} intersection {:?} is not equal to {:?}", y, x, r);
456    }
457  }
458
459  #[test]
460  fn difference_test() {
461    let cases = vec![
462      (empty, empty,  empty, empty),
463      (empty, zero,   empty, zero),
464      (zero, zero,    empty, empty),
465      (zero, ten,     zero, ten),
466      (ten, ten,      empty, empty)
467    ];
468
469    for (x,y,r1,r2) in cases.into_iter() {
470      assert!(x.difference(&y) == r1, "{:?} difference {:?} is not equal to {:?}", x, y, r1);
471      assert!(y.difference(&x) == r2, "{:?} difference {:?} is not equal to {:?}", y, x, r2);
472    }
473  }
474
475  #[test]
476  fn intersection_value_test() {
477    let sym_cases = vec![
478      (empty, 0, empty),
479      (empty, 1, empty),
480      (zero, 0, zero),
481      (zero, 1, empty),
482      (ten, 10, ten)
483    ];
484
485    for (x,y,r) in sym_cases.into_iter() {
486      assert!(x.intersection(&y) == r, "{:?} intersection {:?} is not equal to {:?}", x, y, r);
487      assert!(y.intersection(&x) == r, "{:?} intersection {:?} is not equal to {:?}", y, x, r);
488    }
489  }
490
491  #[test]
492  fn difference_value_test() {
493    let cases = vec![
494      (empty, 0,  empty, zero),
495      (zero, 0,   empty, empty),
496      (zero, 10,  zero, ten),
497      (ten,  10,  empty, empty)
498    ];
499
500    for (x,y,r1,r2) in cases.into_iter() {
501      assert!(x.difference(&y) == r1, "{:?} difference {:?} is not equal to {:?}", x, y, r1);
502      assert!(y.difference(&x) == r2, "{:?} difference {:?} is not equal to {:?}", y, x, r2);
503    }
504  }
505
506  #[test]
507  fn is_disjoint_and_overlap_test() {
508    let sym_cases = vec![
509      (empty, empty, true),
510      (empty, zero, true),
511      (zero, zero, false),
512      (zero, ten, true),
513      (ten, ten, false)
514    ];
515
516    for (x,y,r) in sym_cases.into_iter() {
517      assert!(x.is_disjoint(&y) == r, "{:?} disjoint {:?} is not equal to {:?}", x, y, r);
518      assert!(y.is_disjoint(&x) == r, "{:?} disjoint {:?} is not equal to {:?}", y, x, r);
519      assert!(x.overlap(&y) == !r, "{:?} overlap {:?} is not equal to {:?}", x, y, !r);
520      assert!(y.overlap(&x) == !r, "{:?} overlap {:?} is not equal to {:?}", y, x, !r);
521    }
522  }
523
524  #[test]
525  fn contains_test() {
526    let cases = vec![
527      (empty, 0, false),
528      (empty, 1, false),
529      (zero, 0, true),
530      (zero, 1, false),
531      (ten, 9, false),
532      (ten, 10, true)
533    ];
534
535    for (x,y,r) in cases.into_iter() {
536      assert!(x.contains(&y) == r, "{:?} contains {:?} is not equal to {:?}", x, y, r);
537    }
538  }
539
540  #[test]
541  fn subset_test() {
542    let cases = vec![
543      (empty, empty,  true, true),
544      (empty, zero,   true, false),
545      (zero, zero,    true, true),
546      (zero, ten,     false, false),
547      (ten, ten,      true, true)
548    ];
549
550    for (x,y,r1,r2) in cases.into_iter() {
551      assert!(x.is_subset(&y) == r1, "{:?} subset {:?} is not equal to {:?}", x, y, r1);
552      assert!(y.is_subset(&x) == r2, "{:?} subset {:?} is not equal to {:?}", y, x, r2);
553    }
554  }
555
556  #[test]
557  fn proper_subset_test() {
558    let cases = vec![
559      (empty, empty,  false, false),
560      (empty, zero,   true, false),
561      (zero, zero,    false, false),
562      (zero, ten,     false, false),
563      (ten, ten,      false, false)
564    ];
565
566    for (x,y,r1,r2) in cases.into_iter() {
567      assert!(x.is_proper_subset(&y) == r1, "{:?} proper_subset {:?} is not equal to {:?}", x, y, r1);
568      assert!(y.is_proper_subset(&x) == r2, "{:?} proper_subset {:?} is not equal to {:?}", y, x, r2);
569    }
570  }
571
572  #[test]
573  fn arithmetics_tests() {
574    let twenty = Optional::singleton(20);
575    let one_hundred = Optional::singleton(100);
576    let cases = vec![
577      // x,     y,    x+y,   x-y,   x*y
578      (empty, empty, empty, empty, empty),
579      (empty, ten,   empty, empty, empty),
580      (ten,   empty, empty, empty, empty),
581      (ten,   zero,  ten,   ten,   zero),
582      (ten,   ten,   twenty,zero,  one_hundred)
583    ];
584    for (x,y,add,sub,mul) in cases.into_iter() {
585      assert!(x + y == add, "{:?} + {:?} is not equal to {:?}", x, y, add);
586      assert!(x - y == sub, "{:?} - {:?} is not equal to {:?}", x, y, sub);
587      assert!(x * y == mul, "{:?} * {:?} is not equal to {:?}", x, y, mul);
588    }
589  }
590}