rust/vec2d/src/lib.rs
branchui-scaling
changeset 15288 c4fd2813b127
parent 14707 29dbe9ce8b7d
equal deleted inserted replaced
13395:0135e64c6c66 15288:c4fd2813b127
       
     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 }