#![feature(conservative_impl_trait)]
use std::ascii::AsciiExt;
pub fn content_encodings<'a>(s: &'a str) -> impl Iterator<Item = ContentEncoding<'a>> {
s.split(',').rev().map(ContentEncoding::new)
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub enum ContentEncoding<'a> {
Std(StdContentEncoding),
Other(&'a str),
}
impl<'a> ContentEncoding<'a> {
pub fn new(s: &'a str) -> Self {
let s = s.trim();
match s.parse() {
Ok(enc) => ContentEncoding::Std(enc),
Err(_) => ContentEncoding::Other(s),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub enum StdContentEncoding {
Brottli,
Compress,
Deflate,
EfficientXML,
Gzip,
Identity,
Pack200Gzip,
}
impl std::str::FromStr for StdContentEncoding {
type Err = ();
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
use self::StdContentEncoding::*;
if s.eq_ignore_ascii_case("br") {
Ok(Brottli)
} else if s.eq_ignore_ascii_case("compress") {
Ok(Compress)
} else if s.eq_ignore_ascii_case("deflate") {
Ok(Deflate)
} else if s.eq_ignore_ascii_case("exi") {
Ok(EfficientXML)
} else if s.eq_ignore_ascii_case("gzip") {
Ok(Gzip)
} else if s.eq_ignore_ascii_case("identity") {
Ok(Identity)
} else if s.eq_ignore_ascii_case("pack200-gzip") {
Ok(Pack200Gzip)
} else if s.is_empty() {
Ok(Identity)
} else {
Err(())
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_ce() {
use self::StdContentEncoding::*;
use self::ContentEncoding::*;
assert_eq!(ContentEncoding::new("br"), Std(Brottli));
assert_eq!(ContentEncoding::new("\t\t\rBr "), Std(Brottli));
assert_eq!(ContentEncoding::new("compress"), Std(Compress));
assert_eq!(ContentEncoding::new(" COMpress "), Std(Compress));
assert_eq!(ContentEncoding::new("deflate"), Std(Deflate));
assert_eq!(ContentEncoding::new("\t\n dEFLAte "), Std(Deflate));
assert_eq!(ContentEncoding::new("exi"), Std(EfficientXML));
assert_eq!(ContentEncoding::new("\tEXI\t"), Std(EfficientXML));
assert_eq!(ContentEncoding::new("gzip"), Std(Gzip));
assert_eq!(ContentEncoding::new(" \tgZIP"), Std(Gzip));
assert_eq!(ContentEncoding::new("identity"), Std(Identity));
assert_eq!(ContentEncoding::new("\niDENtiTY\r\r\r "), Std(Identity));
assert_eq!(ContentEncoding::new(""), Std(Identity));
assert_eq!(ContentEncoding::new(" \t "), Std(Identity));
assert_eq!(ContentEncoding::new("pack200-gzip"), Std(Pack200Gzip));
assert_eq!(ContentEncoding::new(" PaCK200-GZip "), Std(Pack200Gzip));
assert_eq!(ContentEncoding::new("ÆØБД❤"), Other("ÆØБД❤"));
}
#[test]
fn test_ces() {
use self::StdContentEncoding::*;
use self::ContentEncoding::*;
let mut ce = content_encodings("deflate, br, identity");
assert_eq!(ce.next().unwrap(), Std(Identity));
assert_eq!(ce.next().unwrap(), Std(Brottli));
assert_eq!(ce.next().unwrap(), Std(Deflate));
assert!(ce.next().is_none());
let mut ce = content_encodings("identity");
assert_eq!(ce.next().unwrap(), Std(Identity));
assert!(ce.next().is_none());
let mut ce = content_encodings("");
assert_eq!(ce.next().unwrap(), Std(Identity));
assert!(ce.next().is_none());
let mut ce = content_encodings("\t\t,, , ,");
assert_eq!(ce.next().unwrap(), Std(Identity));
assert_eq!(ce.next().unwrap(), Std(Identity));
assert_eq!(ce.next().unwrap(), Std(Identity));
assert_eq!(ce.next().unwrap(), Std(Identity));
assert_eq!(ce.next().unwrap(), Std(Identity));
assert!(ce.next().is_none());
let mut ce = content_encodings("Br, exi,pack200-GZip ");
assert_eq!(ce.next().unwrap(), Std(Pack200Gzip));
assert_eq!(ce.next().unwrap(), Std(EfficientXML));
assert_eq!(ce.next().unwrap(), Std(Brottli));
assert!(ce.next().is_none());
let mut ce = content_encodings("\t\t\t gzip");
assert_eq!(ce.next().unwrap(), Std(Gzip));
assert!(ce.next().is_none());
let mut ce = content_encodings("\tabc\t\t, def ");
assert_eq!(ce.next().unwrap(), Other("def"));
assert_eq!(ce.next().unwrap(), Other("abc"));
assert!(ce.next().is_none());
}
}