float-pigment-css 0.8.2

The CSS parser for the float-pigment project.
Documentation
use alloc::string::ToString;

use super::*;

#[inline(never)]
pub(crate) fn font_face_src<'a, 't: 'a, 'i: 't>(
    parser: &'a mut Parser<'i, 't>,
    _properties: &mut [PropertyMeta],
    _st: &mut ParseState,
) -> Result<Vec<FontSrc>, ParseError<'i, CustomError>> {
    parser.parse_comma_separated(|parser| {
        let next = parser.next()?.clone();
        let mut maybe_font_src = match &next {
            Token::Function(name) => {
                let name: &str = name;
                let fs = parser.parse_nested_block(|parser| match name {
                    "url" => {
                        let url = parser.expect_string()?.to_string();
                        Ok(FontSrc::Url(FontUrl { url, format: None }))
                    }
                    "local" => {
                        let name = font_family_name(parser)?;
                        Ok(FontSrc::Local(name))
                    }
                    _ => Err(parser.new_unexpected_token_error(next.clone())),
                })?;
                Ok(fs)
            }
            Token::UnquotedUrl(value) => {
                Ok(FontSrc::Url(FontUrl { url: value.to_string(), format: None}))
            }
            _ => Err(parser.new_unexpected_token_error(next.clone())),
        };
        if let Ok(FontSrc::Url(font_url)) = maybe_font_src.as_mut() {
            if !parser.is_exhausted() {
                let next = parser.next()?.clone();
                match &next {
                    Token::Function(name) => match name.to_string().as_str() {
                        "format" => {
                            let format = parser.parse_nested_block(|parser| {
                                parser.parse_comma_separated(
                                    |parser: &mut Parser| -> Result<String, ParseError<'_, CustomError>> {
                                        let s = parser.expect_string()?.to_string();
                                        Ok(s)
                                    }
                                )
                            })?;
                            font_url.format = Some(format);
                        },
                        _ => return Err(parser.new_unexpected_token_error(next.clone()))
                    },
                    _ => return Err(parser.new_unexpected_token_error(next.clone()))
                };
            }
        }
        maybe_font_src
    })
}

#[inline(never)]
pub(crate) fn font_display<'a, 't: 'a, 'i: 't>(
    parser: &'a mut Parser<'i, 't>,
) -> Result<FontDisplay, ParseError<'i, CustomError>> {
    let next: &str = &parser.expect_ident()?.clone();
    let next: &str = &next.to_lowercase();
    match next {
        "auto" => Ok(FontDisplay::Auto),
        "block" => Ok(FontDisplay::Block),
        "swap" => Ok(FontDisplay::Swap),
        "fallback" => Ok(FontDisplay::Fallback),
        "optional" => Ok(FontDisplay::Optional),
        _ => Err(parser.new_custom_error(CustomError::Unsupported)),
    }
}

#[inline(never)]
pub(crate) fn font_family_name<'a, 't: 'a, 'i: 't>(
    parser: &'a mut Parser<'i, 't>,
) -> Result<FontFamilyName, ParseError<'i, CustomError>> {
    let ret;
    let name = parser.next()?.clone();
    match name {
        Token::Ident(s) => {
            let s: &str = &s;
            match s.to_lowercase().as_str() {
                "serif" => ret = FontFamilyName::Serif,
                "sans-serif" => ret = FontFamilyName::SansSerif,
                "monospace" => ret = FontFamilyName::Monospace,
                "cursive" => ret = FontFamilyName::Cursive,
                "fantasy" => ret = FontFamilyName::Fantasy,
                "system-ui" => ret = FontFamilyName::SystemUi,
                _ => {
                    let mut v = vec![s.to_string()];
                    while !parser.is_exhausted() {
                        if next_is_comma(parser) || next_is_important(parser) {
                            break;
                        }
                        let name = parser.next()?.clone();
                        match name {
                            Token::Ident(s) => {
                                let s = s.to_string();
                                v.push(s);
                            }
                            _ => return Err(parser.new_unexpected_token_error::<CustomError>(name)),
                        }
                    }
                    let str = v.join(" ");
                    ret = FontFamilyName::Title(str.into());
                }
            }
        }
        Token::QuotedString(s) => {
            ret = FontFamilyName::Title(s.to_string().into());
        }
        _ => return Err(parser.new_unexpected_token_error(name)),
    }
    Ok(ret)
}

#[inline(never)]
pub(crate) fn font_family_repr<'a, 't: 'a, 'i: 't>(
    parser: &'a mut Parser<'i, 't>,
    _properties: &mut [PropertyMeta],
    _st: &mut ParseState,
) -> Result<FontFamilyType, ParseError<'i, CustomError>> {
    parser.try_parse(|parser| {
        parse_comma_separated_without_important(parser, |parser| font_family_name(parser))
            .map(|ret| FontFamilyType::Names(ret.into()))
    })
}