int_vec_2d/
lib.rs

1#![feature(iter_advance_by)]
2#![feature(stmt_expr_attributes)]
3#![feature(trusted_len)]
4
5#![deny(warnings)]
6#![allow(unstable_name_collisions)] // because I can
7#![doc(test(attr(deny(warnings))))]
8#![doc(test(attr(allow(dead_code))))]
9#![doc(test(attr(allow(unused_variables))))]
10#![allow(clippy::collapsible_else_if)]
11#![allow(clippy::collapsible_if)]
12#![allow(clippy::manual_map)]
13#![allow(clippy::many_single_char_names)]
14#![allow(clippy::too_many_arguments)]
15
16#![no_std]
17
18use core::cmp::{min, max};
19use core::iter::{FusedIterator, TrustedLen};
20use core::num::{NonZeroI16, NonZeroUsize};
21use core::ops::{Add, AddAssign, Sub, SubAssign, Neg, Index, IndexMut};
22use either::{Either, Left, Right};
23use enum_derive_2018::{EnumDisplay, EnumFromStr};
24use macro_attr_2018::macro_attr;
25use num_traits::Zero;
26#[cfg(test)]
27use quickcheck::{Arbitrary, Gen};
28#[cfg(feature="serde")]
29use serde::{Serialize, Deserialize, Deserializer};
30#[cfg(feature="serde")]
31use serde::de::Unexpected;
32#[cfg(feature="serde")]
33use serde::de::Error as de_Error;
34
35#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
36pub struct Range1d {
37    pub start: i16,
38    pub end: i16,
39}
40
41impl Range1d {
42    pub fn new(start: i16, end: i16) -> Self {
43        Range1d { start, end }
44    }
45
46    pub fn len(self) -> u16 { self.end.wrapping_sub(self.start) as u16 }
47
48    pub fn inclusive(start: i16, end: i16) -> Option<Self> {
49        let res = Range1d { start, end: end.wrapping_add(1) };
50        if res.is_empty() { None } else { Some(res) }
51    }
52
53    pub fn contains(self, coord: i16) -> bool {
54        (coord.wrapping_sub(self.start) as u16) < (self.end.wrapping_sub(self.start) as u16)
55    }
56
57    pub fn is_empty(self) -> bool {
58        self.start == self.end
59    }
60
61    pub fn intersect(self, other: Range1d) -> Range1d {
62        let (long, short) = if self.len() <= other.len() {
63            (other, self)
64        } else {
65            (self, other)
66        };
67        if long.contains(short.start) {
68            if long.contains(short.end) {
69                short
70            } else {
71                Range1d::new(short.start, long.end)
72            }
73        } else {
74            if long.contains(short.end) {
75                Range1d::new(long.start, short.end)
76            } else {
77                Range1d::new(self.start, self.start)
78            }
79        }
80    }
81
82    pub fn union(self, other: Range1d) -> Option<Range1d> {
83        let (long, short) = if self.len() <= other.len() {
84            (other, self)
85        } else {
86            (self, other)
87        };
88        if long.contains(short.start) {
89            if long.contains(short.end) {
90                if Range1d::new(long.start, short.end).len() >= Range1d::new(long.start, short.start).len() {
91                    Some(long)
92                } else {
93                    None
94                }
95            } else {
96                let res = Range1d::new(long.start, short.end);
97                if res.is_empty() { None } else { Some(res) }
98            }
99        } else {
100            if long.contains(short.end) {
101                let res = Range1d::new(short.start, long.end);
102                if res.is_empty() { None } else { Some(res) }
103            } else {
104                if other.is_empty() {
105                    Some(self)
106                } else if self.is_empty() {
107                    Some(other)
108                } else {
109                    let u = Range1d::new(self.start, other.end);
110                    let v = Range1d::new(other.start, self.end);
111                    if u.is_empty() {
112                        if v.is_empty() { None } else { Some(v) }
113                    } else {
114                        Some(if v.is_empty() {
115                            u
116                        } else {
117                            if u.len() < v.len() { u } else { v }
118                        })
119                    }
120                }
121            }
122        }
123    }
124}
125
126impl Iterator for Range1d {
127    type Item = i16;
128
129    fn next(&mut self) -> Option<i16> {
130        if !self.is_empty() {
131            let item = self.start;
132            self.start = self.start.wrapping_add(1);
133            Some(item)
134        } else {
135            None
136        }
137    }
138
139    fn size_hint(&self) -> (usize, Option<usize>) {
140        let len = self.len();
141        (len, Some(len))
142    }
143
144    fn count(self) -> usize { self.len() as usize }
145
146    fn last(self) -> Option<i16> {
147        if self.is_empty() { None } else { Some(self.end) }
148    }
149
150    fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
151        if let Some(rem) = n.checked_sub(self.len()).and_then(NonZeroUsize::new) {
152            self.start = self.end;
153            return Err(rem);
154        }
155        self.start = self.start.wrapping_add(n as u16 as i16);
156        Ok(())
157    }
158}
159
160impl FusedIterator for Range1d { }
161
162impl DoubleEndedIterator for Range1d {
163    fn next_back(&mut self) -> Option<i16> {
164        if !self.is_empty() {
165            let item = self.end;
166            self.end = self.end.wrapping_sub(1);
167            Some(item)
168        } else {
169            None
170        }
171    }
172
173    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
174        if let Some(rem) = n.checked_sub(self.len()).and_then(NonZeroUsize::new) {
175            self.end = self.start;
176            return Err(rem);
177        }
178        self.end = self.end.wrapping_sub(n as u16 as i16);
179        Ok(())
180    }
181}
182
183impl ExactSizeIterator for Range1d {
184    fn len(&self) -> usize {
185        Range1d::len(*self) as usize
186    }
187}
188
189unsafe impl TrustedLen for Range1d { }
190
191macro_attr! {
192    #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
193    #[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
194    #[derive(EnumDisplay!, EnumFromStr!)]
195    pub enum Side {
196        Left,
197        Top,
198        Right,
199        Bottom
200    }
201}
202
203#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
204#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
205pub struct Point {
206    pub x: i16,
207    pub y: i16,
208}
209
210impl Point {
211    pub fn offset(self, d: Vector) -> Point {
212        Point { x: self.x.wrapping_add(d.x), y: self.y.wrapping_add(d.y) }
213    }
214
215    pub fn offset_from(self, other: Point) -> Vector {
216        Vector { x: self.x.wrapping_sub(other.x), y: self.y.wrapping_sub(other.y) }
217    }
218
219    pub fn relative_to(self, base: Point) -> Point {
220        Point { x: self.x.wrapping_sub(base.x), y: self.y.wrapping_sub(base.y) }
221    }
222
223    pub fn absolute_with(self, base: Point) -> Point {
224        Point { x: self.x.wrapping_add(base.x), y: self.y.wrapping_add(base.y) }
225    }
226}
227
228#[cfg(test)]
229impl Arbitrary for Point {
230    fn arbitrary(g: &mut Gen) -> Self {
231        let a = <(_, _)>::arbitrary(g);
232        Point { x: a.0, y: a.1 }
233    }
234}
235
236#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
237#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
238pub struct Vector {
239    pub x: i16,
240    pub y: i16,
241}
242
243impl Vector {
244    pub const fn null() -> Vector { Vector { x: 0, y: 0 } }
245
246    pub fn is_null(self) -> bool { self.x == 0 && self.y == 0 }
247
248    pub fn rect_area(self) -> u32 { (self.x as u16 as u32) * (self.y as u16 as u32) }
249
250    pub fn max(self, other: Vector) -> Vector {
251        Vector {
252            x: max(self.x as u16, other.x as u16) as i16,
253            y: max(self.y as u16, other.y as u16) as i16,
254        }
255    }
256
257    pub fn min(self, other: Vector) -> Vector {
258        Vector {
259            x: min(self.x as u16, other.x as u16) as i16,
260            y: min(self.y as u16, other.y as u16) as i16,
261        }
262    }
263}
264
265impl Default for Vector {
266    fn default() -> Self { Vector::null() }
267}
268
269impl Zero for Vector {
270    fn zero() -> Self { Vector::null() }
271
272    fn is_zero(&self) -> bool { self.is_null() }
273
274    fn set_zero(&mut self) { *self = Vector::null() }
275}
276
277impl Add for Vector {
278    type Output = Self;
279
280    fn add(self, other: Self) -> Self {
281        Vector { x: self.x.wrapping_add(other.x), y: self.y.wrapping_add(other.y) }
282    }
283}
284
285impl AddAssign for Vector {
286    fn add_assign(&mut self, other: Self) {
287        *self = *self + other;
288    }
289}
290
291impl Sub for Vector {
292    type Output = Self;
293
294    fn sub(self, other: Self) -> Self {
295        Vector { x: self.x.wrapping_sub(other.x), y: self.y.wrapping_sub(other.y) }
296    }
297}
298
299impl SubAssign for Vector {
300    fn sub_assign(&mut self, other: Self) {
301        *self = *self - other;
302    }
303}
304
305impl Neg for Vector {
306    type Output = Self;
307
308    fn neg(self) -> Self {
309        Vector::null() - self
310    }
311}
312
313#[cfg(test)]
314impl Arbitrary for Vector {
315    fn arbitrary(g: &mut Gen) -> Self {
316        let a = <(_, _)>::arbitrary(g);
317        Vector { x: a.0, y: a.1 }
318    }
319}
320
321#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
322#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
323pub struct VBand {
324    pub l: i16,
325    pub w: NonZeroI16,
326}
327
328impl VBand {
329    pub fn from_l_r(l: i16, r: i16) -> Option<VBand> {
330        NonZeroI16::new(r.wrapping_sub(l)).map(|w| VBand { l, w })
331    }
332
333    pub fn from_h_range(h_range: Range1d) -> Option<VBand> {
334        VBand::from_l_r(h_range.start, h_range.end)
335    }
336
337    pub fn r(self) -> i16 { self.l.wrapping_add(self.w.get()) }
338
339    pub fn h_range(self) -> Range1d { Range1d::new(self.l, self.r()) }
340
341    pub fn offset(self, d: Vector) -> VBand {
342        VBand { l: self.l.wrapping_add(d.x), w: self.w }
343    }
344
345    pub fn relative_to(self, base: Point) -> VBand {
346        VBand { l: self.l.wrapping_sub(base.x), w: self.w }
347    }
348
349    pub fn absolute_with(self, base: Point) -> VBand {
350        VBand { l: self.l.wrapping_add(base.x), w: self.w }
351    }
352}
353
354#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
355#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
356pub struct HBand {
357    pub t: i16,
358    pub h: NonZeroI16,
359}
360
361impl HBand {
362    pub fn from_t_b(t: i16, b: i16) -> Option<HBand> {
363        NonZeroI16::new(b.wrapping_sub(t)).map(|h| HBand { t, h })
364    }
365
366    pub fn from_v_range(v_range: Range1d) -> Option<HBand> {
367        HBand::from_t_b(v_range.start, v_range.end)
368    }
369
370    pub fn b(self) -> i16 { self.t.wrapping_add(self.h.get()) }
371
372    pub fn v_range(self) -> Range1d { Range1d::new(self.t, self.b()) }
373
374    pub fn offset(self, d: Vector) -> HBand {
375        HBand { t: self.t.wrapping_add(d.y), h: self.h }
376    }
377
378    pub fn relative_to(self, base: Point) -> HBand {
379        HBand { t: self.t.wrapping_sub(base.y), h: self.h }
380    }
381
382    pub fn absolute_with(self, base: Point) -> HBand {
383        HBand { t: self.t.wrapping_add(base.y), h: self.h }
384    }
385}
386
387#[cfg(feature="serde")]
388fn deserialize_thickness_value<'de, D>(d: D) -> Result<i32, D::Error> where D: Deserializer<'de> {
389    let value = i32::deserialize(d)?;
390    if value >= -(u16::MAX as u32 as i32) && value <= u16::MAX as u32 as i32 { return Ok(value); }
391    Err(D::Error::invalid_value(
392        Unexpected::Signed(value.into()),
393        &"integer in the -(2¹⁶ - 1) ..= (2¹⁶ - 1) range"
394    ))
395}
396
397#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
398#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Default)]
399pub struct Thickness {
400    #[cfg_attr(feature="serde", serde(deserialize_with="deserialize_thickness_value"))]
401    l: i32,
402    #[cfg_attr(feature="serde", serde(deserialize_with="deserialize_thickness_value"))]
403    r: i32,
404    #[cfg_attr(feature="serde", serde(deserialize_with="deserialize_thickness_value"))]
405    t: i32,
406    #[cfg_attr(feature="serde", serde(deserialize_with="deserialize_thickness_value"))]
407    b: i32,
408}
409
410impl Thickness {
411    pub const fn new(l: i32, t: i32, r: i32, b: i32) -> Self {
412        assert!(l >= -(u16::MAX as u32 as i32) && l <= u16::MAX as u32 as i32);
413        assert!(t >= -(u16::MAX as u32 as i32) && t <= u16::MAX as u32 as i32);
414        assert!(r >= -(u16::MAX as u32 as i32) && r <= u16::MAX as u32 as i32);
415        assert!(b >= -(u16::MAX as u32 as i32) && b <= u16::MAX as u32 as i32);
416        Thickness { l, t, r, b }
417    }
418
419    /// # Safety
420    ///
421    /// All passed parameters should be in the `-(2¹⁶ - 1) ..= (2¹⁶ - 1)` range.
422    pub const unsafe fn new_unchecked(l: i32, t: i32, r: i32, b: i32) -> Self {
423        Thickness { l, t, r, b }
424    }
425
426    pub const fn all(a: i32) -> Thickness {
427        assert!(a >= -(u16::MAX as u32 as i32) && a <= u16::MAX as u32 as i32);
428        Thickness { l: a, t: a, r: a, b: a }
429    }
430
431    pub fn l(self) -> i32 { self.l }
432
433    pub fn t(self) -> i32 { self.t }
434
435    pub fn r(self) -> i32 { self.r }
436
437    pub fn b(self) -> i32 { self.b }
438
439    pub fn align(inner: Vector, outer: Vector, h_align: HAlign, v_align: VAlign) -> Thickness {
440        let h_neg = inner.x as u16 > outer.x as u16;
441        let (outer_x, inner_x) = if h_neg { (inner.x, outer.x) } else { (outer.x, inner.x) };
442        let w = (outer_x as u16) - (inner_x as u16);
443        let (l, r) = match h_align {
444            HAlign::Left => (0, w),
445            HAlign::Right => (w, 0),
446            HAlign::Center => {
447                let l = w / 2;
448                let r = w - l;
449                (l, r)
450            }
451        };
452        let v_neg = inner.y as u16 > outer.y as u16;
453        let (outer_y, inner_y) = if v_neg { (inner.y, outer.y) } else { (outer.y, inner.y) };
454        let h = (outer_y as u16) - (inner_y as u16);
455        let (t, b) = match v_align {
456            VAlign::Top => (0, h),
457            VAlign::Bottom => (h, 0),
458            VAlign::Center => {
459                let t = h / 2;
460                let b = h - t;
461                (t, b)
462            }
463        };
464        let l = l as u32 as i32;
465        let t = t as u32 as i32;
466        let r = r as u32 as i32;
467        let b = b as u32 as i32;
468        Thickness {
469            l: if h_neg { -l } else { l },
470            t: if v_neg { -t } else { t },
471            r: if h_neg { -r } else { r },
472            b: if v_neg { -b } else { b }
473        }
474    }
475
476    fn shrink_near(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
477        let thickness = min(thickness, rect.1 as u16);
478        (rect.0.wrapping_add(thickness as i16), rect.1.wrapping_sub(thickness as i16))
479    }
480
481    fn shrink_far(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
482        let thickness = min(thickness, rect.1 as u16);
483        (rect.0, rect.1.wrapping_sub(thickness as i16))
484    }
485
486    fn expand_near(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
487        let thickness = min(thickness, u16::MAX - (rect.1 as u16));
488        (rect.0.wrapping_sub(thickness as i16), rect.1.wrapping_add(thickness as i16))
489    }
490
491    fn expand_far(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
492        let thickness = min(thickness, u16::MAX - (rect.1 as u16));
493        (rect.0, rect.1.wrapping_add(thickness as i16))
494    }
495
496    pub fn shrink_rect(self, rect: Rect) -> Rect {
497        let (l, w) = if self.l < 0 {
498            Self::expand_near((-self.l) as u32 as u16, (rect.l(), rect.w()))
499        } else {
500            Self::shrink_near(self.l as u32 as u16, (rect.l(), rect.w()))
501        };
502        let (t, h) = if self.t < 0 {
503            Self::expand_near((-self.t) as u32 as u16, (rect.t(), rect.h()))
504        } else {
505            Self::shrink_near(self.t as u32 as u16, (rect.t(), rect.h()))
506        };
507        let (l, w) = if self.r < 0 {
508            Self::expand_far((-self.r) as u32 as u16, (l, w))
509        } else {
510            Self::shrink_far(self.r as u32 as u16, (l, w))
511        };
512        let (t, h) = if self.b < 0 {
513            Self::expand_far((-self.b) as u32 as u16, (t, h))
514        } else {
515            Self::shrink_far(self.b as u32 as u16, (t, h))
516        };
517        Rect { tl: Point { x: l, y: t }, size: Vector { x: w, y: h } }
518    }
519
520    pub fn expand_rect(self, rect: Rect) -> Rect {
521        (-self).shrink_rect(rect)
522    }
523
524    pub fn shrink_rect_size(self, rect_size: Vector) -> Vector {
525        self.shrink_rect(Rect { tl: Point { x: 0, y: 0 }, size: rect_size }).size
526    }
527
528    pub fn expand_rect_size(self, rect_size: Vector) -> Vector {
529        self.expand_rect(Rect { tl: Point { x: 0, y: 0 }, size: rect_size }).size
530    }
531
532    pub fn shrink_band_h(self, band_h: i16) -> i16 {
533        let (_, h) = if self.t < 0 {
534            Self::expand_near((-self.t) as u32 as u16, (0, band_h))
535        } else {
536            Self::shrink_near(self.t as u32 as u16, (0, band_h))
537        };
538        h
539    }
540
541    pub fn expand_band_h(self, band_h: i16) -> i16 {
542        (-self).shrink_band_h(band_h)
543    }
544
545    pub fn shrink_band_w(self, band_w: i16) -> i16 {
546        let (_, w) = if self.l < 0 {
547            Self::expand_near((-self.t) as u32 as u16, (0, band_w))
548        } else {
549            Self::shrink_near(self.t as u32 as u16, (0, band_w))
550        };
551        w
552    }
553
554    pub fn expand_band_w(self, band_w: i16) -> i16 {
555        (-self).shrink_band_w(band_w)
556    }
557
558    fn add_side(this: i32, other: i32) -> i32 {
559        if this < 0 {
560            if other < 0 {
561                -(((-this) as u32 as u16).saturating_add((-other) as u32 as u16) as u32 as i32)
562            } else {
563                other + this
564            }
565        } else {
566            if other > 0 {
567                (this as u32 as u16).saturating_add(other as u32 as u16) as u32 as i32
568            } else {
569                other + this
570            }
571        }
572    }
573}
574
575impl Add for Thickness {
576    type Output = Self;
577
578    fn add(self, other: Self) -> Self {
579        let l = Self::add_side(self.l, other.l);
580        let t = Self::add_side(self.t, other.t);
581        let r = Self::add_side(self.r, other.r);
582        let b = Self::add_side(self.b, other.b);
583        Thickness { l, t, r, b }
584    }
585}
586
587impl AddAssign for Thickness {
588    fn add_assign(&mut self, other: Self) {
589        *self = *self + other;
590    }
591}
592
593impl Sub for Thickness {
594    type Output = Self;
595
596    fn sub(self, other: Self) -> Self {
597        self + (-other)
598    }
599}
600
601impl SubAssign for Thickness {
602    fn sub_assign(&mut self, other: Self) {
603        *self = *self - other;
604    }
605}
606
607impl Neg for Thickness {
608    type Output = Self;
609
610    fn neg(self) -> Self {
611        Thickness { l: -self.l, t: -self.t, r: -self.r, b: -self.b }
612    }
613}
614
615impl Index<Side> for Thickness {
616    type Output = i32;
617
618    fn index(&self, index: Side) -> &i32 {
619        match index {
620            Side::Left => &self.l,
621            Side::Top => &self.t,
622            Side::Right => &self.r,
623            Side::Bottom => &self.b
624        }
625    }
626}
627
628impl IndexMut<Side> for Thickness {
629    fn index_mut(&mut self, index: Side) -> &mut i32 {
630        match index {
631            Side::Left => &mut self.l,
632            Side::Top => &mut self.t,
633            Side::Right => &mut self.r,
634            Side::Bottom => &mut self.b
635        }
636    }
637}
638
639macro_attr! {
640    #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
641    #[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
642    #[derive(EnumDisplay!, EnumFromStr!)]
643    pub enum HAlign { Left, Center, Right }
644}
645
646macro_attr! {
647    #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
648    #[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
649    #[derive(EnumDisplay!, EnumFromStr!)]
650    pub enum VAlign { Top, Center, Bottom }
651}
652
653pub struct RectPoints {
654    rect: Rect,
655    x: i16,
656}
657
658impl Iterator for RectPoints {
659    type Item = Point;
660
661    fn next(&mut self) -> Option<Point> {
662        if self.rect.is_empty() {
663            return None;
664        }
665        let item = Point { x: self.x, y: self.rect.t() };
666        self.x = self.x.wrapping_add(1);
667        if self.x == self.rect.r() {
668            self.x = self.rect.l();
669            self.rect.tl = Point { x: self.x, y: self.rect.t().wrapping_add(1) };
670            self.rect.size = Vector { x: self.rect.w(), y: self.rect.h().wrapping_sub(1) };
671        }
672        Some(item)
673    }
674
675    fn size_hint(&self) -> (usize, Option<usize>) {
676        let len = self.rect.area() - (self.x.wrapping_sub(self.rect.l()) as u16 as u32);
677        if len as usize as u32 == len {
678            (len as usize, Some(len as usize))
679        } else {
680            (usize::MAX, None)
681        }
682    }
683
684    fn count(self) -> usize { self.size_hint().1.unwrap() }
685
686    fn last(self) -> Option<Point> {
687        if self.rect.is_empty() { None } else { Some(self.rect.br_inner()) }
688    }
689
690    fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
691        if let Some(rem) = self.size_hint().1.and_then(|len| n.checked_sub(len)).and_then(NonZeroUsize::new) {
692            self.x = self.rect.l();
693            self.rect.tl = self.rect.bl();
694            return Err(rem);
695        }
696        let n = n as u32;
697        let current_line_last = self.rect.r().wrapping_sub(self.x) as u16 as u32;
698        if n < current_line_last {
699            self.x = self.x.wrapping_add(n as u16 as i16);
700            return Ok(());
701        }
702        let n = n - current_line_last;
703        let skip_lines = 1i16.wrapping_add((n / self.rect.w() as u32) as u16 as i16);
704        self.rect.tl = Point { x: self.rect.l(), y: self.rect.t().wrapping_add(skip_lines) };
705        self.rect.size = Vector { x: self.rect.w(), y: self.rect.h().wrapping_sub(skip_lines) };
706        self.x = (n % self.rect.w() as u32) as u16 as i16;
707        Ok(())
708    }
709}
710
711impl FusedIterator for RectPoints { }
712
713#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
714#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
715pub struct Rect {
716    pub tl: Point,
717    pub size: Vector,
718}
719
720impl Rect {
721    pub fn from_tl_br(tl: Point, br: Point) -> Rect {
722        Rect { tl, size: br.offset_from(tl) }
723    }
724    
725    pub fn from_h_v_ranges(h_range: Range1d, v_range: Range1d) -> Rect {
726        Rect::from_tl_br(
727            Point { x: h_range.start, y: v_range.start },
728            Point { x: h_range.end, y: v_range.end }
729        )
730    }
731
732    pub fn is_empty(self) -> bool { self.w() == 0 || self.h() == 0 }
733
734    pub fn w(self) -> i16 { self.size.x }
735
736    pub fn h(self) -> i16 { self.size.y }
737
738    pub fn l(self) -> i16 { self.tl.x }
739
740    pub fn t(self) -> i16 { self.tl.y }
741
742    pub fn r(self) -> i16 { self.tl.x.wrapping_add(self.size.x) }
743
744    pub fn b(self) -> i16 { self.tl.y.wrapping_add(self.size.y) }
745
746    pub fn tr(self) -> Point { Point { x: self.r(), y: self.t() } }
747
748    pub fn bl(self) -> Point { Point { x: self.l(), y: self.b() } }
749
750    pub fn br(self) -> Point { Point { x: self.r(), y: self.b() } }
751
752    pub fn r_inner(self) -> i16 {
753        self.l().wrapping_add((self.size.x as u16).saturating_sub(1) as i16)
754    }
755
756    pub fn b_inner(self) -> i16 {
757        self.t().wrapping_add((self.size.y as u16).saturating_sub(1) as i16)
758    }
759
760    pub fn tr_inner(self) -> Point { Point { x: self.r_inner(), y: self.t() } }
761
762    pub fn bl_inner(self) -> Point { Point { x: self.l(), y: self.b_inner() } }
763
764    pub fn br_inner(self) -> Point { Point { x: self.r_inner(), y: self.b_inner() } }
765
766    pub fn area(self) -> u32 { self.size.rect_area() }
767
768    pub fn points(self) -> RectPoints { RectPoints { rect: self, x: self.l() } }
769
770    pub fn h_range(self) -> Range1d { Range1d { start: self.l(), end: self.r() } }
771
772    pub fn v_range(self) -> Range1d { Range1d { start: self.t(), end: self.b() } }
773
774    pub fn contains(self, p: Point) -> bool {
775        self.h_range().contains(p.x) && self.v_range().contains(p.y)
776    }
777
778    pub fn intersect(self, other: Rect) -> Rect {
779        let h = self.h_range().intersect(other.h_range());
780        let v = self.v_range().intersect(other.v_range());
781        Rect::from_h_v_ranges(h, v)
782    }
783
784    pub fn intersect_h_band(self, band: HBand) -> Rect {
785        let v = self.v_range().intersect(band.v_range());
786        Rect::from_h_v_ranges(self.h_range(), v)
787    }
788
789    pub fn intersect_v_band(self, band: VBand) -> Rect {
790        let h = self.h_range().intersect(band.h_range());
791        Rect::from_h_v_ranges(h, self.v_range())
792    }
793
794    pub fn union(self, other: Rect) -> Option<Either<Either<HBand, VBand>, Rect>> {
795        if other.is_empty() { return Some(Right(self)); }
796        if self.is_empty() { return Some(Right(other)); }
797        let hr = self.h_range().union(other.h_range());
798        let vr = self.v_range().union(other.v_range());
799        if let Some(hr) = hr {
800            if let Some(vr) = vr {
801                Some(Right(Rect::from_h_v_ranges(hr, vr)))
802            } else {
803                Some(Left(Right(VBand::from_h_range(hr).unwrap())))
804            }
805        } else {
806            if let Some(vr) = vr {
807                Some(Left(Left(HBand::from_v_range(vr).unwrap())))
808            } else {
809                None
810            }
811        }
812    }
813
814    pub fn union_intersect(self, union_with: Rect, intersect_with: Rect) -> Rect {
815        match self.union(union_with) {
816            None => intersect_with,
817            Some(Right(rect)) => rect.intersect(intersect_with),
818            Some(Left(Right(v_band))) => Rect {
819                tl: Point { x: v_band.l, y: intersect_with.t() },
820                size: Vector { x: v_band.w.get(), y: intersect_with.h() }
821            },
822            Some(Left(Left(h_band))) => Rect {
823                tl: Point { y: h_band.t, x: intersect_with.l() },
824                size: Vector { y: h_band.h.get(), x: intersect_with.w() }
825            },
826        }
827    }
828 
829    pub fn offset(self, d: Vector) -> Rect {
830        Rect { tl: self.tl.offset(d), size: self.size }
831    }
832
833    pub fn relative_to(self, base: Point) -> Rect {
834        Rect { tl: self.tl.relative_to(base), size: self.size }
835    }
836
837    pub fn absolute_with(self, base: Point) -> Rect {
838        Rect { tl: self.tl.absolute_with(base), size: self.size }
839    }
840
841    pub fn t_line(self) -> Rect {
842        let height = min(1, self.size.y as u16) as i16;
843        Rect { tl: self.tl, size: Vector { x: self.size.x, y: height } }
844    }
845
846    pub fn b_line(self) -> Rect {
847        let height = min(1, self.size.y as u16) as i16;
848        Rect {
849            tl: Point { x: self.l(), y: self.b().wrapping_sub(height) },
850            size: Vector { x: self.size.x, y: height }
851        }
852    }
853
854    pub fn l_line(self) -> Rect {
855        let width = min(1, self.size.x as u16) as i16;
856        Rect { tl: self.tl, size: Vector { x: width, y: self.size.y } }
857    }
858
859    pub fn r_line(self) -> Rect {
860        let width = min(1, self.size.x as u16) as i16;
861        Rect {
862            tl: Point { x: self.r().wrapping_sub(width), y: self.t() },
863            size: Vector { x: width, y: self.size.y }
864        }
865    }
866}
867
868#[cfg(test)]
869impl Arbitrary for Rect {
870    fn arbitrary(g: &mut Gen) -> Self {
871        let a = <(Point, Point)>::arbitrary(g);
872        Rect::from_tl_br(a.0, a.1)
873    }
874}
875
876#[cfg(test)]
877mod tests {
878    use quickcheck::TestResult;
879    use quickcheck_macros::quickcheck;
880    use crate::*;
881
882    #[test]
883    fn test_range_iterator() {
884        let r = Range1d::new(0, 29).step_by(2);
885        assert_eq!(r.count(), 15);
886    }
887
888    #[quickcheck]
889    fn rect_area(r: Rect) -> bool {
890        r.area() == r.size.rect_area()
891    }
892
893    #[quickcheck]
894    #[allow(clippy::bool_comparison)]
895    fn rect_is_empty_area(r: Rect) -> bool {
896        !r.is_empty() == (r.area() > 0)
897    }
898
899    #[quickcheck]
900    fn null_size_rect_is_empty(tl: Point) -> bool {
901        Rect { tl, size: Vector::null() }.is_empty()
902    }
903
904    #[quickcheck]
905    fn rect_empty_intersect(tl1: Point, r2: Rect) -> bool {
906        let r1 = Rect { tl: tl1, size: Vector::null() };
907        r1.intersect(r2) == r1
908    }
909
910    #[quickcheck]
911    fn rect_intersect_empty(r1: Rect, tl2: Point) -> bool {
912        let r2 = Rect { tl: tl2, size: Vector::null() };
913        r1.is_empty() || r1.contains(r1.intersect(r2).tl)
914    }
915
916    #[quickcheck]
917    fn rect_intersect_contains(r1: Rect, r2: Rect, p: Point) -> bool {
918        r1.intersect(r2).contains(p) || !(r1.contains(p) && r2.contains(p))
919    }
920
921    #[quickcheck]
922    fn rect_union_contains(r1: Rect, r2: Rect, p: Point) -> bool {
923        r1.union(r2).map_or(true, |u| u.either(|_| true, |u| u.contains(p))) || !(r1.contains(p) || r2.contains(p))
924    }
925
926    #[quickcheck]
927    fn rect_empty_h_union(tl1: Point, r2: Rect, w: i16) -> bool {
928        let r1 = Rect { tl: tl1, size: Vector { x: w, y: 0} };
929        r2.is_empty() || r1.union(r2).unwrap().right().unwrap() == r2
930    }
931
932    #[quickcheck]
933    fn rect_union_empty_h(r1: Rect, tl2: Point, w: i16) -> bool {
934        let r2 = Rect { tl: tl2, size: Vector { x: w, y: 0 } };
935        r1.union(r2).unwrap().right().unwrap() == r1
936    }
937
938    #[quickcheck]
939    fn rect_empty_w_union(tl1: Point, r2: Rect, h: i16) -> bool {
940        let r1 = Rect { tl: tl1, size: Vector { x: 0, y: h } };
941        r2.is_empty() || r1.union(r2).unwrap().right().unwrap() == r2
942    }
943
944    #[quickcheck]
945    fn rect_union_empty_w(r1: Rect, tl2: Point, h: i16) -> bool {
946        let r2 = Rect { tl: tl2, size: Vector { x: 0, y: h } };
947        r1.union(r2).unwrap().right().unwrap() == r1
948    }
949
950    #[quickcheck]
951    fn rect_contains_all_self_points(r: Rect) -> TestResult {
952        if r.area() > 100000 { return TestResult::discard(); }
953        TestResult::from_bool(r.points().all(|x| r.contains(x)))
954    }
955}