antecedent_core/query/target.rs
1//! Query submodule.
2//!
3//! SPDX-License-Identifier: MIT OR Apache-2.0
4
5use std::sync::Arc;
6
7use crate::ids::{DistributionRef, EnvironmentId};
8
9use super::error::QueryError;
10
11/// Portable predicate over units/rows.
12///
13/// [`Self::Rows`] is evaluated directly; [`Self::Named`] resolves through
14/// [`super::PopulationRegistry`].
15#[derive(Clone, Debug, Eq, PartialEq, Hash)]
16#[non_exhaustive]
17pub enum PredicateExpr {
18 /// Registry-named predicate resolved by callers.
19 Named(Arc<str>),
20 /// Explicit row indices into the bound tabular view.
21 Rows(Arc<[usize]>),
22}
23
24impl PredicateExpr {
25 /// Named registry predicate.
26 #[must_use]
27 pub fn named(id: impl Into<Arc<str>>) -> Self {
28 Self::Named(id.into())
29 }
30
31 /// Explicit row subset.
32 #[must_use]
33 pub fn rows(rows: impl Into<Arc<[usize]>>) -> Self {
34 Self::Rows(rows.into())
35 }
36
37 /// Validate predicate geometry (non-empty name / rows).
38 ///
39 /// # Errors
40 ///
41 /// Empty name or empty row set.
42 pub fn validate(&self) -> Result<(), QueryError> {
43 match self {
44 Self::Named(name) => {
45 if name.is_empty() {
46 Err(QueryError::EmptyPredicateName)
47 } else {
48 Ok(())
49 }
50 }
51 Self::Rows(rows) => {
52 if rows.is_empty() {
53 Err(QueryError::EmptyPopulationRows)
54 } else {
55 Ok(())
56 }
57 }
58 }
59 }
60}
61
62/// Target population for an effect query.
63#[derive(Clone, Debug, Eq, PartialEq, Hash)]
64#[non_exhaustive]
65pub enum TargetPopulation {
66 /// All observed units.
67 AllObserved,
68 /// Treated units only.
69 Treated,
70 /// Untreated units only.
71 Untreated,
72 /// Environment-restricted population.
73 Environment(EnvironmentId),
74 /// Predicate-selected units ([`PredicateExpr`]).
75 Predicate(PredicateExpr),
76 /// Custom target distribution handle (weights via [`super::PopulationRegistry`]).
77 CustomDistribution(DistributionRef),
78}
79
80impl TargetPopulation {
81 /// Validate population geometry for Planned / structured variants.
82 ///
83 /// # Errors
84 ///
85 /// Empty predicate name or empty row set.
86 pub fn validate(&self) -> Result<(), QueryError> {
87 match self {
88 Self::Predicate(expr) => expr.validate(),
89 Self::AllObserved
90 | Self::Treated
91 | Self::Untreated
92 | Self::Environment(_)
93 | Self::CustomDistribution(_) => Ok(()),
94 }
95 }
96}