rune/ast/
expr_select.rs
1use crate::ast::prelude::*;
2
3#[test]
4#[cfg(not(miri))]
5fn ast_parse() {
6 let select = rt::<ast::ExprSelect>(
7 r#"
8 select {
9 _ = a => 0,
10 _ = b => {},
11 _ = c => {}
12 default => ()
13 }
14 "#,
15 );
16
17 assert_eq!(4, select.branches.len());
18 assert!(matches!(
19 select.branches.get(1),
20 Some(&(ast::ExprSelectBranch::Pat(..), Some(..)))
21 ));
22 assert!(matches!(
23 select.branches.get(2),
24 Some(&(ast::ExprSelectBranch::Pat(..), None))
25 ));
26 assert!(matches!(
27 select.branches.get(3),
28 Some(&(ast::ExprSelectBranch::Default(..), None))
29 ));
30}
31
32#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
36#[non_exhaustive]
37pub struct ExprSelect {
38 #[rune(iter)]
40 pub attributes: Vec<ast::Attribute>,
41 pub select: T![select],
43 pub open: T!['{'],
45 #[rune(iter)]
47 pub branches: Vec<(ExprSelectBranch, Option<T![,]>)>,
48 pub close: T!['}'],
50}
51
52impl ExprSelect {
53 pub(crate) fn parse_with_attributes(
55 p: &mut Parser<'_>,
56 attributes: Vec<ast::Attribute>,
57 ) -> Result<Self> {
58 let select = p.parse()?;
59 let open = p.parse()?;
60
61 let mut branches = Vec::new();
62
63 while !p.peek::<T!['}']>()? {
64 let branch = ExprSelectBranch::parse(p)?;
65 let comma = p.parse::<Option<T![,]>>()?;
66 let is_end = ast::utils::is_block_end(branch.expr(), comma.as_ref());
67 branches.try_push((branch, comma))?;
68
69 if is_end {
70 break;
71 }
72 }
73
74 let close = p.parse()?;
75
76 Ok(Self {
77 attributes,
78 select,
79 open,
80 branches,
81 close,
82 })
83 }
84}
85
86expr_parse!(Select, ExprSelect, "select expression");
87
88#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
90#[non_exhaustive]
91#[allow(clippy::large_enum_variant)]
92pub enum ExprSelectBranch {
93 Pat(ExprSelectPatBranch),
95 Default(ExprDefaultBranch),
97}
98
99impl ExprSelectBranch {
100 pub(crate) fn expr(&self) -> &ast::Expr {
102 match self {
103 ExprSelectBranch::Pat(pat) => &pat.body,
104 ExprSelectBranch::Default(def) => &def.body,
105 }
106 }
107}
108
109impl Parse for ExprSelectBranch {
110 fn parse(p: &mut Parser<'_>) -> Result<Self> {
111 Ok(if p.peek::<T![default]>()? {
112 Self::Default(p.parse()?)
113 } else {
114 Self::Pat(p.parse()?)
115 })
116 }
117}
118
119#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
121#[non_exhaustive]
122pub struct ExprSelectPatBranch {
123 pub pat: ast::Pat,
125 pub eq: T![=],
127 pub expr: ast::Expr,
129 pub rocket: T![=>],
131 pub body: ast::Expr,
133}
134
135#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
137#[non_exhaustive]
138pub struct ExprDefaultBranch {
139 pub default: T![default],
141 pub rocket: T![=>],
143 pub body: ast::Expr,
145}