|
1 use std::{ |
|
2 ops::{Index, IndexMut}, |
|
3 slice::SliceIndex |
|
4 }; |
|
5 use integral_geometry::Size; |
|
6 |
|
7 pub struct Vec2D<T> { |
|
8 data: Vec<T>, |
|
9 size: Size, |
|
10 } |
|
11 |
|
12 impl<T> Index<usize> for Vec2D<T> { |
|
13 type Output = [T]; |
|
14 |
|
15 #[inline] |
|
16 fn index(&self, row: usize) -> &[T] { |
|
17 debug_assert!(row < self.height()); |
|
18 |
|
19 let pos = row * self.width(); |
|
20 |
|
21 &self.data[pos..pos + self.width()] |
|
22 } |
|
23 } |
|
24 |
|
25 impl<T> IndexMut<usize> for Vec2D<T> { |
|
26 #[inline] |
|
27 fn index_mut(&mut self, row: usize) -> &mut [T] { |
|
28 debug_assert!(row < self.height()); |
|
29 |
|
30 let pos = row * self.width(); |
|
31 |
|
32 &mut self.data[pos..pos + self.size.width] |
|
33 } |
|
34 } |
|
35 |
|
36 impl <T> Vec2D<T> { |
|
37 #[inline] |
|
38 pub fn width(&self) -> usize { |
|
39 self.size.width |
|
40 } |
|
41 |
|
42 #[inline] |
|
43 pub fn height(&self) -> usize { |
|
44 self.size.height |
|
45 } |
|
46 |
|
47 #[inline] |
|
48 pub fn size(&self) -> Size { |
|
49 self.size |
|
50 } |
|
51 } |
|
52 |
|
53 impl<T: Copy> Vec2D<T> { |
|
54 pub fn new(size: Size, value: T) -> Self { |
|
55 Self { size, data: vec![value; size.area()] } |
|
56 } |
|
57 |
|
58 #[inline] |
|
59 pub fn as_slice(&self) -> &[T] { |
|
60 self.data.as_slice() |
|
61 } |
|
62 |
|
63 #[inline] |
|
64 pub fn as_mut_slice(&mut self) -> &mut [T] { |
|
65 self.data.as_mut_slice() |
|
66 } |
|
67 |
|
68 #[inline] |
|
69 pub fn get(&self, row: usize, column: usize) -> Option<&<usize as SliceIndex<[T]>>::Output> { |
|
70 self.data.get(row * self.width() + column) |
|
71 } |
|
72 |
|
73 #[inline] |
|
74 pub fn get_mut(&mut self, row: usize, column: usize) -> Option<&mut <usize as SliceIndex<[T]>>::Output> { |
|
75 self.data.get_mut(row * self.size.width + column) |
|
76 } |
|
77 |
|
78 #[inline] |
|
79 pub unsafe fn get_unchecked(&self, row: usize, column: usize) -> &<usize as SliceIndex<[T]>>::Output { |
|
80 self.data.get_unchecked(row * self.width() + column) |
|
81 } |
|
82 |
|
83 #[inline] |
|
84 pub unsafe fn get_unchecked_mut(&mut self, row: usize, column: usize) -> &mut <usize as SliceIndex<[T]>>::Output { |
|
85 self.data.get_unchecked_mut(row * self.size.width + column) |
|
86 } |
|
87 |
|
88 #[inline] |
|
89 pub fn rows(&self) -> impl DoubleEndedIterator<Item = &[T]> { |
|
90 self.data.chunks_exact(self.width()) |
|
91 } |
|
92 |
|
93 #[inline] |
|
94 pub fn rows_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut [T]> { |
|
95 let width = self.width(); |
|
96 self.data.chunks_exact_mut(width) |
|
97 } |
|
98 |
|
99 #[inline] |
|
100 pub unsafe fn as_bytes(&self) -> &[u8] { |
|
101 use std::{ |
|
102 slice, |
|
103 mem |
|
104 }; |
|
105 |
|
106 slice::from_raw_parts( |
|
107 self.data.as_ptr() as *const u8, |
|
108 self.data.len() * mem::size_of::<T>(), |
|
109 ) |
|
110 } |
|
111 } |
|
112 |
|
113 impl<T: Copy> AsRef<[T]> for Vec2D<T> { |
|
114 fn as_ref(&self) -> &[T] { |
|
115 self.as_slice() |
|
116 } |
|
117 } |
|
118 |
|
119 impl<T: Copy> AsMut<[T]> for Vec2D<T> { |
|
120 fn as_mut(&mut self) -> &mut [T] { |
|
121 self.as_mut_slice() |
|
122 } |
|
123 } |
|
124 |
|
125 #[cfg(test)] |
|
126 mod tests { |
|
127 use super::*; |
|
128 |
|
129 #[test] |
|
130 fn basics() { |
|
131 let mut v: Vec2D<u8> = Vec2D::new(Size::new(2, 3), 0xff); |
|
132 |
|
133 assert_eq!(v.width(), 2); |
|
134 assert_eq!(v.height(), 3); |
|
135 |
|
136 assert_eq!(v[0][0], 0xff); |
|
137 assert_eq!(v[2][1], 0xff); |
|
138 |
|
139 v[2][1] = 0; |
|
140 |
|
141 assert_eq!(v[2][0], 0xff); |
|
142 assert_eq!(v[2][1], 0); |
|
143 |
|
144 v.get_mut(2, 1).map(|v| *v = 1); |
|
145 assert_eq!(v[2][1], 1); |
|
146 |
|
147 assert_eq!(v.get_mut(2, 2), None); |
|
148 } |
|
149 } |