1use nom::number::complete::le_i16;
18
19use crate::error::{SudachiError, SudachiResult};
20use crate::util::cow_array::CowArray;
21
22pub struct ConnectionMatrix<'a> {
23 data: CowArray<'a, i16>,
24 num_left: usize,
25 num_right: usize,
26}
27
28impl<'a> ConnectionMatrix<'a> {
29 pub fn from_bytes(buf: &'a [u8]) -> SudachiResult<ConnectionMatrix<'a>> {
30 let (rest, (num_left, num_right)) = nom::sequence::tuple((le_i16, le_i16))(buf)?;
31 Self::from_offset_size(rest, 0, num_left as usize, num_right as usize)
32 }
33
34 pub fn from_offset_size(
35 data: &'a [u8],
36 offset: usize,
37 num_left: usize,
38 num_right: usize,
39 ) -> SudachiResult<ConnectionMatrix<'a>> {
40 let size = num_left * num_right;
41 let end = offset + size * std::mem::size_of::<i16>();
42 if end > data.len() {
43 return Err(SudachiError::InvalidDictionaryGrammar.with_context("connection matrix"));
44 }
45
46 Ok(ConnectionMatrix {
47 data: CowArray::from_bytes(data, offset, size),
48 num_left,
49 num_right,
50 })
51 }
52
53 #[inline(always)]
54 fn index(&self, left: u16, right: u16) -> usize {
55 let uleft = left as usize;
56 let uright = right as usize;
57 debug_assert!(
58 uleft < self.num_left,
59 "left id {} is out of range (num_left={})",
60 uleft,
61 self.num_left
62 );
63 debug_assert!(
64 uright < self.num_right,
65 "right id {} is out of range (num_right={})",
66 uright,
67 self.num_right
68 );
69 let index = uright * self.num_left + uleft;
70 debug_assert!(index < self.data.len());
71 index
72 }
73
74 #[inline(always)]
84 pub fn cost(&self, left: u16, right: u16) -> i16 {
85 let index = self.index(left, right);
86 *unsafe { self.data.get_unchecked(index) }
87 }
88
89 pub fn update(&mut self, left: u16, right: u16, value: i16) {
90 let index = self.index(left, right);
91 self.data.set(index, value);
92 }
93
94 pub fn num_left(&self) -> usize {
96 self.num_left
97 }
98
99 pub fn num_right(&self) -> usize {
101 self.num_right
102 }
103}
104
105impl ConnectionMatrix<'static> {
106 pub fn empty() -> Self {
107 ConnectionMatrix {
108 data: CowArray::from_owned(Vec::new()),
109 num_left: 0,
110 num_right: 0,
111 }
112 }
113}