style: Cleanup and refactor how media types are represented.

This is necessary for the upcoming work in Stylo, given I plan to make MediaType
different for Servo and Gecko, and the Unknown variant doesn't fit in MediaType
to be fair, the device is never going to have any unknown media type.
This commit is contained in:
Emilio Cobos Álvarez 2016-12-26 22:13:43 +01:00
parent b49eb6f566
commit b4caebae69
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 45 additions and 36 deletions

View file

@ -94,6 +94,12 @@ pub struct MediaQuery {
} }
impl MediaQuery { impl MediaQuery {
/// Return a media query that never matches, used for when we fail to parse
/// a given media query.
fn never_matching() -> Self {
Self::new(Some(Qualifier::Not), MediaQueryType::All, vec![])
}
pub fn new(qualifier: Option<Qualifier>, media_type: MediaQueryType, pub fn new(qualifier: Option<Qualifier>, media_type: MediaQueryType,
expressions: Vec<Expression>) -> MediaQuery { expressions: Vec<Expression>) -> MediaQuery {
MediaQuery { MediaQuery {
@ -115,9 +121,9 @@ impl ToCss for MediaQuery {
let mut type_ = String::new(); let mut type_ = String::new();
match self.media_type { match self.media_type {
MediaQueryType::All => try!(write!(type_, "all")), MediaQueryType::All => try!(write!(type_, "all")),
MediaQueryType::MediaType(MediaType::Screen) => try!(write!(type_, "screen")), MediaQueryType::Known(MediaType::Screen) => try!(write!(type_, "screen")),
MediaQueryType::MediaType(MediaType::Print) => try!(write!(type_, "print")), MediaQueryType::Known(MediaType::Print) => try!(write!(type_, "print")),
MediaQueryType::MediaType(MediaType::Unknown(ref desc)) => try!(write!(type_, "{}", desc)), MediaQueryType::Unknown(ref desc) => try!(write!(type_, "{}", desc)),
}; };
if self.expressions.is_empty() { if self.expressions.is_empty() {
return write!(dest, "{}", type_) return write!(dest, "{}", type_)
@ -148,7 +154,18 @@ impl ToCss for MediaQuery {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum MediaQueryType { pub enum MediaQueryType {
All, // Always true All, // Always true
MediaType(MediaType), Known(MediaType),
Unknown(Atom),
}
impl MediaQueryType {
fn matches(&self, other: &MediaType) -> bool {
match *self {
MediaQueryType::All => true,
MediaQueryType::Known(ref known_type) => known_type == other,
MediaQueryType::Unknown(..) => false,
}
}
} }
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
@ -156,7 +173,6 @@ pub enum MediaQueryType {
pub enum MediaType { pub enum MediaType {
Screen, Screen,
Print, Print,
Unknown(Atom),
} }
#[derive(Debug)] #[derive(Debug)]
@ -220,10 +236,10 @@ impl MediaQuery {
let media_type; let media_type;
if let Ok(ident) = input.try(|input| input.expect_ident()) { if let Ok(ident) = input.try(|input| input.expect_ident()) {
media_type = match_ignore_ascii_case! { ident, media_type = match_ignore_ascii_case! { ident,
"screen" => MediaQueryType::MediaType(MediaType::Screen), "screen" => MediaQueryType::Known(MediaType::Screen),
"print" => MediaQueryType::MediaType(MediaType::Print), "print" => MediaQueryType::Known(MediaType::Print),
"all" => MediaQueryType::All, "all" => MediaQueryType::All,
_ => MediaQueryType::MediaType(MediaType::Unknown(Atom::from(&*ident))) _ => MediaQueryType::Unknown(Atom::from(&*ident))
} }
} else { } else {
// Media type is only optional if qualifier is not specified. // Media type is only optional if qualifier is not specified.
@ -253,10 +269,8 @@ pub fn parse_media_query_list(input: &mut Parser) -> MediaList {
let mut media_queries = vec![]; let mut media_queries = vec![];
loop { loop {
media_queries.push( media_queries.push(
input.parse_until_before(Delimiter::Comma, MediaQuery::parse) input.parse_until_before(Delimiter::Comma, MediaQuery::parse).ok()
.unwrap_or(MediaQuery::new(Some(Qualifier::Not), .unwrap_or_else(MediaQuery::never_matching));
MediaQueryType::All,
vec!())));
match input.next() { match input.next() {
Ok(Token::Comma) => {}, Ok(Token::Comma) => {},
Ok(_) => unreachable!(), Ok(_) => unreachable!(),
@ -275,12 +289,7 @@ impl MediaList {
// Check if it is an empty media query list or any queries match (OR condition) // Check if it is an empty media query list or any queries match (OR condition)
// https://drafts.csswg.org/mediaqueries-4/#mq-list // https://drafts.csswg.org/mediaqueries-4/#mq-list
self.media_queries.is_empty() || self.media_queries.iter().any(|mq| { self.media_queries.is_empty() || self.media_queries.iter().any(|mq| {
// Check if media matches. Unknown media never matches. let media_match = mq.media_type.matches(&device.media_type);
let media_match = match mq.media_type {
MediaQueryType::MediaType(MediaType::Unknown(_)) => false,
MediaQueryType::MediaType(ref media_type) => *media_type == device.media_type,
MediaQueryType::All => true,
};
// Check if all conditions match (AND condition) // Check if all conditions match (AND condition)
let query_match = media_match && mq.expressions.iter().all(|expression| { let query_match = media_match && mq.expressions.iter().all(|expression| {

View file

@ -74,7 +74,7 @@ fn test_mq_screen() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == None, css.to_owned()); assert!(q.qualifier == None, css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
@ -82,7 +82,7 @@ fn test_mq_screen() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned()); assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
@ -90,7 +90,7 @@ fn test_mq_screen() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned()); assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
} }
@ -101,7 +101,7 @@ fn test_mq_print() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == None, css.to_owned()); assert!(q.qualifier == None, css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
@ -109,7 +109,7 @@ fn test_mq_print() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned()); assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
@ -117,7 +117,7 @@ fn test_mq_print() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned()); assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
} }
@ -128,7 +128,7 @@ fn test_mq_unknown() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == None, css.to_owned()); assert!(q.qualifier == None, css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("fridge"))), css.to_owned()); assert!(q.media_type == MediaQueryType::Unknown(Atom::from("fridge")), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
@ -136,7 +136,7 @@ fn test_mq_unknown() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned()); assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("glass"))), css.to_owned()); assert!(q.media_type == MediaQueryType::Unknown(Atom::from("glass")), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
@ -144,7 +144,7 @@ fn test_mq_unknown() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned()); assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("wood"))), css.to_owned()); assert!(q.media_type == MediaQueryType::Unknown(Atom::from("wood")), css.to_owned());
assert!(q.expressions.len() == 0, css.to_owned()); assert!(q.expressions.len() == 0, css.to_owned());
}); });
} }
@ -182,12 +182,12 @@ fn test_mq_or() {
assert!(list.media_queries.len() == 2, css.to_owned()); assert!(list.media_queries.len() == 2, css.to_owned());
let q0 = &list.media_queries[0]; let q0 = &list.media_queries[0];
assert!(q0.qualifier == None, css.to_owned()); assert!(q0.qualifier == None, css.to_owned());
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned()); assert!(q0.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
assert!(q0.expressions.len() == 0, css.to_owned()); assert!(q0.expressions.len() == 0, css.to_owned());
let q1 = &list.media_queries[1]; let q1 = &list.media_queries[1];
assert!(q1.qualifier == None, css.to_owned()); assert!(q1.qualifier == None, css.to_owned());
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned()); assert!(q1.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
assert!(q1.expressions.len() == 0, css.to_owned()); assert!(q1.expressions.len() == 0, css.to_owned());
}); });
} }
@ -225,7 +225,7 @@ fn test_mq_expressions() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == None, css.to_owned()); assert!(q.qualifier == None, css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
assert!(q.expressions.len() == 1, css.to_owned()); assert!(q.expressions.len() == 1, css.to_owned());
match q.expressions[0] { match q.expressions[0] {
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))), Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
@ -237,7 +237,7 @@ fn test_mq_expressions() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == None, css.to_owned()); assert!(q.qualifier == None, css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
assert!(q.expressions.len() == 1, css.to_owned()); assert!(q.expressions.len() == 1, css.to_owned());
match q.expressions[0] { match q.expressions[0] {
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))), Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
@ -249,7 +249,7 @@ fn test_mq_expressions() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == None, css.to_owned()); assert!(q.qualifier == None, css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
assert!(q.expressions.len() == 1, css.to_owned()); assert!(q.expressions.len() == 1, css.to_owned());
match q.expressions[0] { match q.expressions[0] {
Expression::Width(Range::Eq(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))), Expression::Width(Range::Eq(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
@ -261,7 +261,7 @@ fn test_mq_expressions() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == None, css.to_owned()); assert!(q.qualifier == None, css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("fridge"))), css.to_owned()); assert!(q.media_type == MediaQueryType::Unknown(Atom::from("fridge")), css.to_owned());
assert!(q.expressions.len() == 1, css.to_owned()); assert!(q.expressions.len() == 1, css.to_owned());
match q.expressions[0] { match q.expressions[0] {
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(52))), Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(52))),
@ -302,7 +302,7 @@ fn test_mq_multiple_expressions() {
assert!(list.media_queries.len() == 1, css.to_owned()); assert!(list.media_queries.len() == 1, css.to_owned());
let q = &list.media_queries[0]; let q = &list.media_queries[0];
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned()); assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned()); assert!(q.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
assert!(q.expressions.len() == 2, css.to_owned()); assert!(q.expressions.len() == 2, css.to_owned());
match q.expressions[0] { match q.expressions[0] {
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))), Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
@ -377,7 +377,7 @@ fn test_mq_malformed_expressions() {
assert!(q0.expressions.len() == 0, css.to_owned()); assert!(q0.expressions.len() == 0, css.to_owned());
let q1 = &list.media_queries[1]; let q1 = &list.media_queries[1];
assert!(q1.qualifier == None, css.to_owned()); assert!(q1.qualifier == None, css.to_owned());
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned()); assert!(q1.media_type == MediaQueryType::Known(MediaType::Print), css.to_owned());
assert!(q1.expressions.len() == 0, css.to_owned()); assert!(q1.expressions.len() == 0, css.to_owned());
}); });
@ -385,7 +385,7 @@ fn test_mq_malformed_expressions() {
assert!(list.media_queries.len() == 2, css.to_owned()); assert!(list.media_queries.len() == 2, css.to_owned());
let q0 = &list.media_queries[0]; let q0 = &list.media_queries[0];
assert!(q0.qualifier == None, css.to_owned()); assert!(q0.qualifier == None, css.to_owned());
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned()); assert!(q0.media_type == MediaQueryType::Known(MediaType::Screen), css.to_owned());
assert!(q0.expressions.len() == 0, css.to_owned()); assert!(q0.expressions.len() == 0, css.to_owned());
let q1 = &list.media_queries[1]; let q1 = &list.media_queries[1];
assert!(q1.qualifier == Some(Qualifier::Not), css.to_owned()); assert!(q1.qualifier == Some(Qualifier::Not), css.to_owned());