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<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>> {
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 From<Decoded> for Shared {
29 fn from(value: Decoded) -> Self {
30 value.storage.into_shared()
31 }
32}
33
34impl<S: AsRef<[u8]>> Decoded<S> {
35 pub fn iter(&self) -> Iter<'_> {
36 Iter::new(self.storage.as_ref())
37 }
38
39 pub fn len(&self) -> usize {
40 self.iter().count()
41 }
42
43 pub fn is_empty(&self) -> bool {
44 self.storage.as_ref().is_empty()
45 }
46
47 pub fn get(&self, name: &[u8]) -> Option<&[u8]> {
48 self.iter()
49 .find(|field| field.name == name)
50 .map(|field| field.value)
51 }
52
53 pub fn as_bytes(&self) -> &[u8] {
54 self.storage.as_ref()
55 }
56
57 pub fn ranges(&self) -> RangeIter<'_> {
58 RangeIter::new(self.storage.as_ref())
59 }
60
61 pub fn try_to_owned(&self) -> Result<Vec<Owned>, alloc::Error> {
62 let mut fields = Vec::new();
63 for field in self.iter() {
64 let slot = alloc::Vacant::try_new(&mut fields)?;
65 slot.insert(Owned::try_from(field)?);
66 }
67 Ok(fields)
68 }
69}
70
71impl metadata::Metadata for Decoded {
72 type Iter<'a> = Iter<'a>;
73
74 fn fields(&self) -> Self::Iter<'_> {
75 Iter::new(self.storage.as_ref())
76 }
77}
78
79impl storage::Block for Decoded {
80 type Format = storage::Raw;
81
82 fn from(storage: storage::Finished<Self>) -> Self {
83 Self {
84 storage: storage.into_frozen(),
85 }
86 }
87
88 fn into_bytes(self) -> storage::Bytes {
89 storage::Bytes::new(self.storage)
90 }
91}
92
93impl<S: AsRef<[u8]>> AsRef<[u8]> for Decoded<S> {
94 fn as_ref(&self) -> &[u8] {
95 self.storage.as_ref()
96 }
97}
98
99impl PartialEq for Decoded {
100 fn eq(&self, other: &Self) -> bool {
101 self.storage.as_ref() == other.storage.as_ref()
102 }
103}
104
105impl Eq for Decoded {}
106
107impl<'a> IntoIterator for &'a Decoded {
108 type Item = Entry<'a>;
109 type IntoIter = Iter<'a>;
110
111 fn into_iter(self) -> Self::IntoIter {
112 self.iter()
113 }
114}
115
116const _: () = assert!(
117 mem::size_of::<Decoded>()
118 == mem::size_of::<pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>()
119);
120const _: () = assert!(mem::size_of::<Option<Decoded>>() == mem::size_of::<Decoded>());
121
122impl storage::Scope for Decoded {
123 type Scoped<'id> = Decoded<
124 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
125 >;
126
127 fn scope<T>(self, use_head: impl for<'id> FnOnce(Self::Scoped<'id>) -> T) -> T {
128 scope::Owner::with(self.storage, |storage| use_head(Decoded { storage }))
129 }
130}
131
132impl<'id>
133 Decoded<scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>>
134{
135 pub fn view(&self) -> scope::View<'_, 'id> {
136 self.storage.view()
137 }
138}
139
140impl<'id>
141 From<
142 Decoded<
143 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
144 >,
145 > for scope::Owner<'id, Shared>
146{
147 fn from(
148 head: Decoded<
149 scope::Owner<'id, pool::Span<owners::Plain<pool::Layout>, pool::Owned, pool::Frozen>>,
150 >,
151 ) -> Self {
152 head.storage.into_shared()
153 }
154}
155
156impl storage::Writer<Decoded> {
157 pub fn try_write<E>(
159 &mut self,
160 write: impl FnOnce(&mut spans::Writer<'_, '_, false>) -> Result<usize, E>,
161 ) -> Result<(), E>
162 where
163 E: From<Error>,
164 {
165 self.try_write_as(crate::field::Indexing::Allowed, write)
166 }
167
168 pub fn try_write_as<E>(
169 &mut self,
170 indexing: crate::field::Indexing,
171 write: impl FnOnce(&mut spans::Writer<'_, '_, false>) -> Result<usize, E>,
172 ) -> Result<(), E>
173 where
174 E: From<Error>,
175 {
176 let mut output =
177 edit::Edit::try_new(self.lease.spare(), &[0; Prefix::LEN]).map_err(Error::Write)?;
178 let mut payload = output.bounded();
179 let name = write(&mut payload)?;
180 payload.commit();
181 let payload = output.len() - Prefix::LEN;
182 let value = payload
183 .checked_sub(name)
184 .ok_or(Error::Layout([0, name, payload]))?;
185 *output.prefix() = Prefix::try_new(name, value, indexing)?.to_bytes();
186 output.commit();
187 Ok(())
188 }
189}