toad_msg/msg/opt/known/
block.rs

1/// Three items of information may need to be transferred in a
2/// Block (Block1 or Block2) option:
3/// * the size of the block ([`Block::size`])
4/// * whether more blocks are following ([`Block::more`])
5/// * the relative number of the block ([`Block::num`]) within a sequence of blocks with the given size.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct Block(u32);
8
9impl Block {
10  #[allow(missing_docs)]
11  pub fn new(size: u16, num: u32, more: bool) -> Self {
12    let num = num << 4;
13    let more = u32::from(more) << 3;
14    let size = f32::from(size.max(16).min(1024)).log2() as u32 - 4;
15
16    Self(num | more | size)
17  }
18
19  #[allow(missing_docs)]
20  pub fn size(&self) -> u16 {
21    let szx = (self.0 & 0b111).min(6);
22    2u16.pow(szx + 4)
23  }
24
25  #[allow(missing_docs)]
26  pub fn more(&self) -> bool {
27    (self.0 & 0b1000) >> 3 == 1
28  }
29
30  #[allow(missing_docs)]
31  pub fn num(&self) -> u32 {
32    self.0 >> 4
33  }
34}
35
36impl From<Block> for u32 {
37  fn from(b: Block) -> Self {
38    b.0
39  }
40}
41
42impl From<u32> for Block {
43  fn from(n: u32) -> Self {
44    Block(n)
45  }
46}
47
48#[cfg(test)]
49mod test {
50  use super::*;
51
52  #[test]
53  fn block() {
54    let b = Block(33);
55    assert_eq!(b.size(), 32);
56    assert_eq!(b.num(), 2);
57    assert_eq!(b.more(), false);
58
59    let b = Block(59);
60    assert_eq!(b.size(), 128);
61    assert_eq!(b.num(), 3);
62    assert_eq!(b.more(), true);
63
64    assert_eq!(Block::new(32, 2, false), Block(33));
65    assert_eq!(Block::new(128, 3, true), Block(59));
66  }
67
68  #[test]
69  fn size_rounds_down_to_nearest_power_of_two() {
70    assert_eq!(Block::new(0, 1, false).size(), 16);
71    assert_eq!(Block::new(10, 1, false).size(), 16);
72    assert_eq!(Block::new(17, 1, false).size(), 16);
73    assert_eq!(Block::new(31, 1, false).size(), 16);
74    assert_eq!(Block::new(33, 1, false).size(), 32);
75    assert_eq!(Block::new(64, 1, false).size(), 64);
76    assert_eq!(Block::new(1024, 1, false).size(), 1024);
77    assert_eq!(Block::new(2048, 1, false).size(), 1024);
78  }
79}