1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
use std::borrow::Borrow; use std::io::{self, Write}; use std::ops::{Index, IndexMut}; use byteorder::{NativeEndian, WriteBytesExt, ByteOrder}; #[derive(Debug, Clone, PartialEq)] pub struct Matrix<T: Borrow<[i16]>> { width: u16, height: u16, table: T, } impl Matrix<Vec<i16>> { pub fn with_zeros(width: u16, height: u16) -> Self { Matrix { width: width, height: height, table: vec![0; width as usize * height as usize], } } } impl<T: Borrow<[i16]>> Matrix<T> { pub fn encode<W: Write, O: ByteOrder>(&self, mut w: W) -> io::Result<()> { w.write_u16::<O>(self.width)?; w.write_u16::<O>(self.height)?; for &byte in self.table.borrow() { w.write_i16::<O>(byte)?; } Ok(()) } pub fn encode_native<W: Write>(&self, w: W) -> io::Result<()> { self.encode::<W, NativeEndian>(w) } pub fn row(&self, left_id: u16) -> &[i16] { let h = left_id as usize; let start = h * self.width as usize; &self.table.borrow()[start..start + self.width as usize] } } impl<'a> Matrix<&'a [i16]> { pub unsafe fn decode(bs: &'a [u8]) -> Self { let ptr = bs.as_ptr() as *const u16; let width = *ptr; let height = *ptr.offset(1); let ptr = ptr.offset(2) as *const i16; let table = ::std::slice::from_raw_parts(ptr, width as usize * height as usize); Matrix { width: width, height: height, table: table, } } } impl<T: Borrow<[i16]>> Index<(u16, u16)> for Matrix<T> { type Output = i16; fn index(&self, index: (u16, u16)) -> &i16 { let w = index.0 as usize; let h = index.1 as usize; &self.table.borrow()[w + h * self.width as usize] } } impl IndexMut<(u16, u16)> for Matrix<Vec<i16>> { fn index_mut(&mut self, index: (u16, u16)) -> &mut i16 { let w = index.0 as usize; let h = index.1 as usize; &mut self.table[w + h * self.width as usize] } } #[test] fn test_encode_decode() { let table: &[i16] = &[-3, -2, -1, 0, 1, 2]; let matrix = Matrix { width: 2, height: 3, table: table, }; let mut buf = Vec::new(); matrix.encode_native(&mut buf).unwrap(); let decoded = unsafe { Matrix::decode(&buf) }; assert_eq!(decoded, matrix); }