use crate::dep::mime::{self, Mime};
use crate::specifier::QualityValue;
use crate::{Error, Header, util};
use rama_http_types::{HeaderName, HeaderValue, header};
use std::iter::FromIterator;
fn qitem(mime: Mime) -> QualityValue<Mime> {
QualityValue::new(mime, Default::default())
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Accept(Vec<QualityValue<Mime>>);
impl Header for Accept {
fn name() -> &'static HeaderName {
&header::ACCEPT
}
fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(values: &mut I) -> Result<Self, Error> {
util::csv::from_comma_delimited(values).map(Accept)
}
fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
use std::fmt;
struct Format<F>(F);
impl<F> fmt::Display for Format<F>
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(self.0)(f)
}
}
let s = format!(
"{}",
Format(|f: &mut fmt::Formatter<'_>| {
util::csv::fmt_comma_delimited(&mut *f, self.0.iter())
})
);
values.extend(Some(HeaderValue::from_str(&s).unwrap()))
}
}
impl FromIterator<QualityValue<Mime>> for Accept {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = QualityValue<Mime>>,
{
Accept(iter.into_iter().collect())
}
}
impl Accept {
pub fn star() -> Accept {
Accept(vec![qitem(mime::STAR_STAR)])
}
pub fn json() -> Accept {
Accept(vec![qitem(mime::APPLICATION_JSON)])
}
pub fn text() -> Accept {
Accept(vec![qitem(mime::TEXT_STAR)])
}
pub fn image() -> Accept {
Accept(vec![qitem(mime::IMAGE_STAR)])
}
pub fn iter(&self) -> impl Iterator<Item = &QualityValue<Mime>> {
self.0.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
dep::mime::{TEXT_HTML, TEXT_PLAIN, TEXT_PLAIN_UTF_8},
specifier::Quality,
};
macro_rules! test_header {
($name: ident, $input: expr, $expected: expr) => {
#[test]
fn $name() {
assert_eq!(
Accept::decode(
&mut $input
.into_iter()
.map(|s| HeaderValue::from_bytes(s).unwrap())
.collect::<Vec<_>>()
.iter()
)
.ok(),
$expected,
);
}
};
}
test_header!(
test1,
vec![b"audio/*; q=0.2, audio/basic"],
Some(Accept(vec![
QualityValue::new("audio/*".parse().unwrap(), Quality::from(200)),
qitem("audio/basic".parse().unwrap()),
]))
);
test_header!(
test2,
vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
Some(Accept(vec![
QualityValue::new(TEXT_PLAIN, Quality::from(500)),
qitem(TEXT_HTML),
QualityValue::new("text/x-dvi".parse().unwrap(), Quality::from(800)),
qitem("text/x-c".parse().unwrap()),
]))
);
test_header!(
test3,
vec![b"text/plain; charset=utf-8"],
Some(Accept(vec![qitem(TEXT_PLAIN_UTF_8),]))
);
test_header!(
test4,
vec![b"text/plain; charset=utf-8; q=0.5"],
Some(Accept(vec![QualityValue::new(
TEXT_PLAIN_UTF_8,
Quality::from(500)
),]))
);
}