1pub trait Union<T: ?Sized> {
5 type Output;
7 fn union(&self, other: &T) -> Self::Output;
9}
10
11pub trait BoundingUnion<T: ?Sized> {
13 type Output;
15 fn bounding_union(&self, other: &T) -> Self::Output;
32}
33
34impl<T: BoundingUnion<T, Output = T> + Clone> BoundingUnion<Option<T>> for T {
35 type Output = T;
36
37 fn bounding_union(&self, other: &Option<T>) -> Self::Output {
38 if let Some(obj) = other {
39 self.bounding_union(obj)
40 } else {
41 self.clone()
42 }
43 }
44}
45
46impl<T: BoundingUnion<T, Output = T> + Clone> BoundingUnion<T> for Option<T> {
47 type Output = T;
48 fn bounding_union(&self, other: &T) -> Self::Output {
49 if let Some(obj) = self {
50 obj.bounding_union(other)
51 } else {
52 other.clone()
53 }
54 }
55}
56
57impl<T: BoundingUnion<Option<T>, Output = T> + Clone> BoundingUnion<Option<T>> for Option<T> {
58 type Output = Option<T>;
59 fn bounding_union(&self, other: &Option<T>) -> Self::Output {
60 if let Some(obj) = self {
61 Some(obj.bounding_union(other))
62 } else {
63 other.clone()
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use crate::{rect::Rect, span::Span, union::BoundingUnion};
71
72 #[test]
73 fn union_works_for_option_rects() {
74 let r1 = Rect::from_sides(0, 0, 100, 200);
75 let r2 = Rect::from_sides(-50, 20, 120, 160);
76 assert_eq!(r1.bounding_union(&r2), Rect::from_sides(-50, 0, 120, 200));
77
78 let r1 = Rect::from_sides(0, 0, 100, 200);
79 let r2 = None;
80 assert_eq!(r1.bounding_union(&r2), Rect::from_sides(0, 0, 100, 200));
81 assert_eq!(r2.bounding_union(&r1), Rect::from_sides(0, 0, 100, 200));
82
83 let r1 = Some(Rect::from_sides(0, 0, 100, 200));
84 let r2: Option<Rect> = None;
85 assert_eq!(
86 r1.bounding_union(&r2),
87 Some(Rect::from_sides(0, 0, 100, 200))
88 );
89 assert_eq!(
90 r2.bounding_union(&r1),
91 Some(Rect::from_sides(0, 0, 100, 200))
92 );
93
94 let r1: Option<Rect> = None;
95 let r2: Option<Rect> = None;
96 assert_eq!(r1.bounding_union(&r2), None,);
97 }
98
99 #[test]
100 fn union_works_for_option_spans() {
101 let r1 = Span::new(0, 100);
102 let r2 = Span::new(-50, 120);
103 assert_eq!(r1.bounding_union(&r2), Span::new(-50, 120));
104
105 let r1 = Span::new(0, 100);
106 let r2 = None;
107 assert_eq!(r1.bounding_union(&r2), Span::new(0, 100));
108 assert_eq!(r2.bounding_union(&r1), Span::new(0, 100));
109
110 let r1 = Some(Span::new(0, 100));
111 let r2: Option<Span> = None;
112 assert_eq!(r1.bounding_union(&r2), Some(Span::new(0, 100)));
113 assert_eq!(r2.bounding_union(&r1), Some(Span::new(0, 100)));
114
115 let r1: Option<Span> = None;
116 let r2: Option<Span> = None;
117 assert_eq!(r1.bounding_union(&r2), None,);
118 }
119}