diff --git a/.gitignore b/.gitignore index ea8c4bf..3ab5292 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +/Cargo.lock +.idea diff --git a/src/array2d.rs b/src/array2d.rs new file mode 100644 index 0000000..c2c1be5 --- /dev/null +++ b/src/array2d.rs @@ -0,0 +1,98 @@ +use crate::index2d::Index2D; + +pub trait Container2D { + type Output; + const HEIGHT: u32; + const WIDTH: u32; + + fn get(&self, i: I) -> Option<&Self::Output>; +} + +pub trait Container2DMut: Container2D { + fn get_mut(&mut self, i: I) -> Option<&mut Self::Output>; +} + +/// A 2D owning array of T +#[derive(Debug)] +pub struct Array2D { + pub data: [[T; N as usize]; M as usize], +} + +impl Container2D for Array2D { + type Output = T; + const HEIGHT: u32 = M; + const WIDTH: u32 = N; + + fn get(&self, i: I) -> Option<&Self::Output> { + let (r, c) = i.to_2d(Self::WIDTH); + self.data.get(r)?.get(c) + } +} + +impl Container2DMut for Array2D { + fn get_mut(&mut self, i: I) -> Option<&mut Self::Output> { + let (r, c) = i.to_2d(Self::WIDTH); + self.data.get_mut(r)?.get_mut(c) + } +} + +/// A 2D immutable view into a Container2D +#[derive(Debug)] +pub struct View2D<'a, D: Container2D, const M: u32, const N: u32> { + r: u32, + c: u32, + data: &'a D, +} + +impl<'a, D: Container2D, const M: u32, const N: u32> Container2D for View2D<'a, D, M, N> { + type Output = D::Output; + const HEIGHT: u32 = M; + const WIDTH: u32 = N; + + fn get(&self, i: I) -> Option<&Self::Output> { + self.data.get(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?) + } +} + +impl<'a, D: Container2DMut, const M: u32, const N: u32> Container2D for Slice2D<'a, D, M, N> { + type Output = D::Output; + const HEIGHT: u32 = M; + const WIDTH: u32 = N; + + fn get(&self, i: I) -> Option<&Self::Output> { + self.data.get(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?) + } +} + +/// A 2D mutable view into a Container2D +#[derive(Debug)] +pub struct Slice2D<'a, D: Container2DMut, const M: u32, const N: u32> { + r: u32, + c: u32, + data: &'a mut D, +} + +impl<'a, D: Container2DMut, const M: u32, const N: u32> Container2DMut +for Slice2D<'a, D, M, N> +{ + fn get_mut(&mut self, i: I) -> Option<&mut Self::Output> { + self.data.get_mut(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?) + } +} + +// An immutable transposition of a Container2D +#[derive(Debug)] +pub struct Transpose<'a, D: Container2D> { + pub data: &'a D, +} + +impl<'a, D: Container2D> Container2D for Transpose<'a, D> { + type Output = D::Output; + const HEIGHT: u32 = D::WIDTH; + const WIDTH: u32 = D::HEIGHT; + + fn get(&self, i: I) -> Option<&Self::Output> { + let (r, c) = i.to_2d(Self::WIDTH); + self.data.get((c, r)) + } +} diff --git a/src/index2d.rs b/src/index2d.rs new file mode 100644 index 0000000..c43317f --- /dev/null +++ b/src/index2d.rs @@ -0,0 +1,28 @@ +pub trait Index2D { + fn to_1d(&self, width: u32) -> u32 { + let (r, c) = self.to_2d(width); + r * width + c + } + + fn to_2d(&self, width: u32) -> (u32, u32); + + fn to_2d_offset(&self, width: u32, height: u32, r: u32, c: u32) -> Option<(u32, u32)> { + let (row, col) = self.to_2d(width); + if row >= height || col >= width { + return None; + }; + Some((row + r, col + c)) + } +} + +impl Index2D for u32 { + fn to_2d(&self, width: u32) -> (u32, u32) { + (*self / width, *self % width) + } +} + +impl Index2D for (u32, u32) { + fn to_2d(&self, _: u32) -> (u32, u32) { + *self + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4e11a00 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +mod array2d; +mod index2d; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -}