1use std::{iter::FusedIterator, ops::ControlFlow};
2
3use o3::buffer::{
4 bytes::scope,
5 hold::ranges,
6 segments, storage,
7 write::{Sink as _, consume},
8};
9
10use crate::{
11 owner::{handoff, handoff::stage},
12 payload::{
13 owned::{self, Segments},
14 response,
15 response::Body as _,
16 },
17};
18
19mod error;
20pub mod iter;
21mod retained;
22mod view;
23
24pub use error::Error;
25#[doc(hidden)]
26pub use retained::Retained;
27pub use view::View;
28
29pub trait Source<'d> {
32 type Body<'a>: Into<Ref<'a, 'd>>
33 where
34 Self: 'a,
35 'd: 'a;
36
37 fn try_project<V, T>(
38 &mut self,
39 value: V,
40 project: impl for<'a> FnOnce(V, View<'a, 'd>) -> T,
41 ) -> Result<T, (V, Error)>;
42
43 fn body<'a>(&'a self) -> Self::Body<'a>
44 where
45 'd: 'a;
46}
47
48#[derive(Clone, Copy, Debug)]
49enum RefStorage<'req, 'd> {
50 Discarded,
51 Empty(&'req [u8]),
52 Slice(&'req [u8]),
54 Retained(Retained<'req, 'd>),
55 Ranges(&'req ranges::Set<'req, 'req, [u8]>),
56}
57
58#[derive(Clone, Copy, Debug)]
60pub struct Ref<'req, 'd> {
61 storage: RefStorage<'req, 'd>,
62 len: usize,
63}
64
65impl<'req, 'd> Ref<'req, 'd> {
66 pub const fn from_slice(bytes: &'req [u8]) -> Self {
68 let storage = if bytes.is_empty() {
69 RefStorage::Empty(bytes)
70 } else {
71 RefStorage::Slice(bytes)
72 };
73 Self {
74 storage,
75 len: bytes.len(),
76 }
77 }
78
79 #[doc(hidden)]
80 pub const fn discarded(len: usize) -> Self {
81 Self {
82 storage: RefStorage::Discarded,
83 len,
84 }
85 }
86
87 #[doc(hidden)]
88 pub const fn from_ranges(ranges: &'req ranges::Set<'req, 'req, [u8]>) -> Self {
89 Self {
90 storage: RefStorage::Ranges(ranges),
91 len: ranges.len(),
92 }
93 }
94
95 pub const fn len(&self) -> usize {
96 self.len
97 }
98
99 pub const fn is_empty(&self) -> bool {
100 self.len == 0
101 }
102
103 pub fn count(&self) -> segments::Count {
104 match self.storage {
105 RefStorage::Discarded | RefStorage::Empty(_) => segments::Count::EMPTY,
106 RefStorage::Slice(_) => segments::Count::ONE,
107 RefStorage::Retained(body) => body.count(),
108 RefStorage::Ranges(ranges) => ranges.count(),
109 }
110 }
111
112 pub fn segment(&self, index: usize) -> Option<&'req [u8]> {
113 match self.storage {
114 RefStorage::Discarded | RefStorage::Empty(_) => None,
115 RefStorage::Slice(bytes) => (index == 0).then_some(bytes),
116 RefStorage::Retained(body) => body.segment(index),
117 RefStorage::Ranges(ranges) => ranges.get(index).map(|view| view.as_slice()),
118 }
119 }
120
121 pub fn segments(self) -> iter::Slices<'req, 'd> {
122 iter::Slices::new(self)
123 }
124
125 pub fn as_slice(&self) -> Option<&'req [u8]> {
126 match self.storage {
127 RefStorage::Discarded => None,
128 RefStorage::Empty(bytes) => Some(bytes),
129 RefStorage::Slice(bytes) => Some(bytes),
130 RefStorage::Retained(body) => body.as_slice(),
131 RefStorage::Ranges(ranges) => ranges.contiguous(),
132 }
133 }
134
135 pub fn try_copy(self) -> Result<storage::Shared, owned::Error> {
137 if let RefStorage::Discarded = self.storage {
138 return Err(owned::Error::Discarded);
139 }
140 storage::Exact::try_build(self.len(), |out| {
141 for part in self.segments() {
142 out.write_slice(part)?;
143 }
144 Ok::<(), consume::Error>(())
145 })
146 .map(storage::Exact::into_shared)
147 .map_err(owned::Error::Build)
148 }
149
150 pub(crate) const fn try_retained(self) -> Result<Retained<'req, 'd>, Self> {
151 match self.storage {
152 RefStorage::Retained(body) => Ok(body),
153 _ => Err(self),
154 }
155 }
156}
157
158impl<'src, 'd> response::Body<'d> for Ref<'src, 'd> {
159 const INLINE: bool = true;
160
161 fn len(&self) -> usize {
162 self.len
163 }
164
165 fn as_slice(&self) -> Option<&[u8]> {
166 Self::as_slice(self)
167 }
168
169 fn segments(&self) -> impl ExactSizeIterator<Item = &[u8]> + FusedIterator {
170 iter::Slices::new(*self)
171 }
172
173 fn try_resolve<'req, H: scope::Source, O: stage::Body<'req, 'd>>(
174 self,
175 slot: &handoff::Slot<'req, 'd, H, O>,
176 ) -> Result<handoff::Plan<'req, 'd, H::Selection, O>, owned::Error> {
177 let origin = slot.origin();
178 if !self.is_empty() {
179 if let RefStorage::Retained(view) = self.storage {
180 return handoff::Plan::try_retain(origin, view);
181 }
182 return handoff::Plan::try_view(origin, self);
183 }
184 Ok(handoff::Plan::new(origin.clear()))
185 }
186
187 fn try_resolve_into<
188 'req,
189 H: scope::Source,
190 O: stage::Body<'req, 'd>,
191 L: std::borrow::BorrowMut<usize>,
192 >(
193 self,
194 slot: &handoff::Slot<'req, 'd, H, O>,
195 out: &mut o3::buffer::write::Slice<'_, L>,
196 ) -> Result<ControlFlow<usize, handoff::Plan<'req, 'd, H::Selection, O>>, owned::Error> {
197 if matches!(self.storage, RefStorage::Slice(_) | RefStorage::Ranges(_))
198 && let Some(bytes) = self.as_slice()
199 && let Some(written) = handoff::copy::into(out, bytes)
200 {
201 return Ok(ControlFlow::Break(written));
202 }
203 self.try_resolve(slot).map(ControlFlow::Continue)
204 }
205}
206
207impl<'d> Source<'d> for &[u8] {
208 type Body<'a>
209 = Ref<'a, 'd>
210 where
211 Self: 'a,
212 'd: 'a;
213
214 fn try_project<V, T>(
215 &mut self,
216 value: V,
217 project: impl for<'a> FnOnce(V, View<'a, 'd>) -> T,
218 ) -> Result<T, (V, Error)> {
219 Ok(project(value, View::Slice(self)))
220 }
221
222 fn body<'a>(&'a self) -> Self::Body<'a>
223 where
224 'd: 'a,
225 {
226 Ref::from_slice(self)
227 }
228}
229
230impl<'req, 'd> Source<'d> for Ref<'req, 'd> {
231 type Body<'a>
232 = Ref<'a, 'd>
233 where
234 Self: 'a,
235 'd: 'a;
236
237 fn try_project<V, T>(
238 &mut self,
239 value: V,
240 project: impl for<'a> FnOnce(V, View<'a, 'd>) -> T,
241 ) -> Result<T, (V, Error)> {
242 let view = match self.storage {
243 RefStorage::Retained(owner) => owner.contiguous(),
244 _ => self.as_slice().map(View::Slice),
245 };
246 match view {
247 Some(view) => Ok(project(value, view)),
248 None => Err((
249 value,
250 Error::Borrowed {
251 len: self.len(),
252 count: self.count(),
253 },
254 )),
255 }
256 }
257
258 fn body<'a>(&'a self) -> Self::Body<'a>
259 where
260 'd: 'a,
261 {
262 *self
263 }
264}
265
266const _: () = {
267 assert!(core::mem::size_of::<Ref<'static, 'static>>() == 4 * core::mem::size_of::<usize>());
268};
269
270impl<'req, 'd> From<&'req Segments<'d>> for Ref<'req, 'd> {
271 fn from(body: &'req Segments<'d>) -> Self {
272 Self {
273 storage: RefStorage::Retained(Retained::Segments(body)),
274 len: body.len(),
275 }
276 }
277}