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