sark_http/field/metadata/packed/
decoded.rs1use std::mem;
2
3use map::{Owned, record::Entry};
4use o3::{
5 alloc,
6 buffer::{bytes::scope, pool, pool::owners, storage::Shared, write},
7};
8use packed::{Iter, RangeIter, prefix::Prefix};
9use write::{SpareExt as _, edit, spans};
10
11use crate::field::metadata::{self, lower::plain::Error, map, packed, section::storage};
12
13#[derive(Debug)]
14#[repr(transparent)]
15pub struct Decoded<S = pool::Span, const PREFIX: usize = 0> {
16 storage: S,
17}
18
19impl Decoded {
20 pub fn try_from(storage: pool::Span) -> Result<Self, storage::Fault> {
22 Ok(<Self as storage::Block>::from(storage::Finished::try_from(
23 storage,
24 )?))
25 }
26}
27
28impl<const PREFIX: usize> Decoded<pool::Span, PREFIX> {
29 pub fn into_lease(self) -> pool::Span {
31 self.storage
32 }
33}
34
35impl<const PREFIX: usize> From<Decoded<pool::Span, PREFIX>> for Shared {
36 fn from(value: Decoded<pool::Span, PREFIX>) -> Self {
37 value.storage.freeze().into_shared()
38 }
39}
40
41impl<S: AsRef<[u8]>, const PREFIX: usize> Decoded<S, PREFIX> {
42 pub fn iter(&self) -> Iter<'_> {
43 Iter::new(&self.storage.as_ref()[PREFIX..])
44 }
45
46 pub fn len(&self) -> usize {
47 self.iter().count()
48 }
49
50 pub fn is_empty(&self) -> bool {
51 self.storage.as_ref().len() == PREFIX
52 }
53
54 pub fn get(&self, name: &[u8]) -> Option<&[u8]> {
55 self.iter()
56 .find(|field| field.name == name)
57 .map(|field| field.value)
58 }
59
60 pub fn as_bytes(&self) -> &[u8] {
61 self.storage.as_ref()
62 }
63
64 pub fn ranges(&self) -> RangeIter<'_> {
65 RangeIter::new(self.storage.as_ref(), PREFIX)
66 }
67
68 pub fn try_to_owned(&self) -> Result<Vec<Owned>, alloc::Error> {
69 let mut fields = Vec::new();
70 for field in self.iter() {
71 alloc::try_vacant(&mut fields)?(Owned::try_from(field)?);
72 }
73 Ok(fields)
74 }
75}
76
77impl<const PREFIX: usize> metadata::Metadata for Decoded<pool::Span, PREFIX> {
78 type Iter<'a> = Iter<'a>;
79
80 fn fields(&self) -> Self::Iter<'_> {
81 self.iter()
82 }
83}
84
85impl<const PREFIX: usize> storage::Block for Decoded<pool::Span, PREFIX> {
86 type Format = storage::Raw;
87 const PREFIX: &'static [u8] = &[0; PREFIX];
88
89 fn from(storage: storage::Finished<Self>) -> Self {
90 Self {
91 storage: storage.into_lease(),
92 }
93 }
94
95 fn into_bytes(self) -> storage::Bytes {
96 storage::Bytes::new(self.storage.freeze())
97 }
98}
99
100impl<S: AsRef<[u8]>, const PREFIX: usize> AsRef<[u8]> for Decoded<S, PREFIX> {
101 fn as_ref(&self) -> &[u8] {
102 self.storage.as_ref()
103 }
104}
105
106impl<const PREFIX: usize> PartialEq for Decoded<pool::Span, PREFIX> {
107 fn eq(&self, other: &Self) -> bool {
108 self.storage.as_ref() == other.storage.as_ref()
109 }
110}
111
112impl<const PREFIX: usize> Eq for Decoded<pool::Span, PREFIX> {}
113
114impl<'a, const PREFIX: usize> IntoIterator for &'a Decoded<pool::Span, PREFIX> {
115 type Item = Entry<'a>;
116 type IntoIter = Iter<'a>;
117
118 fn into_iter(self) -> Self::IntoIter {
119 self.iter()
120 }
121}
122
123const _: () = assert!(
124 mem::size_of::<Decoded>()
125 == mem::size_of::<pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>()
126);
127const _: () = assert!(mem::size_of::<Option<Decoded>>() == mem::size_of::<Decoded>());
128
129impl<const PREFIX: usize> storage::Scope for Decoded<pool::Span, PREFIX> {
130 type Scoped<'id> = Decoded<
131 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
132 PREFIX,
133 >;
134
135 fn scope<T>(self, use_head: impl for<'id> FnOnce(Self::Scoped<'id>) -> T) -> T {
136 scope::Owner::with(self.storage.freeze(), |storage| {
139 use_head(Decoded { storage })
140 })
141 }
142}
143
144impl<'id, const PREFIX: usize>
145 Decoded<
146 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
147 PREFIX,
148 >
149{
150 pub fn view(&self) -> scope::View<'_, 'id> {
151 self.storage.view()
152 }
153}
154
155impl<'id, const PREFIX: usize>
156 From<
157 Decoded<
158 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
159 PREFIX,
160 >,
161 > for scope::Owner<'id, Shared>
162{
163 fn from(
164 head: Decoded<
165 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
166 PREFIX,
167 >,
168 ) -> Self {
169 head.storage.into_shared()
170 }
171}
172
173impl<const PREFIX: usize> storage::Writer<Decoded<pool::Span, PREFIX>> {
174 pub fn try_write<E>(
176 &mut self,
177 write: impl FnOnce(&mut spans::Writer<'_, '_>) -> Result<usize, E>,
178 ) -> Result<(), E>
179 where
180 E: From<Error>,
181 {
182 self.try_write_as(crate::field::Indexing::Allowed, write)
183 }
184
185 pub fn try_write_as<E>(
186 &mut self,
187 indexing: crate::field::Indexing,
188 write: impl FnOnce(&mut spans::Writer<'_, '_>) -> Result<usize, E>,
189 ) -> Result<(), E>
190 where
191 E: From<Error>,
192 {
193 let mut output =
194 edit::Edit::try_new(self.lease.spare(), &[0; Prefix::LEN]).map_err(Error::Write)?;
195 let mut payload = output.bounded();
196 let name = write(&mut payload)?;
197 payload.commit();
198 let payload = output.len() - Prefix::LEN;
199 let value = payload
200 .checked_sub(name)
201 .ok_or(Error::Layout([0, name, payload]))?;
202 *output.prefix() = Prefix::try_new(name, value, indexing)?.to_bytes();
203 output.commit();
204 Ok(())
205 }
206}