Skip to main content

sark_core/http/response/
body.rs

1use o3::buffer::{Borrowed, Bytes, Retained, Shared};
2
3use super::TextBody;
4
5#[derive(Clone)]
6pub enum BodyInner<'req> {
7    Owned(Vec<u8>),
8    Shared(Shared),
9    Borrowed(Bytes<Borrowed<'req>>),
10    Retained(Bytes<Retained>),
11    StaticSlice(&'static [u8]),
12}
13
14pub type Body = BodyInner<'static>;
15
16impl<'req> std::fmt::Debug for BodyInner<'req> {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        match self {
19            Self::Owned(buf) => f
20                .debug_struct("Body::Owned")
21                .field("len", &buf.len())
22                .finish(),
23            Self::Shared(buf) => f
24                .debug_struct("Body::Shared")
25                .field("len", &buf.len())
26                .finish(),
27            Self::Borrowed(buf) => f
28                .debug_struct("Body::Borrowed")
29                .field("len", &buf.len())
30                .finish(),
31            Self::Retained(buf) => f
32                .debug_struct("Body::Retained")
33                .field("len", &buf.len())
34                .finish(),
35            Self::StaticSlice(buf) => f
36                .debug_struct("Body::StaticSlice")
37                .field("len", &buf.len())
38                .finish(),
39        }
40    }
41}
42
43impl<'req> BodyInner<'req> {
44    pub(crate) fn empty() -> Self {
45        Self::Owned(Vec::new())
46    }
47
48    pub(crate) fn len(&self) -> usize {
49        match self {
50            Self::Owned(buf) => buf.len(),
51            Self::Shared(buf) => buf.len(),
52            Self::Borrowed(buf) => buf.len(),
53            Self::Retained(buf) => buf.len(),
54            Self::StaticSlice(buf) => buf.len(),
55        }
56    }
57
58    pub(crate) fn as_bytes(&self) -> &[u8] {
59        match self {
60            Self::Owned(buf) => buf.as_ref(),
61            Self::Shared(buf) => buf.as_ref(),
62            Self::Borrowed(buf) => buf.as_slice(),
63            Self::Retained(buf) => buf.as_slice(),
64            Self::StaticSlice(buf) => buf,
65        }
66    }
67
68    pub(crate) fn is_shared(&self) -> bool {
69        matches!(
70            self,
71            Self::Shared(_) | Self::Borrowed(_) | Self::Retained(_) | Self::StaticSlice(_)
72        )
73    }
74
75    pub(crate) fn into_bytes(self) -> Shared {
76        match self {
77            Self::Owned(buf) => Shared::from(buf),
78            Self::Shared(buf) => buf,
79            Self::Borrowed(buf) => Shared::copy_from_slice(buf.as_slice()),
80            Self::Retained(buf) => buf.into_shared(),
81            Self::StaticSlice(buf) => Shared::from_static(buf),
82        }
83    }
84
85    pub(crate) fn into_owned(self) -> Vec<u8> {
86        match self {
87            Self::Owned(buf) => buf,
88            Self::Shared(buf) => buf.as_ref().to_vec(),
89            Self::Borrowed(buf) => buf.as_slice().to_vec(),
90            Self::Retained(buf) => buf.as_slice().to_vec(),
91            Self::StaticSlice(buf) => buf.to_vec(),
92        }
93    }
94
95    pub(super) fn into_static(self) -> Body {
96        match self {
97            Self::Owned(buf) => BodyInner::Owned(buf),
98            Self::Shared(buf) => BodyInner::Shared(buf),
99            Self::Borrowed(buf) => BodyInner::Shared(Shared::copy_from_slice(buf.as_slice())),
100            Self::Retained(buf) => BodyInner::Retained(buf),
101            Self::StaticSlice(buf) => BodyInner::StaticSlice(buf),
102        }
103    }
104
105    pub(crate) fn as_owned_mut(&mut self) -> &mut Vec<u8> {
106        if matches!(
107            self,
108            Self::Shared(_) | Self::Borrowed(_) | Self::Retained(_) | Self::StaticSlice(_)
109        ) {
110            let old = std::mem::replace(self, Self::empty());
111            *self = Self::Owned(old.into_owned());
112        }
113        match self {
114            Self::Owned(buf) => buf,
115            _ => unreachable!("response body must be owned after conversion"),
116        }
117    }
118}
119
120pub trait IntoBody<'req>: sealed::SealedBody {
121    fn into_response_body(self) -> BodyInner<'req>;
122}
123
124impl<'req> IntoBody<'req> for BodyInner<'req> {
125    fn into_response_body(self) -> Self {
126        self
127    }
128}
129
130impl<'req> IntoBody<'req> for o3::buffer::Owned {
131    fn into_response_body(self) -> BodyInner<'req> {
132        BodyInner::Shared(self.freeze())
133    }
134}
135
136impl<'req> IntoBody<'req> for Shared {
137    fn into_response_body(self) -> BodyInner<'req> {
138        BodyInner::Shared(self)
139    }
140}
141
142impl<'req> IntoBody<'req> for Bytes<Borrowed<'req>> {
143    fn into_response_body(self) -> BodyInner<'req> {
144        BodyInner::Borrowed(self)
145    }
146}
147
148impl<'req> IntoBody<'req> for Bytes<Retained> {
149    fn into_response_body(self) -> BodyInner<'req> {
150        BodyInner::Retained(self)
151    }
152}
153
154impl<'req> IntoBody<'req> for TextBody {
155    fn into_response_body(self) -> BodyInner<'req> {
156        BodyInner::Shared(self.into_bytes())
157    }
158}
159
160impl<'req> IntoBody<'req> for Vec<u8> {
161    fn into_response_body(self) -> BodyInner<'req> {
162        BodyInner::Owned(self)
163    }
164}
165
166impl<'req> IntoBody<'req> for String {
167    fn into_response_body(self) -> BodyInner<'req> {
168        BodyInner::Owned(self.into_bytes())
169    }
170}
171
172impl<'req> IntoBody<'req> for &[u8] {
173    fn into_response_body(self) -> BodyInner<'req> {
174        BodyInner::Owned(self.to_vec())
175    }
176}
177
178impl<'req> IntoBody<'req> for &str {
179    fn into_response_body(self) -> BodyInner<'req> {
180        BodyInner::Owned(self.as_bytes().to_vec())
181    }
182}
183
184mod sealed {
185    use super::super::TextBody;
186    use super::BodyInner;
187
188    pub trait SealedBody {}
189
190    impl<'req> SealedBody for BodyInner<'req> {}
191    impl SealedBody for TextBody {}
192    impl SealedBody for o3::buffer::Owned {}
193    impl SealedBody for o3::buffer::Shared {}
194    impl SealedBody for o3::buffer::Bytes<o3::buffer::Borrowed<'_>> {}
195    impl SealedBody for o3::buffer::Bytes<o3::buffer::Retained> {}
196    impl SealedBody for Vec<u8> {}
197    impl SealedBody for String {}
198    impl SealedBody for &[u8] {}
199    impl SealedBody for &str {}
200}