sark_http/field/metadata/block/
table.rs1use crate::field::metadata::{block, map::record::Span};
2
3pub struct Table<'a, const N: usize> {
5 entries: [(&'a [u8], &'a [u8]); N],
6 names: [block::Name; N],
7}
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub struct Error {
11 pub index: usize,
12}
13
14#[derive(Clone, Copy)]
16pub struct Entry<'table, 'data> {
17 bytes: &'table (&'data [u8], &'data [u8]),
18 proof: block::Name,
19}
20
21impl<'a, const N: usize> Table<'a, N> {
22 pub const fn try_new(entries: [(&'a [u8], &'a [u8]); N]) -> Result<Self, Error> {
23 let mut names = [block::Name::REGULAR; N];
24 let mut index = 0;
25 while index < N {
26 let (name, value) = entries[index];
27 let mut scan = block::Value::new();
28 let mut offset = 0;
29 while offset < value.len() {
30 scan.push(value[offset]);
31 offset += 1;
32 }
33 if !scan.is_valid() {
34 return Err(Error { index });
35 }
36 names[index] = block::Name::classify(name);
37 index += 1;
38 }
39 Ok(Self { entries, names })
40 }
41
42 pub const fn len(&self) -> usize {
43 N
44 }
45
46 pub const fn is_empty(&self) -> bool {
47 N == 0
48 }
49
50 pub const fn entries(&self) -> &[(&'a [u8], &'a [u8]); N] {
51 &self.entries
52 }
53
54 pub fn get(&self, index: usize) -> Option<Entry<'_, 'a>> {
55 let bytes = self.entries.get(index)?;
56 Some(Entry {
57 bytes,
58 proof: self.names[index],
59 })
60 }
61}
62
63impl<'a> Entry<'_, 'a> {
64 pub const fn name(self) -> block::Named<'a> {
65 block::Named::from_scanned(Span::from_slice(self.bytes.0), self.proof)
66 }
67
68 pub const fn value(self) -> &'a [u8] {
69 self.bytes.1
70 }
71
72 pub const fn valued(self) -> block::Valued<'a> {
73 block::Valued::from_scanned(Span::from_slice(self.bytes.1), block::Validation::Valid)
74 }
75
76 pub const fn validation(self) -> block::Validation {
77 if self.proof.is_forbidden() {
78 block::Validation::Malformed
79 } else {
80 block::Validation::Valid
81 }
82 }
83}
84
85const _: () = assert!(core::mem::size_of::<Entry<'_, '_>>() == 2 * core::mem::size_of::<usize>());