refactor(headers): Use u16 based newtype for quality value

Using floating point numbers is problematic because comparison is inexact.
They also take more space than integral numbers in this case.

Add `FromPrimitve`, `ToPrimitive` and `Default` traits to quality newtype.

Closes: #330

BREAKING_CHANGE: Replace f32 quality values in quality items with a
Quality(u16) newtype. Valid values are from 0 to 1000.
This commit is contained in:
Pyfisch
2015-02-22 16:51:53 +01:00
parent b1b8bf1db7
commit 8f6ce453de
6 changed files with 202 additions and 114 deletions

View File

@@ -33,7 +33,8 @@ impl_list_header!(Accept,
mod tests {
use mime::*;
use header::{Header, QualityItem, qitem};
use header::{Header, Quality, QualityItem, qitem};
use super::Accept;
#[test]
@@ -49,7 +50,7 @@ mod tests {
fn test_parse_header_with_quality() {
let a: Accept = Header::parse_header([b"text/plain; charset=utf-8; q=0.5".to_vec()].as_slice()).unwrap();
let b = Accept(vec![
QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]), 0.5f32),
QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]), Quality(500)),
]);
assert_eq!(a, b);
}

View File

@@ -13,7 +13,7 @@ impl_list_header!(AcceptEncoding,
#[cfg(test)]
mod tests {
use header::{Encoding, Header, QualityItem};
use header::{Encoding, Header, qitem, Quality, QualityItem};
use super::*;
@@ -21,8 +21,8 @@ mod tests {
fn test_parse_header() {
let a: AcceptEncoding = Header::parse_header([b"gzip;q=1.0, identity; q=0.5".to_vec()].as_slice()).unwrap();
let b = AcceptEncoding(vec![
QualityItem{item: Encoding::Gzip, quality: 1f32},
QualityItem{item: Encoding::Identity, quality: 0.5f32},
qitem(Encoding::Gzip),
QualityItem::new(Encoding::Identity, Quality(500)),
]);
assert_eq!(a, b);
}

View File

@@ -46,41 +46,45 @@ impl_list_header!(AcceptLanguage,
"Accept-Language",
Vec<QualityItem<Language>>);
#[cfg(test)]
mod tests {
use header::{Header, qitem, Quality, QualityItem};
use super::*;
#[test]
fn test_parse_header() {
let a: AcceptLanguage = Header::parse_header(
[b"en-us;q=1.0, en;q=0.5, fr".to_vec()].as_slice()).unwrap();
let b = AcceptLanguage(vec![
qitem(Language{primary: "en".to_string(), sub: Some("us".to_string())}),
QualityItem::new(Language{primary: "en".to_string(), sub: None},
Quality(500)),
qitem(Language{primary: "fr".to_string(), sub: None}),
]);
assert_eq!(format!("{}", a), format!("{}", b));
assert_eq!(a, b);
}
#[test]
fn test_display() {
assert_eq!("en".to_string(),
format!("{}", Language{primary: "en".to_string(),
sub: None}));
assert_eq!("en-us".to_string(),
format!("{}", Language{primary: "en".to_string(),
sub: Some("us".to_string())}));
}
#[test]
fn test_from_str() {
assert_eq!(Language { primary: "en".to_string(), sub: None },
"en".parse().unwrap());
assert_eq!(Language { primary: "en".to_string(),
sub: Some("us".to_string()) },
"en-us".parse().unwrap());
}
}
bench_header!(bench, AcceptLanguage,
{ vec![b"en-us;q=1.0, en;q=0.5, fr".to_vec()] });
#[test]
fn test_parse_header() {
let a: AcceptLanguage = header::Header::parse_header(
[b"en-us;q=1.0, en;q=0.5, fr".to_vec()].as_slice()).unwrap();
let b = AcceptLanguage(vec![
QualityItem { item: Language{primary: "en".to_string(),
sub: Some("us".to_string())},
quality: 1f32 },
QualityItem { item: Language{primary: "en".to_string(), sub: None},
quality: 0.5f32 },
QualityItem { item: Language{primary: "fr".to_string(), sub: None},
quality: 1f32 },
]);
assert_eq!(format!("{}", a), format!("{}", b));
assert_eq!(a, b);
}
#[test]
fn test_display() {
assert_eq!("en".to_string(),
format!("{}", Language{primary: "en".to_string(),
sub: None}));
assert_eq!("en-us".to_string(),
format!("{}", Language{primary: "en".to_string(),
sub: Some("us".to_string())}));
}
#[test]
fn test_from_str() {
assert_eq!(Language { primary: "en".to_string(), sub: None },
"en".parse().unwrap());
assert_eq!(Language { primary: "en".to_string(),
sub: Some("us".to_string()) },
"en-us".parse().unwrap());
}