hotshot_types/data/
ns_table.rs1use std::ops::Range;
10
11const NUM_NSS_BYTE_LEN: usize = 4;
13const NS_OFFSET_BYTE_LEN: usize = 4;
14const NS_ID_BYTE_LEN: usize = 4;
15
16#[allow(clippy::single_range_in_vec_init)]
20pub fn parse_ns_table(payload_byte_len: usize, bytes: &[u8]) -> Vec<Range<usize>> {
21 let mut result = vec![];
22 if bytes.len() < NUM_NSS_BYTE_LEN
23 || (bytes.len() - NUM_NSS_BYTE_LEN) % (NS_OFFSET_BYTE_LEN + NS_ID_BYTE_LEN) != 0
24 {
25 tracing::warn!(
26 "Failed to parse the metadata as namespace table. Use a single namespace table \
27 instead."
28 );
29 return vec![(0..payload_byte_len)];
30 }
31 let num_entries = u32::from_le_bytes(bytes[..NUM_NSS_BYTE_LEN].try_into().unwrap()) as usize;
32 if num_entries
33 != bytes.len().saturating_sub(NUM_NSS_BYTE_LEN)
34 / NS_ID_BYTE_LEN.saturating_add(NS_OFFSET_BYTE_LEN)
35 || (num_entries == 0 && payload_byte_len != 0)
36 {
37 tracing::warn!(
38 "Failed to parse the metadata as namespace table. Use a single namespace table \
39 instead."
40 );
41 return vec![(0..payload_byte_len)];
42 }
43 if num_entries == 0 {
45 return vec![(0..payload_byte_len)];
46 }
47 let mut l = 0;
48 for i in 0..num_entries {
49 let offset = NUM_NSS_BYTE_LEN + i * (NS_ID_BYTE_LEN + NS_OFFSET_BYTE_LEN) + NS_ID_BYTE_LEN;
50 let r = u32::from_le_bytes(
51 bytes[offset..offset + NS_OFFSET_BYTE_LEN]
52 .try_into()
53 .unwrap(),
54 ) as usize;
55 if r < l || r > payload_byte_len {
56 tracing::warn!(
57 "Failed to parse the metadata as namespace table. Use a single namespace table \
58 instead."
59 );
60 return vec![(0..payload_byte_len)];
61 }
62 result.push(l..r);
63 l = r;
64 }
65 if l != payload_byte_len {
66 tracing::warn!(
67 "Failed to parse the metadata as namespace table. Use a single namespace table \
68 instead."
69 );
70 return vec![(0..payload_byte_len)];
71 }
72 result
73}