1use std::{convert, num, ops};
2
3use storage::{provided, range};
4use write::consume;
5
6use crate::{buffer::pool::owners, mem::rc};
7
8pub mod raw;
9
10pub mod bytes;
11pub mod hold;
12pub mod pool;
13pub mod resident;
14pub mod segments;
15pub mod storage;
16pub mod write;
17
18#[must_use]
22#[repr(C)]
23pub struct View<'source, S: ?Sized> {
24 source: &'source S,
25 bytes: &'source [u8],
26}
27
28impl<S: ?Sized> Copy for View<'_, S> {}
29
30impl<S: ?Sized> Clone for View<'_, S> {
31 fn clone(&self) -> Self {
32 *self
33 }
34}
35
36impl<'source, S: ?Sized> View<'source, S> {
37 pub fn as_slice(&self) -> &'source [u8] {
38 self.bytes
39 }
40
41 pub fn is_empty(&self) -> bool {
42 self.bytes.is_empty()
43 }
44
45 pub fn len(&self) -> usize {
46 self.bytes.len()
47 }
48
49 pub fn select(&self, bytes: &[u8]) -> Option<View<'source, S>> {
50 let range: ops::Range<usize> = self.bytes.subslice_range(bytes)?.into();
51 Some(Self {
54 source: self.source,
55 bytes: unsafe { self.bytes.get_unchecked(range) },
56 })
57 }
58
59 pub fn get(&self, range: ops::Range<usize>) -> Option<View<'source, S>> {
60 let bytes = self.bytes.get(range)?;
61 Some(View {
62 source: self.source,
63 bytes,
64 })
65 }
66
67 pub fn try_get(&self, range: ops::Range<usize>) -> Result<Self, range::Error> {
68 let bytes = self.bytes.try_get(range)?;
69 Ok(Self {
70 source: self.source,
71 bytes,
72 })
73 }
74
75 pub fn new(source: &'source S) -> Self
77 where
78 S: AsRef<[u8]>,
79 {
80 Self {
81 source,
82 bytes: source.as_ref(),
83 }
84 }
85}
86
87impl<S: segments::Seal> View<'_, S> {
88 pub fn try_retain(self) -> Result<S, rc::Error> {
90 use storage::regions::NonEmpty;
91
92 let Some(view) = NonEmpty::new(&self) else {
93 return Ok(S::EMPTY);
94 };
95 S::try_share(view).map(segments::Item::into_inner)
96 }
97}
98
99impl View<'_, resident::Shared<'_>> {
100 pub fn try_own(self) -> Result<Option<storage::Shared>, rc::Error> {
103 if self.is_empty() {
104 return Ok(Some(storage::Shared::new()));
105 }
106 let owner = match self.source.region.owner() {
107 resident::State::Owned(owner) => Some(owner.try_clone()?),
108 resident::State::Static => None,
109 resident::State::Slice
110 | resident::State::Resident(_)
111 | resident::State::Accounted(_)
112 | resident::State::Provided(_) => return Ok(None),
113 };
114 Ok(Some(unsafe {
117 storage::Shared::assume(self.as_slice(), owner)
118 }))
119 }
120}
121
122const _: () = assert!(size_of::<View<'static, storage::Shared>>() == 3 * size_of::<usize>());
123
124impl<S: ?Sized> consume::Consume for View<'_, S> {
125 fn remaining(&self) -> usize {
126 self.bytes.len()
127 }
128 fn try_consume(&mut self, amount: usize) -> Result<(), consume::Error> {
129 raw::Selection::try_new(self, amount).map(raw::Selection::consume)
130 }
131
132 fn consume_max(&mut self, max: usize) -> usize {
133 raw::Store::advance_max(self, max)
134 }
135}
136
137impl<S: ?Sized> AsRef<[u8]> for View<'_, S> {
138 fn as_ref(&self) -> &[u8] {
139 self.bytes
140 }
141}
142
143impl<'input, S: ?Sized> Read<'input> for View<'input, S> {
144 fn as_slice(&self) -> &'input [u8] {
145 self.bytes
146 }
147
148 fn try_split<const N: usize>(mut self) -> Result<(&'input [u8; N], Self), consume::Error> {
149 let (head, tail) = Read::try_split(self.bytes)?;
150 self.bytes = tail;
151 Ok((head, self))
152 }
153}
154
155pub trait Residency {
158 fn resident(&self) -> usize;
159}
160
161impl<L> Residency for pool::Span<owners::Plain<L>, pool::Owned, pool::Frozen> {
162 fn resident(&self) -> usize {
163 self.capacity().get() as usize
164 }
165}
166
167impl<L> Residency for pool::Cursor<L> {
168 fn resident(&self) -> usize {
169 self.len() + self.spare_len()
170 }
171}
172
173impl Residency for Vec<u8> {
174 fn resident(&self) -> usize {
175 self.capacity()
176 }
177}
178
179impl<const CAP: usize, L> Residency for storage::inline::Bytes<CAP, L> {
180 fn resident(&self) -> usize {
181 CAP
182 }
183}
184
185impl Residency for &[u8] {
186 fn resident(&self) -> usize {
188 0
189 }
190}
191
192pub const BLOCK_CAPACITY: u32 = 64 * 1024;
193
194fn is_within(range: &ops::Range<usize>, len: usize) -> bool {
195 range.start <= range.end && range.end <= len
196}
197
198pub trait Read<'input>: Sized {
200 fn as_slice(&self) -> &'input [u8];
201 fn try_split<const N: usize>(self) -> Result<(&'input [u8; N], Self), consume::Error>;
202}
203
204impl<'input> Read<'input> for convert::Infallible {
205 fn as_slice(&self) -> &'input [u8] {
206 match *self {}
207 }
208
209 fn try_split<const N: usize>(self) -> Result<(&'input [u8; N], Self), consume::Error> {
210 match self {}
211 }
212}
213
214impl<'input> Read<'input> for &'input [u8] {
215 fn as_slice(&self) -> &'input [u8] {
216 self
217 }
218
219 fn try_split<const N: usize>(self) -> Result<(&'input [u8; N], Self), consume::Error> {
220 self.split_first_chunk::<N>().ok_or_else(|| {
221 consume::Error::new(
222 num::NonZero::<usize>::MIN.saturating_add(N.saturating_sub(1)),
223 self.len(),
224 )
225 })
226 }
227}
228
229pub trait Source: Unpin {
230 type View<'input>: Read<'input>
231 where
232 Self: 'input;
233
234 fn remaining(&self) -> usize;
235
236 fn is_empty(&self) -> bool {
237 self.remaining() == 0
238 }
239}
240
241pub trait Cursor: Source + AsRef<[u8]> {
242 fn try_get<'input>(
244 &'input self,
245 range: ops::Range<usize>,
246 ) -> Result<Self::View<'input>, range::Error>;
247}
248
249impl Source for [u8] {
250 type View<'input> = &'input [u8];
251
252 fn remaining(&self) -> usize {
253 self.len()
254 }
255}
256
257impl Cursor for [u8] {
258 #[inline]
259 fn try_get<'input>(
260 &'input self,
261 range: ops::Range<usize>,
262 ) -> Result<Self::View<'input>, range::Error> {
263 self.get(range.clone())
264 .ok_or_else(|| range::Error::new(range, self.len()))
265 }
266}
267
268pub trait Complete: Cursor {
269 fn view(&self) -> Self::View<'_>;
270}
271
272impl<O: Unpin> Source for storage::Shared<O> {
273 type View<'input>
274 = View<'input, Self>
275 where
276 Self: 'input;
277 fn remaining(&self) -> usize {
278 self.len()
279 }
280}
281impl<O: Unpin> Cursor for storage::Shared<O> {
282 fn try_get<'input>(
283 &'input self,
284 range: ops::Range<usize>,
285 ) -> Result<Self::View<'input>, range::Error> {
286 self.view().try_get(range)
287 }
288}
289impl<O: Unpin> Complete for storage::Shared<O> {
290 fn view(&self) -> Self::View<'_> {
291 View::new(self)
292 }
293}
294
295impl<'d> View<'_, storage::Shared<Option<provided::Account<'d>>>> {
296 pub fn try_retain(self) -> Result<storage::Shared<Option<provided::Account<'d>>>, rc::Error> {
298 if self.is_empty() {
299 return Ok(storage::Shared::<Option<provided::Account<'d>>>::new());
300 }
301 self.try_clone()
302 }
303}
304const _: () = {
305 assert!(
306 size_of::<storage::Shared<Option<provided::Account<'static>>>>() == 3 * size_of::<usize>()
307 );
308 assert!(
309 size_of::<Option<storage::Shared<Option<provided::Account<'static>>>>>()
310 == 3 * size_of::<usize>()
311 );
312};