|
1 | 1 | //! Basic manipulation of rectangles. |
2 | 2 |
|
3 | | -use std::cmp; |
4 | | - |
5 | 3 | /// A rectangular region of non-zero width and height. |
6 | 4 | /// # Examples |
7 | 5 | /// ``` |
@@ -62,14 +60,14 @@ impl Rect { |
62 | 60 | /// |
63 | 61 | /// See the [struct-level documentation](Rect) for examples. |
64 | 62 | pub fn bottom(&self) -> i32 { |
65 | | - self.top + (self.height as i32) - 1 |
| 63 | + self.top + i32::try_from(self.height).unwrap() - 1 |
66 | 64 | } |
67 | 65 |
|
68 | 66 | /// Greatest x-coordinate reached by rect. |
69 | 67 | /// |
70 | 68 | /// See the [struct-level documentation](Rect) for examples. |
71 | 69 | pub fn right(&self) -> i32 { |
72 | | - self.left + (self.width as i32) - 1 |
| 70 | + self.left + i32::try_from(self.width).unwrap() - 1 |
73 | 71 | } |
74 | 72 |
|
75 | 73 | /// Width of rect. |
@@ -105,21 +103,18 @@ impl Rect { |
105 | 103 | /// assert_eq!(r.intersect(s), None); |
106 | 104 | /// ``` |
107 | 105 | pub fn intersect(&self, other: Rect) -> Option<Rect> { |
108 | | - let left = cmp::max(self.left, other.left); |
109 | | - let top = cmp::max(self.top, other.top); |
110 | | - let right = cmp::min(self.right(), other.right()); |
111 | | - let bottom = cmp::min(self.bottom(), other.bottom()); |
| 106 | + let left = self.left.max(other.left); |
| 107 | + let top = self.top.max(other.top); |
| 108 | + let right = self.right().min(other.right()); |
| 109 | + let bottom = self.bottom().min(other.bottom()); |
112 | 110 |
|
113 | 111 | if right < left || bottom < top { |
114 | 112 | return None; |
115 | 113 | } |
116 | 114 |
|
117 | | - Some(Rect { |
118 | | - left, |
119 | | - top, |
120 | | - width: (right - left) as u32 + 1, |
121 | | - height: (bottom - top) as u32 + 1, |
122 | | - }) |
| 115 | + let width = u32::try_from(right - left).unwrap() + 1; |
| 116 | + let height = u32::try_from(bottom - top).unwrap() + 1; |
| 117 | + Some(Rect::at(left, top).of_size(width, height)) |
123 | 118 | } |
124 | 119 | } |
125 | 120 |
|
@@ -189,3 +184,29 @@ mod tests { |
189 | 184 | assert!(!r.contains(10.1f32, 10f32)); |
190 | 185 | } |
191 | 186 | } |
| 187 | + |
| 188 | +#[cfg(not(miri))] |
| 189 | +#[cfg(test)] |
| 190 | +mod proptests { |
| 191 | + use super::*; |
| 192 | + use proptest::prelude::*; |
| 193 | + |
| 194 | + proptest! { |
| 195 | + #[test] |
| 196 | + fn proptest_intersect( |
| 197 | + (x1, y1) in (-50..50, -50..50), |
| 198 | + (w1, h1) in (1..50u32, 1..50u32), |
| 199 | + |
| 200 | + (x2, y2) in (-50..50, -50..50), |
| 201 | + (w2, h2) in (1..50u32, 1..50u32), |
| 202 | + ) { |
| 203 | + let rect1 = Rect::at(x1, y1).of_size(w1, h1); |
| 204 | + let rect2 = Rect::at(x2, y2).of_size(w2, h2); |
| 205 | + |
| 206 | + if let Some(intersect) = rect1.intersect(rect2) { |
| 207 | + assert!(intersect.width() > 0); |
| 208 | + assert!(intersect.height() > 0); |
| 209 | + }; |
| 210 | + } |
| 211 | + } |
| 212 | +} |
0 commit comments