rust_rcs_core/internet/
header.rs1use std::fmt;
16use std::io::Read;
17use std::slice::Iter;
18
19use crate::io::Serializable;
20
21pub struct Header {
22 name: Box<dyn AsRef<[u8]> + Send + Sync>,
23 value: Box<dyn AsRef<[u8]> + Send + Sync>,
24}
25
26impl Header {
27 pub fn new<N, V>(name: N, value: V) -> Header
28 where
29 N: AsRef<[u8]> + Send + Sync + 'static,
30 V: AsRef<[u8]> + Send + Sync + 'static,
31 {
32 Header {
33 name: Box::new(name),
34 value: Box::new(value),
35 }
36 }
37
38 pub fn get_name(&self) -> &[u8] {
39 self.name.as_ref().as_ref()
40 }
41
42 pub fn get_value(&self) -> &[u8] {
43 self.value.as_ref().as_ref()
44 }
45
46 pub fn reader(&self) -> HeaderReader {
47 HeaderReader {
48 header: self,
49 pos: 0,
50 }
51 }
52}
53
54impl Clone for Header {
55 fn clone(&self) -> Self {
56 Header {
57 name: Box::new(self.name.as_ref().as_ref().to_vec()),
58 value: Box::new(self.value.as_ref().as_ref().to_vec()),
59 }
60 }
61}
62
63impl fmt::Debug for Header {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 f.debug_struct("Header")
66 .field(
67 &String::from_utf8_lossy(self.name.as_ref().as_ref()),
68 &String::from_utf8_lossy(self.value.as_ref().as_ref()),
69 )
70 .finish()
71 }
72}
73
74pub struct HeaderReader<'a> {
75 header: &'a Header,
76 pos: usize,
77}
78
79impl<'a> Read for HeaderReader<'a> {
80 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
81 let name = self.header.name.as_ref().as_ref();
82 let value = self.header.value.as_ref().as_ref();
83 let mut i = 0;
84 while self.pos + i < name.len() && i < buf.len() {
85 buf[i] = name[self.pos + i];
86 i += 1;
87 }
88 while self.pos + i >= name.len() && self.pos + i < name.len() + 2 && i < buf.len() {
89 if self.pos + i == name.len() {
90 buf[i] = b':';
91 } else {
92 buf[i] = b' ';
93 }
94 i += 1;
95 }
96 while self.pos + i >= name.len() + 2
97 && self.pos + i < name.len() + 2 + value.len()
98 && i < buf.len()
99 {
100 buf[i] = value[self.pos + i - name.len() - 2];
101 i += 1;
102 }
103 while self.pos + i >= name.len() + 2 + value.len()
104 && self.pos + i < name.len() + 2 + value.len() + 2
105 && i < buf.len()
106 {
107 if self.pos + i == name.len() + 2 + value.len() {
108 buf[i] = b'\r';
109 } else {
110 buf[i] = b'\n';
111 }
112 i += 1;
113 }
114 self.pos += i;
115 Ok(i)
116 }
117}
118
119pub struct HeaderSearch<'a, 'b> {
120 iter: Iter<'a, Header>,
121 name: &'b [u8],
122 ignore_case: bool,
123}
124
125impl<'a, 'b> HeaderSearch<'a, 'b> {
126 pub fn new(headers: &'a [Header], name: &'b [u8], ignore_case: bool) -> HeaderSearch<'a, 'b> {
127 HeaderSearch {
128 iter: headers.iter(),
129 name,
130 ignore_case,
131 }
132 }
133}
134
135impl<'a, 'b> Iterator for HeaderSearch<'a, '_> {
136 type Item = &'a Header;
137 fn next(&mut self) -> Option<&'a Header> {
138 while let Some(h) = self.iter.next() {
139 if self.ignore_case {
140 if h.name.as_ref().as_ref().eq_ignore_ascii_case(self.name) {
141 return Some(h);
142 }
143 } else {
144 if h.name.as_ref().as_ref().eq(self.name) {
145 return Some(h);
146 }
147 }
148 }
149
150 None
151 }
152}
153
154pub fn search<'a>(headers: &'a [Header], name: &[u8], ignore_case: bool) -> Option<&'a Header> {
155 HeaderSearch::new(headers, name, ignore_case).next()
156}
157
158impl Serializable for [Header] {
159 fn estimated_size(&self) -> usize {
171 let mut size = 0;
172 for header in self {
173 size += header.name.as_ref().as_ref().len();
174 size += 2;
175 size += header.value.as_ref().as_ref().len();
176 size += 2;
177 }
178 size
179 }
180}
181
182pub fn headers_get_readers<'a>(
183 headers: &'a [Header],
184 readers: &mut Vec<Box<dyn Read + Send + 'a>>,
185) {
186 for header in headers {
187 readers.push(Box::new(header.reader()));
188 }
189}