toasty_core/stmt/expr_variant.rs
1use crate::schema::app::VariantId;
2
3use super::Expr;
4
5/// Selects a variant of an embedded enum value.
6///
7/// Evaluates to the payload of `base` when it holds `variant`: the record of
8/// the variant's fields, in declaration order, without the discriminant.
9/// Projections applied to it index that record with the variant's local
10/// field positions, so `project(variant(owner, Human), [1])` is the second
11/// field of `Owner::Human`, whatever the enum's storage layout.
12///
13/// The selection carries no check of its own. A predicate over a selection
14/// must also require the variant; statement normalization in the engine
15/// conjoins an [`is_variant`](Expr::is_variant) check for every selection a
16/// predicate's operands reach. Lowering resolves the selection to the
17/// variant's column expressions and the guard to a discriminant comparison;
18/// the node never reaches a driver.
19///
20/// # Examples
21///
22/// ```text
23/// variant(owner, Owner::Human) // the Human payload
24/// project(variant(owner, Owner::Human), [0]) // its first field
25/// ```
26#[derive(Debug, Clone, PartialEq)]
27pub struct ExprVariant {
28 /// Expression evaluating to an enum value.
29 pub base: Box<Expr>,
30
31 /// The variant whose payload is selected.
32 pub variant: VariantId,
33}
34
35impl Expr {
36 /// Creates a variant selection: the payload of `base` as `variant`.
37 pub fn variant(base: impl Into<Self>, variant: VariantId) -> Self {
38 ExprVariant {
39 base: Box::new(base.into()),
40 variant,
41 }
42 .into()
43 }
44
45 /// Returns a reference to the inner [`ExprVariant`] if this is a variant
46 /// selection, or `None` otherwise.
47 pub fn as_variant(&self) -> Option<&ExprVariant> {
48 match self {
49 Self::Variant(expr_variant) => Some(expr_variant),
50 _ => None,
51 }
52 }
53}
54
55impl From<ExprVariant> for Expr {
56 fn from(value: ExprVariant) -> Self {
57 Self::Variant(value)
58 }
59}