Skip to main content

sark_core/http/response/
body.rs

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