use std::cmp::Eq; use std::collections::VecDeque; use std::fmt::Debug; use std::hash::Hash; use std::ops::{Add, Index, IndexMut, Mul, Sub}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Vector2D<T> { x: T, y: T, } impl<T> Vector2D<T> { pub fn new(x: T, y: T) -> Vector2D<T> { Vector2D { x, y } } } impl<T: Copy> Vector2D<T> { pub fn swap(&self) -> Self { Self { x: self.y, y: self.x, } } pub fn x(&self) -> T { self.x } pub fn y(&self) -> T { self.y } } macro_rules! generate_indices { ($container:ty) => { impl<I, C> Index<Vector2D<I>> for $container where I: Copy + TryInto<usize>, <I as TryInto<usize>>::Error: Debug, C: Index<usize>, { type Output = C::Output; fn index(&self, index: Vector2D<I>) -> &Self::Output { let (x, y): (usize, usize) = (index.x.try_into().unwrap(), index.y.try_into().unwrap()); &self[y][x] } } impl<I, C> IndexMut<Vector2D<I>> for $container where I: Copy + TryInto<usize>, <I as TryInto<usize>>::Error: Debug, C: IndexMut<usize>, { fn index_mut(&mut self, index: Vector2D<I>) -> &mut Self::Output { let (x, y): (usize, usize) = (index.x.try_into().unwrap(), index.y.try_into().unwrap()); &mut self[y][x] } } }; } generate_indices!(VecDeque<C>); generate_indices!([C]); generate_indices!(Vec<C>); // generate_indices!([C; N], const N: usize); pub fn in_range<I, C>(v: &[Vec<C>], idx: &Vector2D<I>) -> bool where I: Copy, usize: TryFrom<I>, { usize::try_from(idx.y) .and_then(|y| usize::try_from(idx.x).map(|x| y < v.len() && x < v[y].len())) .unwrap_or(false) } // See: https://github.com/rust-lang/rust/issues/102731 // impl<U: From<T>, T> From<Vector2D<T>> for Vector2D<U> { // fn from(value: Vector2D<T>) -> Self { // Self { // x: U::from(value.x), // y: U::from(value.y), // } // } // } impl<T: Add + Add<Output = U>, U> Add for Vector2D<T> { type Output = Vector2D<U>; fn add(self, rhs: Self) -> Self::Output { Vector2D { x: self.x + rhs.x, y: self.y + rhs.y, } } } impl<T: Sub + Sub<Output = U>, U> Sub for Vector2D<T> { type Output = Vector2D<U>; fn sub(self, rhs: Self) -> Self::Output { Vector2D { x: self.x - rhs.x, y: self.y - rhs.y, } } } impl<T: Mul + Mul<Output = U>, U> Mul for Vector2D<T> { type Output = Vector2D<U>; fn mul(self, rhs: Self) -> Self::Output { Vector2D { x: self.x * rhs.x, y: self.y * rhs.y, } } } impl<T: Mul + Mul<Output = U> + Copy, U> Mul<T> for Vector2D<T> { type Output = Vector2D<U>; fn mul(self, rhs: T) -> Self::Output { Vector2D { x: self.x * rhs, y: self.y * rhs, } } }