http_types_2/server/
allow.rs1use crate::headers::{Header, HeaderName, HeaderValue, Headers, ALLOW};
4use crate::Method;
5
6use std::collections::{hash_set, HashSet};
7use std::fmt::{self, Debug, Write};
8use std::iter::Iterator;
9
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 insert(&mut self, method: Method) {
71 self.entries.insert(method);
72 }
73
74 pub fn iter(&self) -> Iter<'_> {
76 Iter {
77 inner: self.entries.iter(),
78 }
79 }
80
81 pub fn contains(&self, method: Method) -> bool {
83 self.entries.contains(&method)
84 }
85}
86
87impl Header for Allow {
88 fn header_name(&self) -> HeaderName {
89 ALLOW
90 }
91 fn header_value(&self) -> HeaderValue {
92 let mut output = String::new();
93 for (n, method) in self.entries.iter().enumerate() {
94 match n {
95 0 => write!(output, "{method}").unwrap(),
96 _ => write!(output, ", {method}").unwrap(),
97 };
98 }
99
100 unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
102 }
103}
104
105impl IntoIterator for Allow {
106 type Item = Method;
107 type IntoIter = IntoIter;
108
109 #[inline]
110 fn into_iter(self) -> Self::IntoIter {
111 IntoIter {
112 inner: self.entries.into_iter(),
113 }
114 }
115}
116
117impl<'a> IntoIterator for &'a Allow {
118 type Item = &'a Method;
119 type IntoIter = Iter<'a>;
120
121 #[inline]
122 fn into_iter(self) -> Self::IntoIter {
123 self.iter()
124 }
125}
126
127#[derive(Debug)]
129pub struct IntoIter {
130 inner: hash_set::IntoIter<Method>,
131}
132
133impl Iterator for IntoIter {
134 type Item = Method;
135
136 fn next(&mut self) -> Option<Self::Item> {
137 self.inner.next()
138 }
139
140 #[inline]
141 fn size_hint(&self) -> (usize, Option<usize>) {
142 self.inner.size_hint()
143 }
144}
145
146#[derive(Debug)]
148pub struct Iter<'a> {
149 inner: hash_set::Iter<'a, Method>,
150}
151
152impl<'a> Iterator for Iter<'a> {
153 type Item = &'a Method;
154
155 fn next(&mut self) -> Option<Self::Item> {
156 self.inner.next()
157 }
158
159 #[inline]
160 fn size_hint(&self) -> (usize, Option<usize>) {
161 self.inner.size_hint()
162 }
163}
164
165impl Debug for Allow {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 let mut list = f.debug_list();
168 for method in &self.entries {
169 list.entry(method);
170 }
171 list.finish()
172 }
173}
174
175#[cfg(test)]
176mod test {
177 use super::*;
178 use crate::headers::Headers;
179
180 #[test]
181 fn smoke() -> crate::Result<()> {
182 let mut allow = Allow::new();
183 allow.insert(Method::Put);
184 allow.insert(Method::Post);
185
186 let mut headers = Headers::new();
187 allow.apply_header(&mut headers);
188
189 let allow = Allow::from_headers(headers)?.unwrap();
190 assert!(allow.contains(Method::Put));
191 assert!(allow.contains(Method::Post));
192 Ok(())
193 }
194}