use {
super::{
FamilyName,
FamilyNameSyntax::*,
FontFamily::*,
GenericFontFamilyName::{self, *},
},
crate::{domain::Atom, CustomParseError},
cssparser::{serialize_identifier, ParseError, Parser, ToCss},
std::fmt,
};
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum FontFamily {
FamilyName(FamilyName),
Generic(GenericFontFamilyName),
}
impl ToCss for FontFamily {
fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
use self::FontFamily::*;
match *self {
FamilyName(ref name) => name.to_css(dest),
Generic(ref name) => name.to_css(dest),
}
}
}
impl FontFamily {
pub(crate) fn parse<'i, 't>(
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i, CustomParseError<'i>>> {
if let Ok(value) = input.r#try(|i| i.expect_string_cloned()) {
return Ok(FontFamily::FamilyName(FamilyName {
name: Atom::from(&*value),
syntax: Quoted,
}));
}
let first_ident = input.expect_ident()?.clone();
let is_css_wide_keyword = {
match_ignore_ascii_case! {
&first_ident,
"serif" => return Ok(Generic(serif)),
"sans-serif" => return Ok(Generic(sans_serif)),
"cursive" => return Ok(Generic(cursive)),
"fantasy" => return Ok(Generic(fantasy)),
"monospace" => return Ok(Generic(monospace)),
"inherit" | "initial" | "unset" | "default" => true,
_ => false,
}
};
let mut value = first_ident.as_ref().to_owned();
let mut serialization = String::new();
serialize_identifier(&first_ident, &mut serialization).unwrap();
if is_css_wide_keyword {
let ident = input.expect_ident()?;
value.push(' ');
value.push_str(ident);
serialization.push(' ');
serialize_identifier(ident, &mut serialization).unwrap();
}
while let Ok(ident) = input.r#try(|i| i.expect_ident_cloned()) {
value.push(' ');
value.push_str(&ident);
serialization.push(' ');
serialize_identifier(&ident, &mut serialization).unwrap();
}
Ok(FontFamily::FamilyName(FamilyName {
name: Atom::from(value),
syntax: Identifiers(serialization),
}))
}
}