yoin_core/dic/
matrix.rs

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}