toasty_core/stmt/expr_project.rs
1use crate::stmt::ExprArg;
2
3use super::{Expr, Projection};
4
5/// Projects a field or element from a base expression.
6///
7/// A [projection] extracts a nested value from a record, tuple, or other
8/// composite type using a path of field indices.
9///
10/// # Examples
11///
12/// ```text
13/// project(record, [0]) // extracts the first field
14/// project(record, [1, 2]) // extracts field 1, then field 2
15/// ```
16///
17/// [projection]: https://en.wikipedia.org/wiki/Projection_(relational_algebra)
18#[derive(Debug, Clone, PartialEq)]
19pub struct ExprProject {
20 /// The expression to project from.
21 pub base: Box<Expr>,
22
23 /// The path specifying which field(s) to extract.
24 pub projection: Projection,
25}
26
27impl Expr {
28 /// Creates a projection expression that extracts a field from `base`
29 /// using the given projection path.
30 pub fn project(base: impl Into<Self>, projection: impl Into<Projection>) -> Self {
31 ExprProject {
32 base: Box::new(base.into()),
33 projection: projection.into(),
34 }
35 .into()
36 }
37
38 /// Shorthand for `Expr::project(Expr::arg(expr_arg), projection)`.
39 pub fn arg_project(expr_arg: impl Into<ExprArg>, projection: impl Into<Projection>) -> Self {
40 Self::project(Self::arg(expr_arg), projection)
41 }
42
43 /// Returns `true` if this expression is a projection.
44 pub fn is_project(&self) -> bool {
45 matches!(self, Self::Project(..))
46 }
47
48 /// Returns a reference to the inner [`ExprProject`] if this is a
49 /// projection, or `None` otherwise.
50 pub fn as_project(&self) -> Option<&ExprProject> {
51 match self {
52 Self::Project(expr_project) => Some(expr_project),
53 _ => None,
54 }
55 }
56
57 /// Returns a reference to the inner [`ExprProject`].
58 ///
59 /// # Panics
60 ///
61 /// Panics if `self` is not `Expr::Project`.
62 #[track_caller]
63 pub fn as_project_unwrap(&self) -> &ExprProject {
64 self.as_project()
65 .unwrap_or_else(|| panic!("expected Expr::Project; actual={self:#?}"))
66 }
67}
68
69impl ExprProject {}
70
71impl From<ExprProject> for Expr {
72 fn from(value: ExprProject) -> Self {
73 Self::Project(value)
74 }
75}