use crate::ast::prelude::*;
#[test]
#[cfg(not(miri))]
fn ast_parse() {
let select = rt::<ast::ExprSelect>(
r#"
select {
_ = a => 0,
_ = b => {},
_ = c => {}
default => ()
}
"#,
);
assert_eq!(4, select.branches.len());
assert!(matches!(
select.branches.get(1),
Some(&(ast::ExprSelectBranch::Pat(..), Some(..)))
));
assert!(matches!(
select.branches.get(2),
Some(&(ast::ExprSelectBranch::Pat(..), None))
));
assert!(matches!(
select.branches.get(3),
Some(&(ast::ExprSelectBranch::Default(..), None))
));
}
#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
#[non_exhaustive]
pub struct ExprSelect {
#[rune(iter)]
pub attributes: Vec<ast::Attribute>,
pub select: T![select],
pub open: T!['{'],
#[rune(iter)]
pub branches: Vec<(ExprSelectBranch, Option<T![,]>)>,
pub close: T!['}'],
}
impl ExprSelect {
pub(crate) fn parse_with_attributes(
p: &mut Parser<'_>,
attributes: Vec<ast::Attribute>,
) -> Result<Self> {
let select = p.parse()?;
let open = p.parse()?;
let mut branches = Vec::new();
while !p.peek::<T!['}']>()? {
let branch = ExprSelectBranch::parse(p)?;
let comma = p.parse::<Option<T![,]>>()?;
let is_end = ast::utils::is_block_end(branch.expr(), comma.as_ref());
branches.try_push((branch, comma))?;
if is_end {
break;
}
}
let close = p.parse()?;
Ok(Self {
attributes,
select,
open,
branches,
close,
})
}
}
expr_parse!(Select, ExprSelect, "select expression");
#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
#[non_exhaustive]
#[allow(clippy::large_enum_variant)]
pub enum ExprSelectBranch {
Pat(ExprSelectPatBranch),
Default(ExprDefaultBranch),
}
impl ExprSelectBranch {
pub(crate) fn expr(&self) -> &ast::Expr {
match self {
ExprSelectBranch::Pat(pat) => &pat.body,
ExprSelectBranch::Default(def) => &def.body,
}
}
}
impl Parse for ExprSelectBranch {
fn parse(p: &mut Parser<'_>) -> Result<Self> {
Ok(if p.peek::<T![default]>()? {
Self::Default(p.parse()?)
} else {
Self::Pat(p.parse()?)
})
}
}
#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
#[non_exhaustive]
pub struct ExprSelectPatBranch {
pub pat: ast::Pat,
pub eq: T![=],
pub expr: ast::Expr,
pub rocket: T![=>],
pub body: ast::Expr,
}
#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
#[non_exhaustive]
pub struct ExprDefaultBranch {
pub default: T![default],
pub rocket: T![=>],
pub body: ast::Expr,
}