sark_core/http/response/
body.rs1use o3::buffer::{Owned, Shared};
2
3use super::TextBody;
4use crate::http::LocalFrameBytesRef;
5
6#[derive(Clone)]
7pub enum BodyInner<'req> {
8 Owned(Owned),
9 Shared(Shared),
10 Local(LocalFrameBytesRef<'req>),
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::Local(buf) => f
28 .debug_struct("Body::Local")
29 .field("len", &buf.len())
30 .finish(),
31 Self::StaticSlice(buf) => f
32 .debug_struct("Body::StaticSlice")
33 .field("len", &buf.len())
34 .finish(),
35 }
36 }
37}
38
39impl<'req> BodyInner<'req> {
40 pub(crate) fn empty() -> Self {
41 Self::Owned(Owned::new())
42 }
43
44 pub(crate) fn len(&self) -> usize {
45 match self {
46 Self::Owned(buf) => buf.len(),
47 Self::Shared(buf) => buf.len(),
48 Self::Local(buf) => buf.len(),
49 Self::StaticSlice(buf) => buf.len(),
50 }
51 }
52
53 pub(crate) fn as_bytes(&self) -> &[u8] {
54 match self {
55 Self::Owned(buf) => buf.as_ref(),
56 Self::Shared(buf) => buf.as_ref(),
57 Self::Local(buf) => buf.as_bytes(),
58 Self::StaticSlice(buf) => buf,
59 }
60 }
61
62 pub(crate) fn is_shared(&self) -> bool {
63 matches!(
64 self,
65 Self::Shared(_) | Self::Local(_) | Self::StaticSlice(_)
66 )
67 }
68
69 pub(crate) fn into_bytes(self) -> Shared {
70 match self {
71 Self::Owned(buf) => buf.freeze(),
72 Self::Shared(buf) => buf,
73 Self::Local(buf) => buf.into_bytes(),
74 Self::StaticSlice(buf) => Shared::from_static(buf),
75 }
76 }
77
78 pub(crate) fn into_owned(self) -> Owned {
79 match self {
80 Self::Owned(buf) => buf,
81 Self::Shared(buf) => Owned::from(buf.as_ref()),
82 Self::Local(buf) => Owned::from(buf.as_bytes()),
83 Self::StaticSlice(buf) => Owned::from(buf),
84 }
85 }
86
87 pub(crate) fn as_owned_mut(&mut self) -> &mut Owned {
88 if matches!(
89 self,
90 Self::Shared(_) | Self::Local(_) | Self::StaticSlice(_)
91 ) {
92 let old = std::mem::replace(self, Self::empty());
93 *self = Self::Owned(old.into_owned());
94 }
95 match self {
96 Self::Owned(buf) => buf,
97 _ => unreachable!("response body must be owned after conversion"),
98 }
99 }
100}
101
102pub trait IntoBody<'req>: sealed::SealedBody {
103 fn into_response_body(self) -> BodyInner<'req>;
104}
105
106impl<'req> IntoBody<'req> for BodyInner<'req> {
107 fn into_response_body(self) -> Self {
108 self
109 }
110}
111
112impl<'req> IntoBody<'req> for Owned {
113 fn into_response_body(self) -> BodyInner<'req> {
114 BodyInner::Owned(self)
115 }
116}
117
118impl<'req> IntoBody<'req> for Shared {
119 fn into_response_body(self) -> BodyInner<'req> {
120 BodyInner::Shared(self)
121 }
122}
123
124impl<'req> IntoBody<'req> for LocalFrameBytesRef<'req> {
125 fn into_response_body(self) -> BodyInner<'req> {
126 BodyInner::Local(self)
127 }
128}
129
130impl<'req> IntoBody<'req> for TextBody {
131 fn into_response_body(self) -> BodyInner<'req> {
132 BodyInner::Shared(self.into_bytes())
133 }
134}
135
136impl<'req> IntoBody<'req> for Vec<u8> {
137 fn into_response_body(self) -> BodyInner<'req> {
138 BodyInner::Owned(Owned::from(self.as_slice()))
139 }
140}
141
142impl<'req> IntoBody<'req> for String {
143 fn into_response_body(self) -> BodyInner<'req> {
144 BodyInner::Owned(Owned::from(self.as_bytes()))
145 }
146}
147
148impl<'req> IntoBody<'req> for &[u8] {
149 fn into_response_body(self) -> BodyInner<'req> {
150 BodyInner::Owned(Owned::from(self))
151 }
152}
153
154impl<'req> IntoBody<'req> for &str {
155 fn into_response_body(self) -> BodyInner<'req> {
156 BodyInner::Owned(Owned::from(self.as_bytes()))
157 }
158}
159
160mod sealed {
161 use super::super::{LocalFrameBytesRef, TextBody};
162 use super::BodyInner;
163
164 pub trait SealedBody {}
165
166 impl<'req> SealedBody for BodyInner<'req> {}
167 impl SealedBody for TextBody {}
168 impl SealedBody for o3::buffer::Owned {}
169 impl SealedBody for o3::buffer::Shared {}
170 impl<'req> SealedBody for LocalFrameBytesRef<'req> {}
171 impl SealedBody for Vec<u8> {}
172 impl SealedBody for String {}
173 impl SealedBody for &[u8] {}
174 impl SealedBody for &str {}
175}