1use vortex_error::VortexExpect;
5use vortex_error::VortexResult;
6
7use crate::AnyCanonical;
8use crate::ArrayRef;
9use crate::Canonical;
10use crate::CanonicalView;
11use crate::Executable;
12use crate::ExecutionCtx;
13use crate::IntoArray;
14use crate::array::ArrayView;
15use crate::arrays::Constant;
16use crate::arrays::ConstantArray;
17use crate::dtype::DType;
18use crate::matcher::Matcher;
19use crate::scalar::Scalar;
20
21pub enum Columnar {
27 Canonical(Canonical),
29 Constant(ConstantArray),
31}
32
33impl Columnar {
34 pub fn constant<S: Into<Scalar>>(scalar: S, len: usize) -> Self {
36 Columnar::Constant(ConstantArray::new(scalar.into(), len))
37 }
38
39 pub fn len(&self) -> usize {
41 match self {
42 Columnar::Canonical(canonical) => canonical.len(),
43 Columnar::Constant(constant) => constant.len(),
44 }
45 }
46
47 pub fn is_empty(&self) -> bool {
49 self.len() == 0
50 }
51
52 pub fn dtype(&self) -> &DType {
54 match self {
55 Columnar::Canonical(canonical) => canonical.dtype(),
56 Columnar::Constant(constant) => constant.dtype(),
57 }
58 }
59}
60
61impl IntoArray for Columnar {
62 fn into_array(self) -> ArrayRef {
63 match self {
64 Columnar::Canonical(canonical) => canonical.into_array(),
65 Columnar::Constant(constant) => constant.into_array(),
66 }
67 }
68}
69
70impl Executable for Columnar {
72 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
73 let result = array.execute_until::<AnyColumnar>(ctx)?;
74 if let Some(constant) = result.as_opt::<Constant>() {
75 Ok(Columnar::Constant(constant.into_owned()))
76 } else {
77 Ok(Columnar::Canonical(
78 result
79 .as_opt::<AnyCanonical>()
80 .map(Canonical::from)
81 .vortex_expect("execute_until::<AnyColumnar> must return a columnar array"),
82 ))
83 }
84 }
85}
86
87pub enum ColumnarView<'a> {
88 Canonical(CanonicalView<'a>),
89 Constant(ArrayView<'a, Constant>),
90}
91
92pub struct AnyColumnar;
93impl Matcher for AnyColumnar {
94 type Match<'a> = ColumnarView<'a>;
95
96 fn try_match<'a>(array: &'a ArrayRef) -> Option<Self::Match<'a>> {
97 if let Some(constant) = array.as_opt::<Constant>() {
98 Some(ColumnarView::Constant(constant))
99 } else {
100 array.as_opt::<AnyCanonical>().map(ColumnarView::Canonical)
101 }
102 }
103}