1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use crate::{BitReader, BitWriter, Flags};
use crate::bits::bits_to_bytes;
use crate::constants::*;
use crate::prefix::Prefix;
use crate::types::NumberLike;

#[derive(Clone, Debug)]
pub struct ChunkMetadata<T> where T: NumberLike {
  pub n: usize,
  pub compressed_body_size: usize,
  pub prefixes: Vec<Prefix<T>>,
}

impl<T> ChunkMetadata<T> where T: NumberLike {
  pub fn parse_from(reader: &mut BitReader, flags: &Flags) -> Self {
    let n = reader.read_usize(BITS_TO_ENCODE_N_ENTRIES as usize);
    let compressed_body_size = reader.read_usize(BITS_TO_ENCODE_COMPRESSED_BODY_SIZE as usize);
    let n_pref = reader.read_usize(MAX_COMPRESSION_LEVEL as usize);
    let mut prefixes = Vec::with_capacity(n_pref);
    let bits_to_encode_prefix_len = flags.bits_to_encode_prefix_len();
    for _ in 0..n_pref {
      let count = reader.read_usize(BITS_TO_ENCODE_N_ENTRIES as usize);
      let lower_bits = reader.read(T::PHYSICAL_BITS);
      let lower = T::from_bytes(bits_to_bytes(lower_bits));
      let upper_bits = reader.read(T::PHYSICAL_BITS);
      let upper = T::from_bytes(bits_to_bytes(upper_bits));
      let code_len = reader.read_usize(bits_to_encode_prefix_len);
      let val = reader.read(code_len);
      let jumpstart = if reader.read_one() {
        Some(reader.read_usize(BITS_TO_ENCODE_JUMPSTART as usize))
      } else {
        None
      };
      prefixes.push(Prefix::new(count, val, lower, upper, jumpstart));
    }

    Self {
      n,
      compressed_body_size,
      prefixes,
    }
  }

  pub fn write_to(&self, writer: &mut BitWriter, flags: &Flags) {
    writer.write_usize(self.n, BITS_TO_ENCODE_N_ENTRIES as usize);
    writer.write_usize(self.compressed_body_size, BITS_TO_ENCODE_COMPRESSED_BODY_SIZE as usize);
    writer.write_usize(self.prefixes.len(), MAX_COMPRESSION_LEVEL as usize);
    let bits_to_encode_prefix_len = flags.bits_to_encode_prefix_len();
    for pref in &self.prefixes {
      writer.write_usize(pref.count, BITS_TO_ENCODE_N_ENTRIES as usize);
      writer.write_bytes(&T::bytes_from(pref.lower));
      writer.write_bytes(&T::bytes_from(pref.upper));
      writer.write_usize(pref.val.len(), bits_to_encode_prefix_len);
      writer.write_bits(&pref.val);
      match pref.run_len_jumpstart {
        None => {
          writer.write_one(false);
        },
        Some(jumpstart) => {
          writer.write_one(true);
          writer.write_usize(jumpstart, BITS_TO_ENCODE_JUMPSTART as usize);
        },
      }
    }
    writer.finish_byte();
  }

  pub fn update_write_compressed_body_size(&self, writer: &mut BitWriter, initial_idx: usize) {
    writer.assign_usize(
      initial_idx + BITS_TO_ENCODE_N_ENTRIES as usize / 8,
      BITS_TO_ENCODE_N_ENTRIES as usize % 8,
      self.compressed_body_size,
      BITS_TO_ENCODE_COMPRESSED_BODY_SIZE,
    );
  }
}

#[derive(Clone)]
pub struct DecompressedChunk<T> where T: NumberLike {
  pub metadata: ChunkMetadata<T>,
  pub nums: Vec<T>,
}