1use std::hash::Hash;
14use std::{borrow::Cow, fmt};
15
16use crate::{Helper, WebError, WebResult};
17use algorithm::buf::{Bt, BtMut};
18
19#[derive(Clone, Debug)]
20pub enum HeaderValue {
21 Stand(&'static str),
22 Value(Vec<u8>),
23}
24
25impl HeaderValue {
26 pub fn from_static(s: &'static str) -> HeaderValue {
27 HeaderValue::Stand(s)
28 }
29
30 pub fn from_bytes(b: &[u8]) -> HeaderValue {
31 HeaderValue::Value(b.to_vec())
32 }
33
34 pub fn from_cow(b: Cow<[u8]>) -> HeaderValue {
35 HeaderValue::Value(Vec::from(b.to_owned()))
36 }
37
38 pub fn bytes_len(&self) -> usize {
39 match self {
40 Self::Stand(s) => s.as_bytes().len(),
41 Self::Value(s) => s.len(),
42 }
43 }
44
45 pub fn as_bytes(&self) -> &[u8] {
46 match self {
47 Self::Stand(s) => &s.as_bytes(),
48 Self::Value(s) => &s,
49 }
50 }
51
52 pub fn as_string(&self) -> Option<String> {
53 match self {
54 Self::Stand(s) => Some(s.to_string()),
55 Self::Value(s) => String::from_utf8(s.clone()).map_or(None, |s| Some(s)),
56 }
57 }
58
59 pub fn push(&mut self, value: HeaderValue) {
60 match self {
61 Self::Stand(s) => *self = Self::Value(s.as_bytes().to_vec()),
62 _ => {}
63 }
64 match self {
65 Self::Value(s) => {
66 s.push(b';');
67 s.append(&mut value.as_bytes().to_vec());
68 }
69 _ => unreachable!(),
70 }
71 }
72
73 pub fn encode<B: Bt + BtMut>(&self, buffer: &mut B) -> WebResult<usize> {
74 match self {
75 Self::Stand(name) => Ok(buffer.put_slice(name.as_bytes())),
76 Self::Value(vec) => Ok(buffer.put_slice(&**vec)),
77 }
78 }
79
80 pub fn contains(&self, bytes: &[u8]) -> bool {
81 Helper::contains_bytes(self.as_bytes(), bytes)
82 }
83}
84
85impl Hash for HeaderValue {
86 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
87 match self {
88 HeaderValue::Stand(stand) => {
89 (*stand.as_bytes()).hash(state);
90 }
91 HeaderValue::Value(val) => {
92 val.hash(state);
93 }
94 }
95 }
96}
97
98impl fmt::Display for HeaderValue {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 match &self {
101 Self::Stand(value) => f.write_str(value),
102 Self::Value(value) => f.write_str(&String::from_utf8_lossy(value)),
103 }
104 }
105}
106
107impl TryInto<usize> for &HeaderValue {
108 type Error = WebError;
109
110 fn try_into(self) -> Result<usize, WebError> {
111 match self {
112 HeaderValue::Stand(s) => s.parse().map_err(WebError::from),
113 HeaderValue::Value(v) => {
114 let mut result = 0usize;
115 for b in v {
116 if !Helper::is_digit(*b) {
117 return Err(WebError::IntoError);
118 }
119 match result.overflowing_mul(10) {
120 (u, false) => {
121 result = u + (b - Helper::DIGIT_0) as usize;
122 }
123 (_u, true) => return Err(WebError::IntoError),
124 }
125 }
126 Ok(result)
127 }
128 }
129 }
130}
131
132impl TryInto<isize> for &HeaderValue {
133 type Error = WebError;
134
135 fn try_into(self) -> Result<isize, WebError> {
136 match self {
137 HeaderValue::Stand(s) => s.parse().map_err(WebError::from),
138 HeaderValue::Value(v) => {
139 let mut result = 0isize;
140 let mut is_neg = false;
141 for b in v {
142 if !Helper::is_digit(*b) {
143 if b == &b'-' && result == 0 {
144 is_neg = true;
145 continue;
146 }
147 return Err(WebError::IntoError);
148 }
149 match result.overflowing_mul(10) {
150 (u, false) => {
151 result = u + (b - Helper::DIGIT_0) as isize;
152 }
153 (_u, true) => return Err(WebError::IntoError),
154 }
155 }
156 if is_neg {
157 Ok(-result)
158 } else {
159 Ok(result)
160 }
161 }
162 }
163 }
164}
165
166impl TryInto<String> for &HeaderValue {
167 type Error = WebError;
168
169 fn try_into(self) -> Result<String, WebError> {
170 match self {
171 HeaderValue::Stand(s) => Ok(s.to_string()),
172 HeaderValue::Value(v) => Ok(String::from_utf8_lossy(v).to_string()),
173 }
174 }
175}
176
177impl TryFrom<&'static str> for HeaderValue {
178 type Error = WebError;
179
180 fn try_from(value: &'static str) -> Result<Self, Self::Error> {
181 Ok(HeaderValue::Stand(value))
182 }
183}
184
185impl TryFrom<String> for HeaderValue {
186 type Error = WebError;
187 fn try_from(value: String) -> Result<Self, Self::Error> {
188 Ok(HeaderValue::Value(value.into_bytes()))
189 }
190}
191
192impl TryFrom<usize> for HeaderValue {
193 type Error = WebError;
194 fn try_from(value: usize) -> Result<Self, Self::Error> {
195 Ok(HeaderValue::Value(format!("{}", value).into_bytes()))
196 }
197}
198
199impl TryFrom<isize> for HeaderValue {
200 type Error = WebError;
201 fn try_from(value: isize) -> Result<Self, Self::Error> {
202 Ok(HeaderValue::Value(format!("{}", value).into_bytes()))
203 }
204}
205
206impl Eq for HeaderValue {}
207
208impl PartialEq<HeaderValue> for HeaderValue {
209 fn eq(&self, other: &HeaderValue) -> bool {
210 match (self, other) {
211 (Self::Stand(l0), Self::Stand(r0)) => l0 == r0,
212 (Self::Value(l0), Self::Value(r0)) => l0 == r0,
213 (Self::Stand(l0), Self::Value(r0)) => l0.as_bytes() == r0,
214 (Self::Value(l0), Self::Stand(r0)) => l0 == r0.as_bytes(),
215 }
216 }
217}
218
219impl PartialEq<&str> for HeaderValue {
220 fn eq(&self, other: &&str) -> bool {
221 match self {
222 HeaderValue::Stand(s) => s == other,
223 HeaderValue::Value(s) => &s[..] == other.as_bytes(),
224 }
225 }
226}
227
228impl PartialEq<HeaderValue> for [u8] {
229 fn eq(&self, other: &HeaderValue) -> bool {
230 other == self
231 }
232}
233
234impl PartialEq<[u8]> for HeaderValue {
235 fn eq(&self, other: &[u8]) -> bool {
236 match self {
237 HeaderValue::Stand(s) => s.as_bytes() == other,
238 HeaderValue::Value(s) => &s[..] == other,
239 }
240 }
241}
242
243impl PartialEq<HeaderValue> for &str {
244 fn eq(&self, url: &HeaderValue) -> bool {
245 url == self
246 }
247}