#[non_exhaustive]pub enum Selection {
False,
True,
All(Box<Selection>),
First(Box<Selection>),
Range(Range, Box<Selection>),
Label(Vec<LabelKey>, Box<Selection>),
Any(Box<Selection>),
Intersection(Box<Selection>, Box<Selection>),
Union(Box<Selection>, Box<Selection>),
}
Expand description
An algebra for expressing node selection.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
False
A selection that never matches any node.
True
A selection that always matches any node.
All(Box<Selection>)
Selects all values along the current dimension, continuing with the given selection.
First(Box<Selection>)
Selects the first value along the current dimension for which applying the inner selection yields any results.
Range(Range, Box<Selection>)
Selects values within a given range along the current dimension, continuing with the given selection.
Label(Vec<LabelKey>, Box<Selection>)
Selects values based on metadata (i.e., labels) along the current dimension. This provides attribute-based selection.
Any(Box<Selection>)
Selects a random index along the current dimension, continuing with the given selection.
Intersection(Box<Selection>, Box<Selection>)
The intersection (logical AND) of two selections.
Union(Box<Selection>, Box<Selection>)
The union (logical OR) of two selections.
Implementations§
Source§impl Selection
impl Selection
Sourcepub fn eval<'a>(
&self,
opts: &EvalOpts,
slice: &'a Slice,
) -> Result<Box<dyn Iterator<Item = usize> + 'a>, ShapeError>
pub fn eval<'a>( &self, opts: &EvalOpts, slice: &'a Slice, ) -> Result<Box<dyn Iterator<Item = usize> + 'a>, ShapeError>
Lazily evaluates this selection against the given slice
yielding flat indices.
Returns a boxed iterator that produces indices of elements
matching the selection expression when evaluated over slice
.
§Lifetimes
The returned iterator borrows slice
because the internal
iterators are implemented as closures that capture
&slice
in their environment. Evaluation is lazy, so these
closures dereference slice
each time a coordinate is
visited. The 'a
lifetime ensures that the iterator cannot
outlive the slice
it reads from.
§Why Box<dyn Iterator>
The selection algebra supports multiple recursive strategies
(All
, Range
, Intersection
, etc.) that return different
iterator types (e.g. Selection::True
=>
std::iter::once(...)
, Selection::False
=>
std::iter::empty()
). Returning impl Iterator
is not
feasible because the precise type depends on dynamic selection
structure. Boxing erases this variability and allows a uniform
return type.
§Canonical handling of 0-dimensional slices
A Slice
with zero dimensions represents the empty product
∏_{i=1}^{0} Xᵢ
, which has exactly one element: the empty
tuple. To ensure that evaluation behaves uniformly across
dimensions, we canonically embed the 0-dimensional case into a
1-dimensional slice of extent 1. That is, we reinterpret the
0D slice as Slice::new(offset, [1], [1])
, which is
semantically equivalent and enables evaluation to proceed
through the normal recursive machinery without special-casing.
The result is that selection expressions are always evaluated
over a slice with at least one dimension, and uniform logic
applies.
Sourcepub fn is_equivalent_to_true(sel: &Selection) -> bool
pub fn is_equivalent_to_true(sel: &Selection) -> bool
Returns true
if this selection is equivalent to True
under
the algebra.
In the selection algebra, All(True)
is considered equivalent
to True
, and this identity extends recursively. For example:
All(True)
≡True
All(All(True))
≡True
All(All(All(True)))
≡True
This method checks whether the selection is structurally identical to True, possibly wrapped in one or more All(…) layers. It does not perform full normalization—only structural matching sufficient to recognize this identity.
Used to detect when a selection trivially selects all elements at all levels.
§Limitations
This is a syntactic check only. It does not recognize semantically equivalent expressions such as:
Union(True, True)
All(Union(True, False))
- A union of all singleton ranges covering the full space
For a semantic check, use evaluation against a known slice.
Sourcepub fn contains(&self, coords: &[usize]) -> bool
pub fn contains(&self, coords: &[usize]) -> bool
Evaluates whether the specified coordinates are part of the selection. Returns true if they are, false otherwise.
Example: let selection = union( range(0..2, range(0..1, range(0..2, true_()))), range(0..2, range(1..2, range(0..2, true_()))), );
assert!(selection.contains(&[0, 0, 1])); assert!(!selection.contains(&[2, 0, 1]));
Sourcepub fn reduce_intersection(self, b: Selection) -> Selection
pub fn reduce_intersection(self, b: Selection) -> Selection
Simplifies the intersection of two Selection
expressions.
Applies short-circuit logic to avoid constructing redundant or degenerate intersections:
- If either side is
False
, the result isFalse
. - If either side is
True
, the result is the other side. - Otherwise, constructs an explicit
Intersection
.
This is required during routing to make progress when
evaluating intersections. Without this reduction, routing may
stall — for example, in intersections like Intersection(True, X)
, which should simplify to X
.
Sourcepub fn fold<S>(&self) -> Swhere
S: SelectionSYM,
pub fn fold<S>(&self) -> Swhere
S: SelectionSYM,
Recursively folds the Selection
into an abstract syntax via
the SelectionSYM
interface.
This method structurally traverses the Selection
tree and
reconstructs it using the operations provided by the
SelectionSYM
trait. It is typically used to reify a
Selection
into alternate forms, such as pretty-printers.
§Type Parameters
S
: An implementation of theSelectionSYM
trait, providing the constructors for the target representation.
Sourcepub fn difference<'a>(
&self,
opts: &EvalOpts,
slice: &'a Slice,
exclusions: &'a HashSet<usize>,
) -> Result<impl Iterator<Item = usize> + use<'a>, ShapeError>
pub fn difference<'a>( &self, opts: &EvalOpts, slice: &'a Slice, exclusions: &'a HashSet<usize>, ) -> Result<impl Iterator<Item = usize> + use<'a>, ShapeError>
Iterator over indices selected by self
and not in
exclusions
.
Evaluates the selection against slice
using opts
, then
filters out any indices present in the exclusion set.
Evaluation is lazy and streaming; the exclusion set is used
directly for fast membership checks.
Sourcepub fn without(
&self,
slice: &Slice,
exclusions: &HashSet<usize>,
) -> Result<Selection, ShapeError>
pub fn without( &self, slice: &Slice, exclusions: &HashSet<usize>, ) -> Result<Selection, ShapeError>
Calculate a new Selection
that excludes the specified flat
ranks.
This computes self \ exclusions
by evaluating self
,
removing the given ranks, and reconstructing a Selection
that selects exactly the remaining elements.
The result is a concrete, structurally uniform expression with predictable construction order and exact correspondence to the surviving ranks.
Sourcepub fn of_ranks(
slice: &Slice,
ranks: &BTreeSet<usize>,
) -> Result<Selection, SliceError>
pub fn of_ranks( slice: &Slice, ranks: &BTreeSet<usize>, ) -> Result<Selection, SliceError>
Converts a set of flat indices into a symbolic Selection
expression over the given slice
. Returns an error if any index
is invalid.
Each flat index is converted into coordinates using
slice.coordinates
, then folded into a nested chain of singleton
ranges. The resulting selection evaluates exactly to the input
indices.
The selections are combined left-associatively using union
, but
since union
is associative, the grouping does not affect
correctness.
The input BTreeSet
ensures:
- all indices are unique (no redundant singleton ranges),
- the resulting selection has a stable, deterministic structure,
- and iteration proceeds in ascending order, which helps produce predictable routing trees and consistent test results.
This choice avoids an explicit sort and makes downstream behavior more reproducible and auditable.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Selection
impl<'de> Deserialize<'de> for Selection
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<Selection, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<Selection, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl From<NormalizedSelection> for Selection
impl From<NormalizedSelection> for Selection
Source§fn from(norm: NormalizedSelection) -> Selection
fn from(norm: NormalizedSelection) -> Selection
Converts the normalized form back into a standard Selection
.
Logical semantics are preserved, but normalized shape (e.g., set-based unions and intersections) is reconstructed as left-associated binary trees.
Source§impl SelectionSYM for Selection
impl SelectionSYM for Selection
Source§fn all(selection: Selection) -> Selection
fn all(selection: Selection) -> Selection
Source§fn first(selection: Selection) -> Selection
fn first(selection: Selection) -> Selection
Source§fn range<R>(range: R, selection: Selection) -> Selection
fn range<R>(range: R, selection: Selection) -> Selection
Source§fn label<L>(labels: Vec<L>, selection: Selection) -> Selection
fn label<L>(labels: Vec<L>, selection: Selection) -> Selection
Source§fn any(selection: Selection) -> Selection
fn any(selection: Selection) -> Selection
Source§impl Serialize for Selection
impl Serialize for Selection
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for Selection
impl RefUnwindSafe for Selection
impl Send for Selection
impl Sync for Selection
impl Unpin for Selection
impl UnwindSafe for Selection
Blanket Implementations§
§impl<T> AnySync for T
impl<T> AnySync for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<A, M> Handler<IndexedErasedUnbound<M>> for A
impl<A, M> Handler<IndexedErasedUnbound<M>> for A
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more