]>
Commit | Line | Data |
---|---|---|
1 | use std::collections::VecDeque; | |
2 | use nihav_core::io::bitwriter::*; | |
3 | ||
4 | const BUNDLE_LEN_BITS: u8 = 13; | |
5 | const MAX_BUNDLE_LEN: usize = 1 << BUNDLE_LEN_BITS; | |
6 | ||
7 | #[derive(Default)] | |
8 | struct Bundle<T:Copy> { | |
9 | bits: u8, | |
10 | data: VecDeque<(usize, Vec<T>)>, | |
11 | row: usize, | |
12 | tmp: Vec<T>, | |
13 | end: bool, | |
14 | last_w: usize, | |
15 | } | |
16 | ||
17 | impl<T:Copy> Bundle<T> { | |
18 | fn reset(&mut self, bits: u8) { | |
19 | self.bits = bits; | |
20 | self.end = false; | |
21 | self.last_w = 0; | |
22 | } | |
23 | fn new_row(&mut self, row: usize) { | |
24 | self.row = row; | |
25 | } | |
26 | fn push(&mut self, val: T) { | |
27 | self.tmp.push(val); | |
28 | } | |
29 | fn push_all(&mut self, slc: &[T]) { | |
30 | self.tmp.extend_from_slice(slc); | |
31 | } | |
32 | fn end_row(&mut self) { | |
33 | if !self.tmp.is_empty() { | |
34 | let mut tmp = Vec::new(); | |
35 | std::mem::swap(&mut tmp, &mut self.tmp); | |
36 | self.data.push_back((self.row, tmp)); | |
37 | } | |
38 | } | |
39 | } | |
40 | ||
41 | trait IntoU32 { | |
42 | fn into_u32(self) -> u32; | |
43 | } | |
44 | ||
45 | impl IntoU32 for u8 { | |
46 | fn into_u32(self) -> u32 { u32::from(self) } | |
47 | } | |
48 | ||
49 | impl IntoU32 for i8 { | |
50 | fn into_u32(self) -> u32 { (self + 16) as u32 } | |
51 | } | |
52 | ||
53 | impl IntoU32 for u16 { | |
54 | fn into_u32(self) -> u32 { u32::from(self) } | |
55 | } | |
56 | ||
57 | impl IntoU32 for i16 { | |
58 | fn into_u32(self) -> u32 { (self + 1024) as u32 } | |
59 | } | |
60 | ||
61 | impl Bundle<(u16, u8)> { | |
62 | fn write(&mut self, bw: &mut BitWriter, cur_row: usize) { | |
63 | if !self.data.is_empty() && self.data[0].0 == cur_row { | |
64 | let (_, row_data) = self.data.pop_front().unwrap(); | |
65 | for &(bits, len) in row_data.iter() { | |
66 | bw.write(u32::from(bits), len); | |
67 | } | |
68 | } | |
69 | } | |
70 | } | |
71 | ||
72 | impl<T: Copy+IntoU32> Bundle<T> { | |
73 | fn write(&mut self, bw: &mut BitWriter, cur_row: usize) { | |
74 | if !self.end && cur_row == self.last_w { | |
75 | let mut num_out = 0; | |
76 | let mut len_out = 0; | |
77 | for (_, row) in self.data.iter() { | |
78 | if len_out + row.len() < MAX_BUNDLE_LEN { | |
79 | len_out += row.len(); | |
80 | num_out += 1; | |
81 | } else { | |
82 | break; | |
83 | } | |
84 | } | |
85 | ||
86 | bw.write(len_out as u32, BUNDLE_LEN_BITS); | |
87 | if len_out == 0 { | |
88 | self.end = true; | |
89 | return; | |
90 | } | |
91 | for _ in 0..num_out { | |
92 | let (row_no, row_data) = self.data.pop_front().unwrap(); | |
93 | self.last_w = row_no + 1; | |
94 | for &el in row_data.iter() { | |
95 | bw.write(el.into_u32(), self.bits); | |
96 | } | |
97 | } | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
102 | #[derive(Default)] | |
103 | pub struct Bundles { | |
104 | btype: Bundle<u8>, | |
105 | colors: Bundle<u8>, | |
106 | pattern: Bundle<u8>, | |
107 | xoff: Bundle<i8>, | |
108 | yoff: Bundle<i8>, | |
109 | intradc: Bundle<u16>, | |
110 | interdc: Bundle<i16>, | |
111 | intraq: Bundle<u8>, | |
112 | interq: Bundle<u8>, | |
113 | nresidues: Bundle<u8>, | |
114 | other: Bundle<(u16, u8)>, | |
115 | } | |
116 | ||
117 | macro_rules! whole_bundle { | |
118 | ($self:expr, $func:ident) => { | |
119 | $self.btype.$func(); | |
120 | $self.colors.$func(); | |
121 | $self.pattern.$func(); | |
122 | $self.xoff.$func(); | |
123 | $self.yoff.$func(); | |
124 | $self.intradc.$func(); | |
125 | $self.interdc.$func(); | |
126 | $self.intraq.$func(); | |
127 | $self.interq.$func(); | |
128 | $self.nresidues.$func(); | |
129 | $self.other.$func(); | |
130 | }; | |
131 | ($self:expr, $func:ident, $($args:expr),*) => { | |
132 | $self.btype.$func($($args),*); | |
133 | $self.colors.$func($($args),*); | |
134 | $self.pattern.$func($($args),*); | |
135 | $self.xoff.$func($($args),*); | |
136 | $self.yoff.$func($($args),*); | |
137 | $self.intradc.$func($($args),*); | |
138 | $self.interdc.$func($($args),*); | |
139 | $self.intraq.$func($($args),*); | |
140 | $self.interq.$func($($args),*); | |
141 | $self.nresidues.$func($($args),*); | |
142 | $self.other.$func($($args),*); | |
143 | } | |
144 | } | |
145 | ||
146 | impl Bundles { | |
147 | pub fn reset(&mut self) { | |
148 | self.btype.reset(4); | |
149 | self.colors.reset(8); | |
150 | self.pattern.reset(8); | |
151 | self.xoff.reset(5); | |
152 | self.yoff.reset(5); | |
153 | self.intradc.reset(11); | |
154 | self.interdc.reset(11); | |
155 | self.intraq.reset(4); | |
156 | self.interq.reset(4); | |
157 | self.nresidues.reset(7); | |
158 | } | |
159 | pub fn add_block_type(&mut self, btype: u8) { | |
160 | self.btype.push(btype); | |
161 | } | |
162 | pub fn write(&mut self, bw: &mut BitWriter, row: usize) { | |
163 | whole_bundle!(self, write, bw, row); | |
164 | } | |
165 | pub fn new_row(&mut self, row: usize) { | |
166 | whole_bundle!(self, new_row, row); | |
167 | } | |
168 | pub fn end_row(&mut self) { | |
169 | whole_bundle!(self, end_row); | |
170 | } | |
171 | ||
172 | pub fn can_fit_raw_block(&self) -> bool { | |
173 | self.colors.data.len() < MAX_BUNDLE_LEN - 1 - 64 | |
174 | } | |
175 | pub fn add_tokens(&mut self, tokens: &BlockTokens) { | |
176 | self.colors.push_all(&tokens.colors); | |
177 | self.pattern.push_all(&tokens.pattern); | |
178 | self.xoff.push_all(&tokens.xoff); | |
179 | self.yoff.push_all(&tokens.yoff); | |
180 | self.intradc.push_all(&tokens.intradc); | |
181 | self.interdc.push_all(&tokens.interdc); | |
182 | self.intraq.push_all(&tokens.intraq); | |
183 | self.interq.push_all(&tokens.interq); | |
184 | self.nresidues.push_all(&tokens.nresidues); | |
185 | self.other.push_all(&tokens.other); | |
186 | } | |
187 | } | |
188 | ||
189 | #[derive(Default)] | |
190 | pub struct BlockTokens { | |
191 | pub colors: Vec<u8>, | |
192 | pub pattern: Vec<u8>, | |
193 | pub xoff: Vec<i8>, | |
194 | pub yoff: Vec<i8>, | |
195 | pub intradc: Vec<u16>, | |
196 | pub interdc: Vec<i16>, | |
197 | pub intraq: Vec<u8>, | |
198 | pub interq: Vec<u8>, | |
199 | pub nresidues: Vec<u8>, | |
200 | pub other: Vec<(u16, u8)>, | |
201 | } | |
202 | ||
203 | impl BlockTokens { | |
204 | pub fn new() -> Self { Self::default() } | |
205 | pub fn clear(&mut self) { | |
206 | self.colors.clear(); | |
207 | self.pattern.clear(); | |
208 | self.xoff.clear(); | |
209 | self.yoff.clear(); | |
210 | self.intradc.clear(); | |
211 | self.interdc.clear(); | |
212 | self.intraq.clear(); | |
213 | self.interq.clear(); | |
214 | self.nresidues.clear(); | |
215 | self.other.clear(); | |
216 | } | |
217 | pub fn bits(&self, is_b: bool) -> usize { | |
218 | if is_b { | |
219 | self.colors.len() * 8 + | |
220 | self.pattern.len() * 8 + | |
221 | self.xoff.len() * 5 + | |
222 | self.yoff.len() * 5 + | |
223 | self.intradc.len() * 11 + | |
224 | self.interdc.len() * 11 + | |
225 | self.intraq.len() * 4 + | |
226 | self.interq.len() * 4 + | |
227 | self.nresidues.len() * 7 + | |
228 | self.other.iter().fold(0usize, |acc, &(_, len)| acc + usize::from(len)) | |
229 | } else { | |
230 | unimplemented!() | |
231 | } | |
232 | } | |
233 | } |