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!("Failed to parse the metadata as namespace table. Use a single namespace table instead.");
26 return vec![(0..payload_byte_len)];
27 }
28 let num_entries = u32::from_le_bytes(bytes[..NUM_NSS_BYTE_LEN].try_into().unwrap()) as usize;
29 if num_entries
30 != bytes.len().saturating_sub(NUM_NSS_BYTE_LEN)
31 / NS_ID_BYTE_LEN.saturating_add(NS_OFFSET_BYTE_LEN)
32 || (num_entries == 0 && payload_byte_len != 0)
33 {
34 tracing::warn!("Failed to parse the metadata as namespace table. Use a single namespace table instead.");
35 return vec![(0..payload_byte_len)];
36 }
37 if num_entries == 0 {
39 return vec![(0..payload_byte_len)];
40 }
41 let mut l = 0;
42 for i in 0..num_entries {
43 let offset = NUM_NSS_BYTE_LEN + i * (NS_ID_BYTE_LEN + NS_OFFSET_BYTE_LEN) + NS_ID_BYTE_LEN;
44 let r = u32::from_le_bytes(
45 bytes[offset..offset + NS_OFFSET_BYTE_LEN]
46 .try_into()
47 .unwrap(),
48 ) as usize;
49 if r < l || r > payload_byte_len {
50 tracing::warn!("Failed to parse the metadata as namespace table. Use a single namespace table instead.");
51 return vec![(0..payload_byte_len)];
52 }
53 result.push(l..r);
54 l = r;
55 }
56 if l != payload_byte_len {
57 tracing::warn!("Failed to parse the metadata as namespace table. Use a single namespace table instead.");
58 return vec![(0..payload_byte_len)];
59 }
60 result
61}