1use http::header::HeaderName;
4use std::{collections::VecDeque, fmt, ops::Deref, rc::Rc, str::Utf8Error};
5
6use crate::{Roll, RollStr};
7
8#[derive(Clone)]
11pub enum Piece {
12 Full {
13 core: PieceCore,
14 },
15 Slice {
16 core: PieceCore,
17 start: usize,
18 len: usize,
19 },
20}
21
22impl Piece {
23 pub fn empty() -> Self {
25 Self::Full {
26 core: PieceCore::Static(&[]),
27 }
28 }
29}
30
31#[derive(Clone)]
32pub enum PieceCore {
33 Static(&'static [u8]),
34 Vec(Rc<Vec<u8>>),
35 Roll(Roll),
36 HeaderName(HeaderName),
37}
38
39impl<T> From<T> for Piece
40where
41 T: Into<PieceCore>,
42{
43 #[inline(always)]
44 fn from(t: T) -> Self {
45 Piece::Full { core: t.into() }
46 }
47}
48
49impl From<&'static [u8]> for PieceCore {
50 #[inline(always)]
51 fn from(slice: &'static [u8]) -> Self {
52 PieceCore::Static(slice)
53 }
54}
55
56impl From<&'static str> for PieceCore {
57 #[inline(always)]
58 fn from(slice: &'static str) -> Self {
59 PieceCore::Static(slice.as_bytes())
60 }
61}
62
63impl From<Vec<u8>> for PieceCore {
64 #[inline(always)]
65 fn from(vec: Vec<u8>) -> Self {
66 PieceCore::Vec(Rc::new(vec))
67 }
68}
69
70impl From<Roll> for PieceCore {
71 #[inline(always)]
72 fn from(roll: Roll) -> Self {
73 PieceCore::Roll(roll)
74 }
75}
76
77impl From<()> for PieceCore {
78 #[inline(always)]
79 fn from(_empty: ()) -> Self {
80 PieceCore::Static(&[])
81 }
82}
83
84impl From<PieceStr> for Piece {
85 fn from(s: PieceStr) -> Self {
86 s.piece
87 }
88}
89
90impl From<HeaderName> for PieceCore {
91 #[inline(always)]
92 fn from(name: HeaderName) -> Self {
93 PieceCore::HeaderName(name)
94 }
95}
96
97impl Deref for PieceCore {
98 type Target = [u8];
99
100 fn deref(&self) -> &Self::Target {
101 self.as_ref()
102 }
103}
104
105impl Deref for Piece {
106 type Target = [u8];
107
108 fn deref(&self) -> &Self::Target {
109 self.as_ref()
110 }
111}
112
113impl AsRef<[u8]> for PieceCore {
114 fn as_ref(&self) -> &[u8] {
115 match self {
116 PieceCore::Static(slice) => slice,
117 PieceCore::Vec(vec) => vec.as_ref(),
118 PieceCore::Roll(roll) => roll.as_ref(),
119 PieceCore::HeaderName(name) => name.as_str().as_bytes(),
120 }
121 }
122}
123
124impl Piece {
125 fn core(&self) -> &PieceCore {
126 match self {
127 Piece::Full { core } => core,
128 Piece::Slice { core, .. } => core,
129 }
130 }
131
132 pub fn split_at(self, middle: usize) -> (Self, Self) {
136 let len = self.len();
137 assert!(middle <= len);
138
139 match self {
140 Piece::Full { core } => (
141 Self::Slice {
142 core: core.clone(),
143 start: 0,
144 len: middle,
145 },
146 Self::Slice {
147 core,
148 start: middle,
149 len: len - middle,
150 },
151 ),
152 Piece::Slice { core, start, len } => (
153 Self::Slice {
154 core: core.clone(),
155 start,
156 len: middle,
157 },
158 Self::Slice {
159 core,
160 start: start + middle,
161 len: len - middle,
162 },
163 ),
164 }
165 }
166}
167
168impl AsRef<[u8]> for Piece {
169 fn as_ref(&self) -> &[u8] {
170 let ptr = self.core().as_ref();
171 if let Piece::Slice { start, len, .. } = self {
172 &ptr[*start..][..*len]
173 } else {
174 ptr
175 }
176 }
177}
178
179impl Piece {
180 pub fn to_str(self) -> Result<PieceStr, Utf8Error> {
182 _ = std::str::from_utf8(&self[..])?;
183 Ok(PieceStr { piece: self })
184 }
185
186 pub unsafe fn to_string_unchecked(self) -> PieceStr {
191 PieceStr { piece: self }
192 }
193}
194
195impl Piece {
196 #[inline(always)]
197 pub fn len(&self) -> usize {
198 self.as_ref().len()
199 }
200
201 #[inline(always)]
202 pub fn is_empty(&self) -> bool {
203 self.len() == 0
204 }
205}
206
207#[derive(Default)]
209pub struct PieceList {
210 pub(crate) pieces: VecDeque<Piece>,
216}
217
218impl PieceList {
219 pub fn single(piece: impl Into<Piece>) -> Self {
221 Self {
222 pieces: [piece.into()].into(),
223 }
224 }
225
226 pub fn push_back(&mut self, chunk: impl Into<Piece>) {
228 let chunk = chunk.into();
229 if !chunk.is_empty() {
230 self.pieces.push_back(chunk);
231 }
232 }
233
234 pub fn push_front(&mut self, chunk: impl Into<Piece>) {
236 let chunk = chunk.into();
237 if !chunk.is_empty() {
238 self.pieces.push_front(chunk);
239 }
240 }
241
242 pub fn followed_by(mut self, chunk: impl Into<Piece>) -> Self {
244 self.push_back(chunk);
245 self
246 }
247
248 pub fn preceded_by(mut self, chunk: impl Into<Piece>) -> Self {
250 self.push_front(chunk);
251 self
252 }
253
254 pub fn len(&self) -> usize {
256 self.pieces.iter().map(|c| c.len()).sum()
257 }
258
259 pub fn num_pieces(&self) -> usize {
260 self.pieces.len()
261 }
262
263 pub fn is_empty(&self) -> bool {
264 self.pieces.is_empty() || self.len() == 0
265 }
266
267 pub fn clear(&mut self) {
268 self.pieces.clear();
269 }
270
271 pub fn into_vec_deque(self) -> VecDeque<Piece> {
272 self.pieces
273 }
274}
275
276impl From<VecDeque<Piece>> for PieceList {
277 fn from(pieces: VecDeque<Piece>) -> Self {
278 Self { pieces }
279 }
280}
281impl From<PieceList> for VecDeque<Piece> {
282 fn from(list: PieceList) -> Self {
283 list.pieces
284 }
285}
286
287#[derive(Clone)]
290pub struct PieceStr {
291 piece: Piece,
292}
293
294impl fmt::Debug for PieceStr {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
296 fmt::Debug::fmt(&self[..], f)
297 }
298}
299
300impl fmt::Display for PieceStr {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
302 f.pad(self)
303 }
304}
305
306impl Deref for PieceStr {
307 type Target = str;
308
309 fn deref(&self) -> &Self::Target {
310 unsafe { std::str::from_utf8_unchecked(&self.piece) }
311 }
312}
313
314impl AsRef<str> for PieceStr {
315 fn as_ref(&self) -> &str {
316 self
317 }
318}
319
320impl PieceStr {
321 pub fn as_bytes(&self) -> &[u8] {
323 self.piece.as_ref()
324 }
325
326 pub fn into_inner(self) -> Piece {
328 self.piece
329 }
330}
331
332impl From<&'static str> for PieceStr {
333 fn from(s: &'static str) -> Self {
334 PieceStr {
335 piece: PieceCore::Static(s.as_bytes()).into(),
336 }
337 }
338}
339
340impl From<String> for PieceStr {
341 fn from(s: String) -> Self {
342 PieceStr {
343 piece: PieceCore::Vec(Rc::new(s.into_bytes())).into(),
344 }
345 }
346}
347
348impl From<RollStr> for PieceStr {
349 fn from(s: RollStr) -> Self {
350 PieceStr {
351 piece: PieceCore::Roll(s.into_inner()).into(),
352 }
353 }
354}
355
356#[cfg(test)]
357mod tests {
358 use crate::{Piece, PieceCore};
359
360 #[test]
361 fn test_slice() {
362 let piece: Piece = PieceCore::Static("französisch".as_bytes()).into();
365 let (first_name, last_name) = piece.split_at(5);
367 assert_eq!(&first_name[..], "franz".as_bytes());
368 assert_eq!(&last_name[..], "ösisch".as_bytes());
369
370 let piece: Piece = PieceCore::Static("französisch".as_bytes()).into();
372 let (first_name, last_name) = piece.split_at(0);
373 assert_eq!(&first_name[..], "".as_bytes());
374 assert_eq!(&last_name[..], "französisch".as_bytes());
375
376 let piece: Piece = PieceCore::Static("französisch".as_bytes()).into();
378 let (first_name, last_name) = piece.split_at(12);
379 assert_eq!(&first_name[..], "französisch".as_bytes());
380 assert_eq!(&last_name[..], "".as_bytes());
381
382 let piece: Piece = PieceCore::Static(b"").into();
384 let (first_name, last_name) = piece.split_at(0);
385 assert_eq!(&first_name[..], "".as_bytes());
386 assert_eq!(&last_name[..], "".as_bytes());
387 }
388}