scraper_trail/
multi_value.rs1use std::{borrow::Cow, marker::PhantomData};
2
3#[derive(Copy, Clone, Debug, thiserror::Error)]
4pub enum Error {
5 #[error("Empty values")]
6 Empty,
7}
8
9#[derive(Clone, Debug, Eq, PartialEq, bounded_static_derive_more::ToStatic)]
15pub struct MultiValue<'a> {
16 pub first: Cow<'a, str>,
17 rest: Option<Vec<Cow<'a, str>>>,
18}
19
20impl<'a> MultiValue<'a> {
21 pub fn new<S: Into<Cow<'a, str>>>(value: S) -> Self {
22 Self {
23 first: value.into(),
24 rest: None,
25 }
26 }
27
28 pub fn push<S: Into<Cow<'a, str>>>(&mut self, value: S) {
29 match &mut self.rest {
30 None => {
31 self.rest = Some(vec![value.into()]);
32 }
33 Some(rest) => {
34 rest.push(value.into());
35 }
36 }
37 }
38
39 #[must_use]
40 pub fn iter(&'a self) -> Iter<'a> {
41 Iter {
42 first: Some(self.first.clone()),
43 rest: self.rest.as_ref().map(|rest| rest.iter()),
44 }
45 }
46}
47
48impl<'a> AsRef<Cow<'a, str>> for MultiValue<'a> {
49 fn as_ref(&self) -> &Cow<'a, str> {
50 &self.first
51 }
52}
53
54impl<'a, S: Into<Cow<'a, str>>> TryFrom<Vec<S>> for MultiValue<'a> {
55 type Error = Error;
56
57 fn try_from(mut value: Vec<S>) -> Result<Self, Self::Error> {
58 if value.is_empty() {
59 Err(Error::Empty)
60 } else {
61 let first = value.remove(0).into();
62 let rest = if value.is_empty() {
63 None
64 } else {
65 Some(value.into_iter().map(std::convert::Into::into).collect())
66 };
67
68 Ok(Self { first, rest })
69 }
70 }
71}
72
73impl<'a> IntoIterator for &'a MultiValue<'a> {
74 type Item = std::borrow::Cow<'a, str>;
75 type IntoIter = Iter<'a>;
76
77 fn into_iter(self) -> Self::IntoIter {
78 self.iter()
79 }
80}
81
82pub struct Iter<'a> {
83 first: Option<Cow<'a, str>>,
84 rest: Option<std::slice::Iter<'a, Cow<'a, str>>>,
85}
86
87impl<'a> Iterator for Iter<'a> {
88 type Item = Cow<'a, str>;
89
90 fn next(&mut self) -> Option<Self::Item> {
91 self.first.take().or_else(|| {
92 self.rest.take().and_then(|mut rest| {
93 let next = rest.next().cloned();
94 self.rest = Some(rest);
95 next
96 })
97 })
98 }
99}
100
101impl<'a, 'de: 'a> serde::de::Deserialize<'de> for MultiValue<'a> {
102 fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
103 const EXPECTED: &str = "one or more header values";
104
105 struct MultiValueVisitor<'a> {
106 _lifetime: PhantomData<&'a ()>,
107 }
108
109 impl<'a, 'de: 'a> serde::de::Visitor<'de> for MultiValueVisitor<'a> {
110 type Value = MultiValue<'a>;
111
112 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 formatter.write_str(EXPECTED)
114 }
115
116 fn visit_borrowed_str<E: serde::de::Error>(
117 self,
118 v: &'de str,
119 ) -> Result<Self::Value, E> {
120 Ok(MultiValue::new(v))
121 }
122
123 fn visit_seq<A: serde::de::SeqAccess<'de>>(
124 self,
125 mut seq: A,
126 ) -> Result<Self::Value, A::Error> {
127 let mut result: Option<MultiValue<'a>> = None;
128
129 while let Some(value) = seq.next_element::<Cow<'a, str>>()? {
130 match result {
131 Some(ref mut multi_value) => {
132 multi_value.push(value);
133 }
134 None => {
135 result = Some(MultiValue::new(value));
136 }
137 }
138 }
139
140 result.ok_or_else(|| {
141 serde::de::Error::invalid_value(serde::de::Unexpected::Seq, &EXPECTED)
142 })
143 }
144
145 fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
146 Ok(MultiValue::new(v.to_string()))
147 }
148 }
149
150 deserializer.deserialize_any(MultiValueVisitor {
151 _lifetime: PhantomData,
152 })
153 }
154}
155
156impl serde::ser::Serialize for MultiValue<'_> {
157 fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
158 use serde::ser::SerializeSeq;
159
160 match self.rest.as_ref() {
161 Some(rest) => {
162 let mut seq = serializer.serialize_seq(Some(rest.len() + 1))?;
163 seq.serialize_element(&self.first)?;
164
165 for element in rest {
166 seq.serialize_element(&element)?;
167 }
168
169 seq.end()
170 }
171 None => self.first.serialize(serializer),
172 }
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use crate::multi_value::MultiValue;
179
180 #[derive(Debug, Eq, PartialEq, serde::Deserialize)]
181 struct Test<'a> {
182 #[serde(borrow)]
183 header_values: super::MultiValue<'a>,
184 }
185
186 #[test]
187 fn deserialize_multi_value() -> Result<(), Box<dyn std::error::Error>> {
188 let singleton_example = r#"{ "header_values": "test" }"#;
189 let multi_example = r#"{ "header_values": ["foo", "bar", "baz"] }"#;
190
191 let singleton_example_parsed = serde_json::from_str::<Test<'_>>(singleton_example)?;
192 let multi_example_parsed = serde_json::from_str::<Test<'_>>(multi_example)?;
193
194 let singleton_example_expected = Test {
195 header_values: MultiValue::new("test"),
196 };
197
198 let multi_example_expected = Test {
199 header_values: vec!["foo", "bar", "baz"].try_into()?,
200 };
201
202 assert_eq!(singleton_example_parsed, singleton_example_expected);
203 assert_eq!(multi_example_parsed, multi_example_expected);
204 Ok(())
205 }
206
207 #[test]
208 fn iter() -> Result<(), Box<dyn std::error::Error>> {
209 let singleton_example = MultiValue::new("test");
210
211 let multi_example: MultiValue<'_> = vec!["foo", "bar", "baz"].try_into()?;
212
213 assert_eq!(singleton_example.iter().collect::<Vec<_>>(), vec!["test"]);
214 assert_eq!(
215 multi_example.iter().collect::<Vec<_>>(),
216 vec!["foo", "bar", "baz"]
217 );
218 Ok(())
219 }
220}