http_types/server/
allow.rs1use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, ALLOW};
4use crate::Method;
5
6use std::collections::{hash_set, HashSet};
7use std::fmt::{self, Debug, Write};
8use std::iter::Iterator;
9use std::option;
10use std::str::FromStr;
11
12pub struct Allow {
40 entries: HashSet<Method>,
41}
42
43impl Allow {
44 pub fn new() -> Self {
46 Self {
47 entries: HashSet::new(),
48 }
49 }
50
51 pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
53 let mut entries = HashSet::new();
54 let headers = match headers.as_ref().get(ALLOW) {
55 Some(headers) => headers,
56 None => return Ok(None),
57 };
58
59 for value in headers {
60 for part in value.as_str().trim().split(',') {
61 let method = Method::from_str(part.trim())?;
62 entries.insert(method);
63 }
64 }
65
66 Ok(Some(Self { entries }))
67 }
68
69 pub fn apply(&self, mut headers: impl AsMut<Headers>) {
71 headers.as_mut().insert(ALLOW, self.value());
72 }
73
74 pub fn name(&self) -> HeaderName {
76 ALLOW
77 }
78
79 pub fn value(&self) -> HeaderValue {
81 let mut output = String::new();
82 for (n, method) in self.entries.iter().enumerate() {
83 match n {
84 0 => write!(output, "{}", method).unwrap(),
85 _ => write!(output, ", {}", method).unwrap(),
86 };
87 }
88
89 unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
91 }
92
93 pub fn insert(&mut self, method: Method) {
95 self.entries.insert(method);
96 }
97
98 pub fn iter(&self) -> Iter<'_> {
100 Iter {
101 inner: self.entries.iter(),
102 }
103 }
104
105 pub fn contains(&self, method: Method) -> bool {
107 self.entries.contains(&method)
108 }
109}
110
111impl IntoIterator for Allow {
112 type Item = Method;
113 type IntoIter = IntoIter;
114
115 #[inline]
116 fn into_iter(self) -> Self::IntoIter {
117 IntoIter {
118 inner: self.entries.into_iter(),
119 }
120 }
121}
122
123impl<'a> IntoIterator for &'a Allow {
124 type Item = &'a Method;
125 type IntoIter = Iter<'a>;
126
127 #[inline]
128 fn into_iter(self) -> Self::IntoIter {
129 self.iter()
130 }
131}
132
133#[derive(Debug)]
135pub struct IntoIter {
136 inner: hash_set::IntoIter<Method>,
137}
138
139impl Iterator for IntoIter {
140 type Item = Method;
141
142 fn next(&mut self) -> Option<Self::Item> {
143 self.inner.next()
144 }
145
146 #[inline]
147 fn size_hint(&self) -> (usize, Option<usize>) {
148 self.inner.size_hint()
149 }
150}
151
152#[derive(Debug)]
154pub struct Iter<'a> {
155 inner: hash_set::Iter<'a, Method>,
156}
157
158impl<'a> Iterator for Iter<'a> {
159 type Item = &'a Method;
160
161 fn next(&mut self) -> Option<Self::Item> {
162 self.inner.next()
163 }
164
165 #[inline]
166 fn size_hint(&self) -> (usize, Option<usize>) {
167 self.inner.size_hint()
168 }
169}
170
171impl ToHeaderValues for Allow {
172 type Iter = option::IntoIter<HeaderValue>;
173 fn to_header_values(&self) -> crate::Result<Self::Iter> {
174 Ok(self.value().to_header_values().unwrap())
176 }
177}
178
179impl Debug for Allow {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 let mut list = f.debug_list();
182 for method in &self.entries {
183 list.entry(method);
184 }
185 list.finish()
186 }
187}
188
189#[cfg(test)]
190mod test {
191 use super::*;
192 use crate::headers::Headers;
193
194 #[test]
195 fn smoke() -> crate::Result<()> {
196 let mut allow = Allow::new();
197 allow.insert(Method::Put);
198 allow.insert(Method::Post);
199
200 let mut headers = Headers::new();
201 allow.apply(&mut headers);
202
203 let allow = Allow::from_headers(headers)?.unwrap();
204 assert!(allow.contains(Method::Put));
205 assert!(allow.contains(Method::Post));
206 Ok(())
207 }
208}