sark_core/http/response/
body.rs1use 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}