sark_http/field/metadata/map/
mod.rs1use std::mem;
4
5use metadata::packed::{Iter, RangeIter, prefix::Prefix};
6use o3::{
7 alloc,
8 alloc::{BoxSliceExt as _, VecExt as _},
9 buffer::write::{self, Sink as _, consume},
10};
11use record::Entry;
12
13use crate::field::metadata;
14
15pub mod record;
16
17#[derive(PartialEq, Eq)]
18pub struct Owned {
19 pub name: Vec<u8>,
20 pub value: Vec<u8>,
21 pub indexing: crate::field::Indexing,
22}
23
24impl Owned {
25 pub fn try_new(name: &[u8], value: &[u8]) -> Result<Self, alloc::Exhausted> {
26 Ok(Self {
27 name: Box::<[u8]>::try_copy(name)?.into_vec(),
28 value: Box::<[u8]>::try_copy(value)?.into_vec(),
29 indexing: crate::field::Indexing::Allowed,
30 })
31 }
32
33 pub fn as_ref(&self) -> Entry<'_> {
34 Entry::new(&self.name, &self.value).with_index(self.indexing)
35 }
36
37 pub fn with_index(mut self, indexing: crate::field::Indexing) -> Self {
38 self.indexing = indexing;
39 self
40 }
41}
42
43impl TryFrom<Entry<'_>> for Owned {
44 type Error = alloc::Exhausted;
45
46 fn try_from(field: Entry<'_>) -> Result<Self, Self::Error> {
47 Ok(Self::try_new(field.name, field.value)?.with_index(field.indexing))
48 }
49}
50
51#[derive(Clone)]
52pub struct OwnedIter<'a> {
53 fields: &'a [Owned],
54}
55
56impl<'a> Iterator for OwnedIter<'a> {
57 type Item = Entry<'a>;
58
59 fn next(&mut self) -> Option<Self::Item> {
60 let (field, rest) = self.fields.split_first()?;
61 self.fields = rest;
62 Some(field.as_ref())
63 }
64
65 fn size_hint(&self) -> (usize, Option<usize>) {
66 let len = self.fields.len();
67 (len, Some(len))
68 }
69}
70
71impl ExactSizeIterator for OwnedIter<'_> {}
72
73impl metadata::Metadata for Vec<Owned> {
74 type Iter<'a> = OwnedIter<'a>;
75
76 fn fields(&self) -> Self::Iter<'_> {
77 OwnedIter {
78 fields: self.as_slice(),
79 }
80 }
81}
82
83#[derive(PartialEq, Eq)]
85pub struct Fields {
86 bytes: Vec<u8>,
87}
88
89#[derive(Clone, Debug, PartialEq, Eq)]
90pub enum Error {
91 Reserve(alloc::Error),
92 Write(consume::Error),
93 ComponentTooLarge {
94 len: usize,
95 },
96 ValueLengthMismatch {
97 expected: usize,
98 actual: usize,
99 },
100}
101
102fn packed_len(len: usize) -> Result<u32, usize> {
103 if len > u32::MAX as usize {
104 return Err(len);
105 }
106 Ok(len as u32)
107}
108
109impl From<usize> for Error {
110 fn from(len: usize) -> Self {
111 Self::ComponentTooLarge { len }
112 }
113}
114
115impl metadata::Metadata for Fields {
116 type Iter<'a> = Iter<'a>;
117
118 fn fields(&self) -> Self::Iter<'_> {
119 Iter::new(self.bytes.as_ref())
120 }
121}
122
123impl Fields {
124 pub const fn new() -> Self {
125 Self { bytes: Vec::new() }
126 }
127
128 pub fn try_with(capacity: usize) -> Result<Self, Error> {
129 Ok(Self {
130 bytes: Vec::try_new(capacity).map_err(Error::Reserve)?,
131 })
132 }
133
134 pub fn push(&mut self, name: &[u8], value: &[u8]) -> Result<(), Error> {
135 self.push_entry(Entry::new(name, value))
136 }
137
138 pub fn push_entry(&mut self, field: Entry<'_>) -> Result<(), Error> {
139 Space::new(
140 &mut self.bytes,
141 field.name.len(),
142 field.value.len(),
143 field.indexing,
144 )?
145 .generated(field.name, |writer| writer.write_slice(field.value))?
146 .commit();
147 Ok(())
148 }
149
150 pub fn push_encoded<F>(&mut self, name: &[u8], vlen: usize, encode: F) -> Result<(), Error>
154 where
155 F: FnOnce(&mut ValueWriter<'_>) -> Result<(), consume::Error>,
156 {
157 self.push_with(name, vlen, crate::field::Indexing::Allowed, encode)
158 }
159
160 pub fn push_with<F>(
162 &mut self,
163 name: &[u8],
164 vlen: usize,
165 indexing: crate::field::Indexing,
166 encode: F,
167 ) -> Result<(), Error>
168 where
169 F: FnOnce(&mut ValueWriter<'_>) -> Result<(), consume::Error>,
170 {
171 Space::new(&mut self.bytes, name.len(), vlen, indexing)?
172 .generated(name, encode)?
173 .commit();
174 Ok(())
175 }
176
177 pub fn iter(&self) -> Iter<'_> {
178 Iter::new(self.bytes.as_ref())
179 }
180
181 pub fn get(&self, name: &[u8]) -> Option<&[u8]> {
182 self.iter()
183 .find(|field| field.name == name)
184 .map(|field| field.value)
185 }
186
187 pub fn as_bytes(&self) -> &[u8] {
188 self.bytes.as_ref()
189 }
190
191 pub fn ranges(&self) -> RangeIter<'_> {
192 RangeIter::new(self.bytes.as_ref(), 0)
193 }
194}
195
196impl Default for Fields {
197 fn default() -> Self {
198 Self::new()
199 }
200}
201
202#[repr(transparent)]
204pub struct ValueWriter<'a>(write::Staged<'a, usize>);
205
206impl write::Sink for ValueWriter<'_> {
207 type Error = consume::Error;
208
209 fn write_slice(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
210 self.0.write_slice(bytes)
211 }
212
213 fn write_slices<const N: usize>(&mut self, slices: [&[u8]; N]) -> Result<(), Self::Error> {
214 self.0.write_slices(slices)
215 }
216}
217
218const _: () = {
219 assert!(mem::size_of::<OwnedIter<'static>>() == mem::size_of::<&[Owned]>());
220 assert!(
221 mem::size_of::<ValueWriter<'static>>() == mem::size_of::<write::Staged<'static, usize>>()
222 );
223};
224
225struct Space<'a> {
226 stage: write::Staged<'a, usize>,
227 prefix: [u8; Prefix::LEN],
228 vlen: usize,
229}
230
231impl<'a> Space<'a> {
232 fn new(
233 bytes: &'a mut Vec<u8>,
234 name: usize,
235 value: usize,
236 indexing: crate::field::Indexing,
237 ) -> Result<Self, Error> {
238 let nwire = packed_len(name)?;
239 let vwire = packed_len(value)?;
240 let added = Prefix::LEN + nwire as usize + vwire as usize;
241 let stage = write::Staged::<usize>::try_reserve(bytes, added).map_err(Error::Reserve)?;
242 Ok(Self {
243 stage,
244 prefix: Prefix::new(nwire, vwire, indexing).to_bytes(),
245 vlen: value,
246 })
247 }
248
249 fn generated<F>(self, name: &[u8], encode: F) -> Result<write::Staged<'a, usize>, Error>
250 where
251 F: FnOnce(&mut ValueWriter<'_>) -> Result<(), consume::Error>,
252 {
253 let expected = self.vlen;
254 let prefix = self.stage.capacity() - expected;
255 let mut writer = ValueWriter(self.stage);
256 writer
257 .write_slices([&self.prefix, name])
258 .map_err(Error::Write)?;
259 encode(&mut writer).map_err(Error::Write)?;
260 writer.0.try_complete().map_err(|error| {
261 let (_, actual) = error.into_parts();
262 Error::ValueLengthMismatch {
263 expected,
264 actual: actual - prefix,
265 }
266 })
267 }
268}