use direction::Orientation; use std::iter; /// A generic structure with a value for each axis. #[derive(Debug,Clone,Copy,PartialEq)] pub struct XY { /// X-axis value pub x: T, /// Y-axis value pub y: T, } impl XY { /// Creates a new `XY` from the given values. pub fn new(x: T, y: T) -> Self { XY { x: x, y: y } } /// Creates a new `XY` by applying `f` to `x` and `y`. pub fn map U>(self, f: F) -> XY { XY::new(f(self.x), f(self.y)) } /// Destructure self into a pair. pub fn pair(self) -> (T, T) { (self.x, self.y) } /// Return a `XY` with references to this one's values. pub fn as_ref(&self) -> XY<&T> { XY::new(&self.x, &self.y) } /// Creates an iterator that returns references to `x`, then `y`. pub fn iter(&self) -> iter::Chain, iter::Once<&T>> { iter::once(&self.x).chain(iter::once(&self.y)) } /// Returns a reference to the value on the given axis. pub fn get(&self, o: Orientation) -> &T { match o { Orientation::Horizontal => &self.x, Orientation::Vertical => &self.y, } } /// Returns a new `XY` by calling `f` on `self` and `other` for each axis. pub fn zip_map V>(self, other: XY, f: F) -> XY { XY::new(f(self.x, other.x), f(self.y, other.y)) } } impl XY> { /// Returns a new `XY` by calling `unwrap_or` on each axis. pub fn unwrap_or(self, other: XY) -> XY { self.zip_map(other, |s, o| s.unwrap_or(o)) } } impl XY { /// Returns `true` if any of `x` or `y` is `true`. pub fn any(&self) -> bool { self.x || self.y } /// Returns `true` if both `x` and `y` are `true`. pub fn both(&self) -> bool { self.x && self.y } } impl XY { /// Creates a `XY` with both `x` and `y` set to `value`. pub fn both_from(value: T) -> Self { XY::new(value, value) } } impl From<(T, T)> for XY { fn from((x, y): (T, T)) -> Self { XY::new(x, y) } }