form_net/multipart/
owned_head.rs1use alloc::vec::Vec;
5use core::fmt;
6use core::ops::Range;
7
8use crate::multipart::filename::{FileName, FileNameSource};
9use crate::multipart::parser::{Charset, PartHead, PartKind};
10
11#[derive(Clone, Default)]
31pub struct OwnedPartHead {
32 buf: Vec<u8>,
33 index: u32,
34 block: Range<usize>,
35 name: Range<usize>,
36 name_raw: Range<usize>,
37 kind: Option<PartKind>,
38 filename: Option<(Range<usize>, FileNameSource)>,
39 content_type: Option<Range<usize>>,
40 charset: Option<Charset>,
41}
42
43impl fmt::Debug for OwnedPartHead {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 fmt::Debug::fmt(&self.view(), f)
46 }
47}
48
49impl OwnedPartHead {
50 #[must_use]
52 pub fn new() -> OwnedPartHead {
53 OwnedPartHead::default()
54 }
55
56 #[must_use]
58 pub fn with_capacity(capacity: usize) -> OwnedPartHead {
59 let mut head = OwnedPartHead::default();
60 head.buf = Vec::with_capacity(capacity);
61 head
62 }
63
64 fn push(&mut self, bytes: &[u8]) -> Range<usize> {
65 let start = self.buf.len();
66 crate::wipe::append_wiping(&mut self.buf, bytes, bytes.len(), usize::MAX);
68 start..self.buf.len()
69 }
70
71 pub fn copy_from(&mut self, head: &PartHead<'_>) {
75 crate::wipe::wipe(&mut self.buf);
76 self.buf.clear();
77 let needed = [
78 head.block().len(),
79 head.name().len(),
80 head.name_raw().len(),
81 head.filename().map_or(0, |f| f.raw().len()),
82 head.content_type().map_or(0, |c| c.raw().len()),
83 ]
84 .iter()
85 .fold(0usize, |a, n| a.saturating_add(*n));
86 if needed > self.buf.capacity() {
87 let mut old = core::mem::replace(&mut self.buf, Vec::with_capacity(needed));
88 crate::wipe::wipe_vec(&mut old);
89 }
90 self.index = head.index();
91 self.block = self.push(head.block());
92 self.name = self.push(head.name().as_bytes());
93 self.name_raw = self.push(head.name_raw());
94 self.kind = Some(head.kind());
95 self.filename = head.filename().map(|f| (self.push(f.raw()), f.source()));
96 self.content_type = head.content_type().map(|c| self.push(c.raw()));
97 self.charset = Some(head.charset());
98 }
99
100 #[must_use]
102 pub fn view(&self) -> PartHead<'_> {
103 let get = |r: &Range<usize>| self.buf.get(r.clone()).unwrap_or(&[]);
104 PartHead::from_parts(
105 self.index,
106 get(&self.block),
107 core::str::from_utf8(get(&self.name)).unwrap_or(""),
108 get(&self.name_raw),
109 self.kind.unwrap_or(PartKind::Field),
110 self.filename
111 .as_ref()
112 .map(|(r, source)| FileName::new(get(r), *source)),
113 self.content_type.as_ref().map(get),
114 self.charset.unwrap_or(Charset::Unspecified),
115 )
116 }
117}
118
119impl Drop for OwnedPartHead {
120 fn drop(&mut self) {
121 crate::wipe::wipe_vec(&mut self.buf);
122 }
123}