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 let slot = alloc::Vacant::try_new(&mut fields)?;
72 slot.insert(Owned::try_from(field)?);
73 }
74 Ok(fields)
75 }
76}
77
78impl<const PREFIX: usize> metadata::Metadata for Decoded<pool::Span, PREFIX> {
79 type Iter<'a> = Iter<'a>;
80
81 fn fields(&self) -> Self::Iter<'_> {
82 self.iter()
83 }
84}
85
86impl<const PREFIX: usize> storage::Block for Decoded<pool::Span, PREFIX> {
87 type Format = storage::Raw;
88 const PREFIX: &'static [u8] = &[0; PREFIX];
89
90 fn from(storage: storage::Finished<Self>) -> Self {
91 Self {
92 storage: storage.into_lease(),
93 }
94 }
95
96 fn into_bytes(self) -> storage::Bytes {
97 storage::Bytes::new(self.storage.freeze())
98 }
99}
100
101impl<S: AsRef<[u8]>, const PREFIX: usize> AsRef<[u8]> for Decoded<S, PREFIX> {
102 fn as_ref(&self) -> &[u8] {
103 self.storage.as_ref()
104 }
105}
106
107impl<const PREFIX: usize> PartialEq for Decoded<pool::Span, PREFIX> {
108 fn eq(&self, other: &Self) -> bool {
109 self.storage.as_ref() == other.storage.as_ref()
110 }
111}
112
113impl<const PREFIX: usize> Eq for Decoded<pool::Span, PREFIX> {}
114
115impl<'a, const PREFIX: usize> IntoIterator for &'a Decoded<pool::Span, PREFIX> {
116 type Item = Entry<'a>;
117 type IntoIter = Iter<'a>;
118
119 fn into_iter(self) -> Self::IntoIter {
120 self.iter()
121 }
122}
123
124const _: () = assert!(
125 mem::size_of::<Decoded>()
126 == mem::size_of::<pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>()
127);
128const _: () = assert!(mem::size_of::<Option<Decoded>>() == mem::size_of::<Decoded>());
129
130impl<const PREFIX: usize> storage::Scope for Decoded<pool::Span, PREFIX> {
131 type Scoped<'id> = Decoded<
132 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
133 PREFIX,
134 >;
135
136 fn scope<T>(self, use_head: impl for<'id> FnOnce(Self::Scoped<'id>) -> T) -> T {
137 scope::Owner::with(self.storage.freeze(), |storage| {
140 use_head(Decoded { storage })
141 })
142 }
143}
144
145impl<'id, const PREFIX: usize>
146 Decoded<
147 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
148 PREFIX,
149 >
150{
151 pub fn view(&self) -> scope::View<'_, 'id> {
152 self.storage.view()
153 }
154}
155
156impl<'id, const PREFIX: usize>
157 From<
158 Decoded<
159 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
160 PREFIX,
161 >,
162 > for scope::Owner<'id, Shared>
163{
164 fn from(
165 head: Decoded<
166 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
167 PREFIX,
168 >,
169 ) -> Self {
170 head.storage.into_shared()
171 }
172}
173
174impl<const PREFIX: usize> storage::Writer<Decoded<pool::Span, PREFIX>> {
175 pub fn try_write<E>(
177 &mut self,
178 write: impl FnOnce(&mut spans::Writer<'_, '_, false>) -> Result<usize, E>,
179 ) -> Result<(), E>
180 where
181 E: From<Error>,
182 {
183 self.try_write_as(crate::field::Indexing::Allowed, write)
184 }
185
186 pub fn try_write_as<E>(
187 &mut self,
188 indexing: crate::field::Indexing,
189 write: impl FnOnce(&mut spans::Writer<'_, '_, false>) -> Result<usize, E>,
190 ) -> Result<(), E>
191 where
192 E: From<Error>,
193 {
194 let mut output =
195 edit::Edit::try_new(self.lease.spare(), &[0; Prefix::LEN]).map_err(Error::Write)?;
196 let mut payload = output.bounded();
197 let name = write(&mut payload)?;
198 payload.commit();
199 let payload = output.len() - Prefix::LEN;
200 let value = payload
201 .checked_sub(name)
202 .ok_or(Error::Layout([0, name, payload]))?;
203 *output.prefix() = Prefix::try_new(name, value, indexing)?.to_bytes();
204 output.commit();
205 Ok(())
206 }
207}