use std::ops::{Range, RangeBounds, RangeInclusive}; use crate::Image; impl Image { /// ``` /// let i = fimg::Image::<_, 1>::alloc(5, 5); /// dbg!(i.bounds((0, 0)..(6, 0))); /// panic!(); /// ``` pub fn bounds(&self, r: impl PBounds) -> std::ops::Range where T: AsRef<[U]>, { let r = r.bound(); let start = match r.start_bound() { std::ops::Bound::Included(&(x, y)) => self.at(x, y), std::ops::Bound::Excluded(&(x, y)) => self.at(x, y) + CHANNELS, std::ops::Bound::Unbounded => 0, }; let end = match r.end_bound() { std::ops::Bound::Included(&(x, y)) => self.at(x, y) + CHANNELS, std::ops::Bound::Excluded(&(x, y)) => self.at(x, y), std::ops::Bound::Unbounded => self.buffer.as_ref().len(), }; start..end } } pub trait PBounds { fn bound(self) -> impl RangeBounds<(u32, u32)>; } impl PBounds for Range<(u32, u32)> { fn bound(self) -> impl RangeBounds<(u32, u32)> { self } } impl PBounds for RangeInclusive<(u32, u32)> { fn bound(self) -> impl RangeBounds<(u32, u32)> { self } } impl PBounds for (Range, u32) { fn bound(self) -> impl RangeBounds<(u32, u32)> { (self.0.start, self.1)..(self.0.end, self.1) } } impl PBounds for (u32, Range) { fn bound(self) -> impl RangeBounds<(u32, u32)> { (self.0, self.1.start)..(self.0, self.1.end) } }