1 use std::collections::VecDeque;
2 use nihav_core::io::bitwriter::*;
4 const BUNDLE_LEN_BITS: u8 = 13;
5 const MAX_BUNDLE_LEN: usize = 1 << BUNDLE_LEN_BITS;
8 struct Bundle<T:Copy> {
10 data: VecDeque<(usize, Vec<T>)>,
17 impl<T:Copy> Bundle<T> {
18 fn reset(&mut self, bits: u8) {
23 fn new_row(&mut self, row: usize) {
26 fn push(&mut self, val: T) {
29 fn push_all(&mut self, slc: &[T]) {
30 self.tmp.extend_from_slice(slc);
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));
42 fn into_u32(self) -> u32;
46 fn into_u32(self) -> u32 { u32::from(self) }
50 fn into_u32(self) -> u32 { (self + 16) as u32 }
53 impl IntoU32 for u16 {
54 fn into_u32(self) -> u32 { u32::from(self) }
57 impl IntoU32 for i16 {
58 fn into_u32(self) -> u32 { (self + 1024) as u32 }
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);
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 {
77 for (_, row) in self.data.iter() {
78 if len_out + row.len() < MAX_BUNDLE_LEN {
86 bw.write(len_out as u32, BUNDLE_LEN_BITS);
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);
109 intradc: Bundle<u16>,
110 interdc: Bundle<i16>,
113 nresidues: Bundle<u8>,
114 other: Bundle<(u16, u8)>,
117 macro_rules! whole_bundle {
118 ($self:expr, $func:ident) => {
120 $self.colors.$func();
121 $self.pattern.$func();
124 $self.intradc.$func();
125 $self.interdc.$func();
126 $self.intraq.$func();
127 $self.interq.$func();
128 $self.nresidues.$func();
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),*);
147 pub fn reset(&mut self) {
149 self.colors.reset(8);
150 self.pattern.reset(8);
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);
159 pub fn add_block_type(&mut self, btype: u8) {
160 self.btype.push(btype);
162 pub fn write(&mut self, bw: &mut BitWriter, row: usize) {
163 whole_bundle!(self, write, bw, row);
165 pub fn new_row(&mut self, row: usize) {
166 whole_bundle!(self, new_row, row);
168 pub fn end_row(&mut self) {
169 whole_bundle!(self, end_row);
172 pub fn can_fit_raw_block(&self) -> bool {
173 self.colors.data.len() < MAX_BUNDLE_LEN - 1 - 64
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);
190 pub struct BlockTokens {
192 pub pattern: Vec<u8>,
195 pub intradc: Vec<u16>,
196 pub interdc: Vec<i16>,
199 pub nresidues: Vec<u8>,
200 pub other: Vec<(u16, u8)>,
204 pub fn new() -> Self { Self::default() }
205 pub fn clear(&mut self) {
207 self.pattern.clear();
210 self.intradc.clear();
211 self.interdc.clear();
214 self.nresidues.clear();
217 pub fn bits(&self, is_b: bool) -> usize {
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))