1use crate::{Result, error};
6use primase_foundations::bytes::View;
7
8const MAX_DEPTH: usize = 32;
10const MAX_ABBREVS_PER_BLOCK: usize = 4096;
11const MAX_ABBREV_OPS: usize = 256;
12const MAX_TOTAL_OPERANDS: usize = 1 << 26;
13
14#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct Record {
17 pub code: u64,
19 pub operands: Vec<u64>,
21 pub blob: Option<Vec<u8>>,
23 pub at: usize,
25}
26#[derive(Clone, Debug, PartialEq, Eq)]
28pub enum Element {
29 Block(Block),
31 Record(Record),
33}
34#[derive(Clone, Debug, PartialEq, Eq)]
36pub struct Block {
37 pub id: u64,
39 pub elements: Vec<Element>,
41 pub at: usize,
43}
44impl Block {
45 pub fn blocks(&self) -> impl Iterator<Item = &Block> {
47 self.elements.iter().filter_map(|e| match e {
48 Element::Block(b) => Some(b),
49 Element::Record(_) => None,
50 })
51 }
52 pub fn records(&self) -> impl Iterator<Item = &Record> {
54 self.elements.iter().filter_map(|e| match e {
55 Element::Record(r) => Some(r),
56 Element::Block(_) => None,
57 })
58 }
59}
60
61#[derive(Clone, Copy, Debug, PartialEq, Eq)]
62enum Op {
63 Literal(u64),
64 Fixed(u32),
65 Vbr(u32),
66 Array,
67 Char6,
68 Blob,
69}
70type Abbrev = Vec<Op>;
71
72const CHAR6: &[u8; 64] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._";
74
75struct Bits<'a> {
76 data: &'a [u8],
77 pos: usize,
79}
80impl Bits<'_> {
81 fn remaining(&self) -> usize {
82 self.data.len().saturating_mul(8).saturating_sub(self.pos)
83 }
84 fn read(&mut self, width: u32) -> Result<u64> {
85 if width > 64 {
86 return Err(error(self.pos, "field wider than 64 bits"));
87 }
88 let n = width as usize;
89 if n > self.remaining() {
90 return Err(error(self.pos, "bitstream ends inside a field"));
91 }
92 let mut value = 0u64;
93 for i in 0..width {
94 let bit = self.pos.saturating_add(i as usize);
95 let byte = self.data.get(bit / 8).copied().unwrap_or(0);
96 let shift = u32::try_from(bit % 8).unwrap_or(0);
97 if byte.checked_shr(shift).unwrap_or(0) & 1 == 1 {
98 value |= 1u64.checked_shl(i).unwrap_or(0);
99 }
100 }
101 self.pos = self.pos.saturating_add(n);
102 Ok(value)
103 }
104 fn vbr(&mut self, width: u32) -> Result<u64> {
105 if !(2..=32).contains(&width) {
106 return Err(error(self.pos, "VBR width outside 2..32"));
107 }
108 let at = self.pos;
109 let high = 1u64.checked_shl(width.saturating_sub(1)).unwrap_or(0);
110 let mut value = 0u64;
111 let mut shift = 0u32;
112 loop {
113 let chunk = self.read(width)?;
114 let payload = chunk & high.saturating_sub(1);
115 if payload != 0 {
116 if shift >= 64 || payload.leading_zeros() < shift {
118 return Err(error(at, "VBR value exceeds 64 bits"));
119 }
120 value |= payload.checked_shl(shift).unwrap_or(0);
121 }
122 if chunk & high == 0 {
123 return Ok(value);
124 }
125 shift = shift.saturating_add(width.saturating_sub(1));
126 if shift > 64 + 32 {
127 return Err(error(at, "VBR value exceeds 64 bits"));
128 }
129 }
130 }
131 fn align32(&mut self) -> Result<()> {
132 let aligned = self
133 .pos
134 .div_ceil(32)
135 .checked_mul(32)
136 .filter(|&aligned| aligned <= self.data.len().saturating_mul(8))
137 .ok_or_else(|| error(self.pos, "bitstream ends before 32-bit alignment"))?;
138 self.pos = aligned;
139 Ok(())
140 }
141 fn vbr_usize(&mut self, width: u32) -> Result<usize> {
143 let at = self.pos;
144 let value = self.vbr(width)?;
145 usize::try_from(value).map_err(|_| error(at, format!("{value} does not fit the address space")))
146 }
147 fn vbr_u32(&mut self, width: u32) -> Result<u32> {
149 let at = self.pos;
150 let value = self.vbr(width)?;
151 u32::try_from(value).map_err(|_| error(at, format!("{value} does not fit 32 bits")))
152 }
153}
154
155struct Reader<'a> {
156 bits: Bits<'a>,
157 info: Vec<(u64, Vec<Abbrev>)>,
159 operands: usize,
160}
161
162fn char6(v: u64) -> u64 {
163 let [index, ..] = v.to_le_bytes();
164 u64::from(CHAR6.get(usize::from(index)).copied().unwrap_or(b'_'))
165}
166
167impl Reader<'_> {
168 fn count(&mut self, n: usize) -> Result<()> {
169 self.operands = self
170 .operands
171 .checked_add(n)
172 .filter(|&t| t <= MAX_TOTAL_OPERANDS)
173 .ok_or_else(|| error(self.bits.pos, "too many record operands"))?;
174 Ok(())
175 }
176 fn scalar(&mut self, op: Op) -> Result<u64> {
177 match op {
178 Op::Literal(v) => Ok(v),
179 Op::Fixed(w) => self.bits.read(w),
180 Op::Vbr(w) => self.bits.vbr(w),
181 Op::Char6 => Ok(char6(self.bits.read(6)?)),
182 Op::Array | Op::Blob => Err(error(self.bits.pos, "array or blob as an element")),
183 }
184 }
185 fn define_abbrev(&mut self) -> Result<Abbrev> {
186 let at = self.bits.pos;
187 let n = self.bits.vbr_usize(5)?;
188 if n == 0 || n > MAX_ABBREV_OPS {
189 return Err(error(at, "abbreviation operand count"));
190 }
191 let mut ops = Vec::with_capacity(n);
192 while ops.len() < n {
193 if self.bits.read(1)? == 1 {
194 ops.push(Op::Literal(self.bits.vbr(8)?));
195 continue;
196 }
197 ops.push(match self.bits.read(3)? {
198 1 => {
199 let w = self.bits.vbr(5)?;
200 if w > 64 {
201 return Err(error(at, "fixed width above 64"));
202 }
203 Op::Fixed(u32::try_from(w).map_err(|_| error(at, "fixed width above 64"))?)
204 }
205 2 => {
206 let w = self.bits.vbr(5)?;
207 if !(2..=32).contains(&w) {
208 return Err(error(at, "VBR width outside 2..32"));
209 }
210 Op::Vbr(u32::try_from(w).map_err(|_| error(at, "VBR width outside 2..32"))?)
211 }
212 3 => Op::Array,
213 4 => Op::Char6,
214 5 => Op::Blob,
215 other => return Err(error(at, format!("abbreviation encoding {other}"))),
216 });
217 }
218 let mut rest = ops.as_slice();
220 while let Some((op, tail)) = rest.split_first() {
221 match (op, tail) {
222 (Op::Array, [Op::Array | Op::Blob, ..]) => {
223 return Err(error(at, "array not followed by one element encoding"));
224 }
225 (Op::Array, [_]) => {}
226 (Op::Array, _) => {
227 return Err(error(at, "array not followed by one element encoding"));
228 }
229 (Op::Blob, [_, ..]) => return Err(error(at, "blob not last")),
230 _ => {}
231 }
232 rest = tail;
233 }
234 Ok(ops)
235 }
236 fn abbreviated(&mut self, abbrev: &Abbrev, at: usize) -> Result<Record> {
237 let mut values: Vec<u64> = Vec::new();
238 let mut blob = None;
239 let mut rest = abbrev.as_slice();
240 while let Some((&op, tail)) = rest.split_first() {
241 rest = tail;
242 match op {
243 Op::Array => {
244 let Some((&element, after)) = tail.split_first() else {
245 return Err(error(at, "array without its element encoding"));
246 };
247 rest = after;
248 let len = self.bits.vbr_usize(6)?;
249 let min_bits = match element {
253 Op::Literal(_) | Op::Fixed(0) => 1,
254 Op::Fixed(w) | Op::Vbr(w) => w as usize,
255 Op::Char6 => 6,
256 _ => 1,
257 };
258 if self
259 .bits
260 .remaining()
261 .checked_div(min_bits)
262 .is_none_or(|most| len > most)
263 {
264 return Err(error(at, "array longer than the bits that remain"));
265 }
266 self.count(len)?;
267 values.reserve(len);
268 for _ in 0..len {
269 values.push(self.scalar(element)?);
270 }
271 }
272 Op::Blob => {
273 let len = self.bits.vbr_usize(6)?;
274 self.bits.align32()?;
275 if len > self.bits.remaining() / 8 {
276 return Err(error(at, "blob longer than the bits that remain"));
277 }
278 let start = self.bits.pos / 8;
279 let bytes = View::new(self.bits.data)
280 .slice(start, len)
281 .map_err(|e| error(at, e.to_string()))?;
282 blob = Some(bytes.to_vec());
283 self.bits.pos = self.bits.pos.saturating_add(len.saturating_mul(8));
284 self.bits.align32()?;
285 }
286 op => {
287 self.count(1)?;
288 values.push(self.scalar(op)?);
289 }
290 }
291 }
292 if values.is_empty() {
293 return Err(error(at, "abbreviated record without a code"));
294 }
295 let code = values.remove(0);
296 Ok(Record {
297 code,
298 operands: values,
299 blob,
300 at,
301 })
302 }
303 fn block(&mut self, id: u64, width: u32, end: usize, depth: usize, at: usize) -> Result<Block> {
305 if depth > MAX_DEPTH {
306 return Err(error(at, "blocks nested too deeply"));
307 }
308 let mut abbrevs: Vec<Abbrev> = self
309 .info
310 .iter()
311 .find(|(b, _)| *b == id)
312 .map(|(_, a)| a.clone())
313 .unwrap_or_default();
314 let mut elements = Vec::new();
315 let mut info_target: Option<u64> = None;
317 loop {
318 if self.bits.pos >= end {
319 return Err(error(at, "block ends without END_BLOCK"));
320 }
321 let here = self.bits.pos;
322 match self.bits.read(width)? {
323 0 => {
324 self.bits.align32()?;
325 if self.bits.pos != end {
326 return Err(error(here, "END_BLOCK before the declared block length"));
327 }
328 return Ok(Block { id, elements, at });
329 }
330 1 => {
331 let child = self.bits.vbr(8)?;
332 let child_width = self.bits.vbr_u32(4)?;
333 if !(1..=32).contains(&child_width) {
334 return Err(error(here, "abbreviation width outside 1..32"));
335 }
336 self.bits.align32()?;
337 let words = usize::try_from(self.bits.read(32)?)
338 .map_err(|_| error(here, "block longer than its parent"))?;
339 let child_end = words
340 .checked_mul(32)
341 .and_then(|b| b.checked_add(self.bits.pos))
342 .filter(|&e| e <= end)
343 .ok_or_else(|| error(here, "block longer than its parent"))?;
344 let b = self.block(child, child_width, child_end, depth.saturating_add(1), here)?;
345 elements.push(Element::Block(b));
346 }
347 2 => {
348 let abbrev = self.define_abbrev()?;
349 if id == 0 {
350 let target =
351 info_target.ok_or_else(|| error(here, "BLOCKINFO abbreviation before SETBID"))?;
352 let slot = match self.info.iter().position(|(b, _)| *b == target) {
353 Some(i) => i,
354 None => {
355 self.info.push((target, Vec::new()));
356 self.info.len().saturating_sub(1)
357 }
358 };
359 let Some((_, entry)) = self.info.get_mut(slot) else {
360 return Err(error(here, "BLOCKINFO abbreviation table"));
361 };
362 if entry.len() >= MAX_ABBREVS_PER_BLOCK {
363 return Err(error(here, "too many abbreviations"));
364 }
365 entry.push(abbrev);
366 } else {
367 if abbrevs.len() >= MAX_ABBREVS_PER_BLOCK {
368 return Err(error(here, "too many abbreviations"));
369 }
370 abbrevs.push(abbrev);
371 }
372 }
373 3 => {
374 let code = self.bits.vbr(6)?;
375 let n = self.bits.vbr_usize(6)?;
376 if n > self.bits.remaining() / 2 {
377 return Err(error(here, "record longer than the bits that remain"));
378 }
379 self.count(n)?;
380 let mut operands = Vec::with_capacity(n);
381 for _ in 0..n {
382 operands.push(self.bits.vbr(6)?);
383 }
384 if id == 0 && code == 1 {
385 info_target = Some(
386 *operands
387 .first()
388 .ok_or_else(|| error(here, "SETBID without a block id"))?,
389 );
390 }
391 elements.push(Element::Record(Record {
392 code,
393 operands,
394 blob: None,
395 at: here,
396 }));
397 }
398 n => {
399 let abbrev = usize::try_from(n.saturating_sub(4))
400 .ok()
401 .and_then(|i| abbrevs.get(i))
402 .cloned()
403 .ok_or_else(|| error(here, format!("undefined abbreviation {n}")))?;
404 let record = self.abbreviated(&abbrev, here)?;
405 if id == 0 && record.code == 1 {
406 info_target = record.operands.first().copied();
407 }
408 elements.push(Element::Record(record));
409 }
410 }
411 }
412 }
413}
414
415pub fn read(data: &[u8], magic: [u8; 4]) -> Result<Vec<Block>> {
417 if data.get(..4) != Some(&magic[..]) || !data.len().is_multiple_of(4) {
418 return Err(error(0, "bitstream magic or length"));
419 }
420 let mut r = Reader {
421 bits: Bits { data, pos: 32 },
422 info: Vec::new(),
423 operands: 0,
424 };
425 let end = data.len().saturating_mul(8);
426 let mut blocks = Vec::new();
427 while r.bits.pos < end {
428 let here = r.bits.pos;
429 if data
431 .get(here / 8..)
432 .is_none_or(|tail| tail.iter().all(|&b| b == 0))
433 {
434 break;
435 }
436 if r.bits.read(2)? != 1 {
437 return Err(error(here, "top level holds only blocks"));
438 }
439 let id = r.bits.vbr(8)?;
440 let width = r.bits.vbr_u32(4)?;
441 if !(1..=32).contains(&width) {
442 return Err(error(here, "abbreviation width outside 1..32"));
443 }
444 r.bits.align32()?;
445 let words =
446 usize::try_from(r.bits.read(32)?).map_err(|_| error(here, "block longer than the stream"))?;
447 let block_end = words
448 .checked_mul(32)
449 .and_then(|b| b.checked_add(r.bits.pos))
450 .filter(|&e| e <= end)
451 .ok_or_else(|| error(here, "block longer than the stream"))?;
452 blocks.push(r.block(id, width, block_end, 1, here)?);
453 }
454 Ok(blocks)
455}