assembly_pack/common/
writer.rs

1//! # Writer for CRC trees
2
3use std::{
4    collections::BTreeMap,
5    io::{self, Write},
6    ops::Range,
7};
8
9/// Write a CRC tree to file
10///
11/// This function recursively subdivides the given `range` to implement a depth first tree-order traversal
12///
13/// For every leaf it calls [`Iterator::next`] and writes out the CRC key, left and right subindices
14/// and then the payload using `write_value`.
15fn write_crc_tree_recursive<V, W: Write, I: Iterator<Item = (u32, V)>>(
16    writer: &mut W,
17    iterator: &mut I,
18    range: Range<u32>,
19    write_value: fn(&mut W, V) -> io::Result<()>,
20) -> io::Result<()> {
21    let len = range.end - range.start;
22    match len {
23        0 => { /* Ignore */ }
24        _ => {
25            let mid = range.start + len / 2;
26
27            let left_range = range.start..mid;
28            let left_len = left_range.end - left_range.start;
29            let left_ptr = if left_len == 0 {
30                u32::MAX
31            } else {
32                left_range.start + left_len / 2
33            };
34
35            let right_range = (mid + 1)..range.end;
36            let right_len = right_range.end - right_range.start;
37            let right_ptr = if right_len == 0 {
38                u32::MAX
39            } else {
40                right_range.start + right_len / 2
41            };
42
43            write_crc_tree_recursive(writer, iterator, left_range, write_value)?;
44
45            let (crc, data) = iterator.next().unwrap();
46            writer.write_all(&crc.to_le_bytes())?;
47            writer.write_all(&left_ptr.to_le_bytes())?;
48            writer.write_all(&right_ptr.to_le_bytes())?;
49            write_value(writer, data)?;
50
51            write_crc_tree_recursive(writer, iterator, right_range, write_value)?;
52        }
53    }
54
55    Ok(())
56}
57
58/// Write a CRC tree to a writer
59pub fn write_crc_tree<V, W: Write>(
60    writer: &mut W,
61    tree: &BTreeMap<u32, V>,
62    write_value: fn(&mut W, &V) -> io::Result<()>,
63) -> io::Result<()> {
64    let len = tree.len() as u32;
65    writer.write_all(&len.to_le_bytes())?;
66    write_crc_tree_recursive(
67        writer,
68        &mut tree.iter().map(|(a, b)| (*a, b)),
69        0..len,
70        write_value,
71    )
72}