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