http_types_rs/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 { entries: HashSet::new() }
47 }
48
49 pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
51 let mut entries = HashSet::new();
52 let headers = match headers.as_ref().get(ALLOW) {
53 Some(headers) => headers,
54 None => return Ok(None),
55 };
56
57 for value in headers {
58 for part in value.as_str().trim().split(',') {
59 let method = Method::from_str(part.trim())?;
60 entries.insert(method);
61 }
62 }
63
64 Ok(Some(Self { entries }))
65 }
66
67 pub fn insert(&mut self, method: Method) {
69 self.entries.insert(method);
70 }
71
72 pub fn iter(&self) -> Iter<'_> {
74 Iter { inner: self.entries.iter() }
75 }
76
77 pub fn contains(&self, method: Method) -> bool {
79 self.entries.contains(&method)
80 }
81}
82
83impl Header for Allow {
84 fn header_name(&self) -> HeaderName {
85 ALLOW
86 }
87 fn header_value(&self) -> HeaderValue {
88 let mut output = String::new();
89 for (n, method) in self.entries.iter().enumerate() {
90 match n {
91 0 => write!(output, "{}", method).unwrap(),
92 _ => write!(output, ", {}", method).unwrap(),
93 };
94 }
95
96 unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
98 }
99}
100
101impl IntoIterator for Allow {
102 type Item = Method;
103 type IntoIter = IntoIter;
104
105 #[inline]
106 fn into_iter(self) -> Self::IntoIter {
107 IntoIter {
108 inner: self.entries.into_iter(),
109 }
110 }
111}
112
113impl<'a> IntoIterator for &'a Allow {
114 type Item = &'a Method;
115 type IntoIter = Iter<'a>;
116
117 #[inline]
118 fn into_iter(self) -> Self::IntoIter {
119 self.iter()
120 }
121}
122
123#[derive(Debug)]
125pub struct IntoIter {
126 inner: hash_set::IntoIter<Method>,
127}
128
129impl Iterator for IntoIter {
130 type Item = Method;
131
132 fn next(&mut self) -> Option<Self::Item> {
133 self.inner.next()
134 }
135
136 #[inline]
137 fn size_hint(&self) -> (usize, Option<usize>) {
138 self.inner.size_hint()
139 }
140}
141
142#[derive(Debug)]
144pub struct Iter<'a> {
145 inner: hash_set::Iter<'a, Method>,
146}
147
148impl<'a> Iterator for Iter<'a> {
149 type Item = &'a Method;
150
151 fn next(&mut self) -> Option<Self::Item> {
152 self.inner.next()
153 }
154
155 #[inline]
156 fn size_hint(&self) -> (usize, Option<usize>) {
157 self.inner.size_hint()
158 }
159}
160
161impl Debug for Allow {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 let mut list = f.debug_list();
164 for method in &self.entries {
165 list.entry(method);
166 }
167 list.finish()
168 }
169}
170
171#[cfg(test)]
172mod test {
173 use super::*;
174 use crate::headers::Headers;
175
176 #[test]
177 fn smoke() -> crate::Result<()> {
178 let mut allow = Allow::new();
179 allow.insert(Method::Put);
180 allow.insert(Method::Post);
181
182 let mut headers = Headers::new();
183 allow.apply_header(&mut headers);
184
185 let allow = Allow::from_headers(headers)?.unwrap();
186 assert!(allow.contains(Method::Put));
187 assert!(allow.contains(Method::Post));
188 Ok(())
189 }
190}