use serde::Deserialize;
#[cfg(feature = "schema")]
pub(crate) fn header_map_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
schemars::json_schema!({
"type": "object",
"description": "A header/query/form name to value mapping. A name that repeats is \
written once with a list of values instead of a scalar. An unquoted number or \
boolean is accepted and coerced to its string form.",
"additionalProperties": {
"anyOf": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" },
{ "type": "array", "items": { "type": "string" } }
]
}
})
}
pub(crate) fn deserialize_headers<'de, D>(
deserializer: D,
) -> Result<Vec<(String, String)>, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::{MapAccess, SeqAccess, Visitor};
enum HeaderValue {
Single(String),
Multiple(Vec<String>),
}
impl<'de> Deserialize<'de> for HeaderValue {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct HeaderValueVisitor;
impl<'de> Visitor<'de> for HeaderValueVisitor {
type Value = HeaderValue;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("a string or a list of strings")
}
fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
Ok(HeaderValue::Single(value.to_string()))
}
fn visit_bool<E: serde::de::Error>(self, value: bool) -> Result<Self::Value, E> {
Ok(HeaderValue::Single(value.to_string()))
}
fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
Ok(HeaderValue::Single(value.to_string()))
}
fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
Ok(HeaderValue::Single(value.to_string()))
}
fn visit_f64<E: serde::de::Error>(self, value: f64) -> Result<Self::Value, E> {
Ok(HeaderValue::Single(value.to_string()))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut values = Vec::new();
while let Some(value) = seq.next_element::<String>()? {
values.push(value);
}
Ok(HeaderValue::Multiple(values))
}
}
deserializer.deserialize_any(HeaderValueVisitor)
}
}
struct HeadersVisitor;
impl<'de> Visitor<'de> for HeadersVisitor {
type Value = Vec<(String, String)>;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("a map of header name to a string or list of strings")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut headers = Vec::new();
while let Some((name, value)) = map.next_entry::<String, HeaderValue>()? {
match value {
HeaderValue::Single(value) => headers.push((name, value)),
HeaderValue::Multiple(values) => {
headers.extend(values.into_iter().map(|value| (name.clone(), value)));
}
}
}
Ok(headers)
}
}
deserializer.deserialize_map(HeadersVisitor)
}
pub(crate) fn serialize_headers<S>(
headers: &[(String, String)],
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeMap;
let mut order: Vec<&str> = Vec::new();
let mut grouped: std::collections::HashMap<&str, Vec<&str>> = std::collections::HashMap::new();
for (name, value) in headers {
let values = grouped.entry(name.as_str()).or_default();
if values.is_empty() {
order.push(name.as_str());
}
values.push(value.as_str());
}
let mut map = serializer.serialize_map(Some(order.len()))?;
for name in order {
let values = &grouped[name];
if values.len() == 1 {
map.serialize_entry(name, values[0])?;
} else {
map.serialize_entry(name, values)?;
}
}
map.end()
}