rama_http_headers/util/
csv.rs1use std::fmt;
2
3use rama_http_types::HeaderValue;
4
5use crate::Error;
6
7pub fn from_comma_delimited<'i, I, T, E>(values: &mut I) -> Result<E, Error>
9where
10 I: Iterator<Item = &'i HeaderValue>,
11 T: std::str::FromStr,
12 E: FromIterator<T>,
13{
14 values
15 .flat_map(|value| {
16 value
17 .to_str()
18 .into_iter()
19 .flat_map(|string| split_csv_str(string))
20 })
21 .collect()
22}
23
24pub(crate) fn split_csv_str<T: std::str::FromStr>(
25 string: &str,
26) -> impl Iterator<Item = Result<T, Error>> + use<'_, T> {
27 let mut in_quotes = false;
28 string
29 .split(move |c| {
30 #[expect(clippy::collapsible_else_if)]
31 if in_quotes {
32 if c == '"' {
33 in_quotes = false;
34 }
35 false } else {
37 if c == ',' {
38 true } else {
40 if c == '"' {
41 in_quotes = true;
42 }
43 false }
45 }
46 })
47 .filter_map(|x| match x.trim() {
48 "" => None,
49 y => Some(y.parse().map_err(|_e| Error::invalid())),
50 })
51}
52
53pub fn fmt_comma_delimited<T: fmt::Display>(
55 f: &mut fmt::Formatter,
56 mut iter: impl Iterator<Item = T>,
57) -> fmt::Result {
58 if let Some(part) = iter.next() {
59 fmt::Display::fmt(&part, f)?;
60 }
61 for part in iter {
62 f.write_str(", ")?;
63 fmt::Display::fmt(&part, f)?;
64 }
65 Ok(())
66}