pub(crate) struct TopLevelRuleParser
{
pub(crate) context: ParserContext,
pub(crate) state: State,
pub(crate) namespaces: Rc<Namespaces>,
}
impl<'i> AtRuleParser<'i> for TopLevelRuleParser
{
type PreludeNoBlock = CssRule;
type PreludeBlock = AtRuleBlockPrelude;
type AtRule = CssRule;
type Error = CustomParseError<'i>;
fn parse_prelude<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) -> Result<AtRuleType<Self::PreludeNoBlock, Self::PreludeBlock>, ParseError<'i, Self::Error>>
{
use ::cssparser::AtRuleType::WithoutBlock;
match_ignore_ascii_case!
{
&name,
"charset" =>
{
Err(ParseError::Custom(CustomParseError::UnexpectedCharsetAtRule))
}
"import" =>
{
if self.state > State::Imports
{
return Err(ParseError::Custom(CustomParseError::AtRuleImportMustBeBeforeAnyRuleExceptAtRuleCharset));
}
Ok(WithoutBlock(CssRule::Import(self.parseImportAtRule(input)?)))
}
"namespace" =>
{
if self.state > State::Namespaces
{
return Err(ParseError::Custom(CustomParseError::AtRuleNamespaceMustBeBeforeAnyRuleExceptAtRuleCharsetAndAtRuleImport));
}
Ok(WithoutBlock(CssRule::Namespace(self.parseNamespaceAtRule(input)?)))
}
_ =>
{
if self.state > State::Body
{
self.state = State::Invalid;
return Err(ParseError::Custom(CustomParseError::InvalidParseState));
}
self.state = State::Body;
let mut nested = self.nested();
<NestedRuleParser as AtRuleParser>::parse_prelude(&mut nested, name.clone(), input)
}
}
}
#[inline]
fn rule_without_block(&mut self, prelude: Self::AtRule) -> Self::AtRule
{
use self::State::*;
use self::CssRule::*;
match prelude
{
Import(..) => { self.state = Imports },
Namespace(..) => { self.state = Namespaces },
_ =>
{
}
}
prelude
}
#[inline]
fn parse_block<'t>(&mut self, prelude: Self::PreludeBlock, input: &mut Parser<'i, 't>) -> Result<Self::AtRule, ParseError<'i, Self::Error>>
{
let result =
{
let mut nested = self.nested();
<NestedRuleParser as AtRuleParser>::parse_block(&mut nested, prelude, input)
};
match result
{
Ok(rule) =>
{
self.state = State::Body;
Ok(rule)
}
Err(error) => Err(error),
}
}
}
impl<'i> QualifiedRuleParser<'i> for TopLevelRuleParser
{
type Prelude = QualifiedRuleParserPrelude;
type QualifiedRule = CssRule;
type Error = CustomParseError<'i>;
#[inline]
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) -> Result<Self::Prelude, ParseError<'i, Self::Error>>
{
let mut nested = self.nested();
<NestedRuleParser as QualifiedRuleParser>::parse_prelude(&mut nested, input)
}
#[inline]
fn parse_block<'t>(&mut self, prelude: Self::Prelude, input: &mut Parser<'i, 't>) -> Result<Self::QualifiedRule, ParseError<'i, Self::Error>>
{
let result =
{
let mut nested = self.nested();
<NestedRuleParser as QualifiedRuleParser>::parse_block(&mut nested, prelude, input)
};
match result
{
Ok(rule) =>
{
self.state = State::Body;
Ok(rule)
}
Err(error) => Err(error),
}
}
}
impl TopLevelRuleParser
{
#[inline(always)]
fn nested<'a>(&'a self) -> NestedRuleParser<'a>
{
NestedRuleParser
{
context: &self.context,
namespaces: self.namespaces.clone(),
}
}
#[inline(always)]
fn parseImportAtRule<'i, 't>(&self, input: &mut Parser<'i, 't>) -> Result<ImportAtRule, ParseError<'i, CustomParseError<'i>>>
{
Ok
(
ImportAtRule
{
url: SpecifiedUrl(input.expect_url_or_string()?.as_ref().to_owned()),
media_list: MediaList::parse_media_query_list(&self.context, input, false)?,
}
)
}
#[inline(always)]
fn parseNamespaceAtRule<'i, 't>(&mut self, input: &mut Parser<'i, 't>) -> Result<NamespaceAtRule, ParseError<'i, CustomParseError<'i>>>
{
let prefix: Result<_, ParseError<CustomParseError>> = input.try(|i|
{
let ident: &CowRcStr = i.expect_ident()?;
Ok(NamespacePrefix(Atom::from(ident)))
});
let prefix = prefix.ok();
let url = match input.expect_url_or_string()
{
Ok(url_or_string) => NamespaceUrl(Atom::from(url_or_string)),
Err(BasicParseError::UnexpectedToken(token)) => return Err(ParseError::Custom(CustomParseError::UnexpectedTokenForAtNamespaceRuleNamespaceValue(token.clone()))),
Err(error) => return Err(ParseError::Basic(error)),
};
Rc::get_mut(&mut self.namespaces).expect("@namespace rules are parsed before css selectors so no other references to self.namespaces should exist").update(prefix.as_ref(), &url);
Ok
(
NamespaceAtRule
{
prefix,
url,
}
)
}
}