minarrow/enums/
value.rs

1//! # **Value Module** - *Single *Whole Type Universe* Value Container*
2//!
3//! Contains the `Value` enum, a unified container for any Minarrow-supported data structure.
4//!  
5//! ## Description
6//! -Encapsulates scalars, arrays, tables, views, chunked collections, bitmasks, fields,
7//! matrices, cubes, nested values, and custom user-defined types.  
8//!  
9//! ## Purpose
10//! Used to create a global type universe for function signatures and dispatch, enabling
11//! constructs like `Result<Value, MinarrowError>` without restricting the contained type.  
12//!  
13//! ## Supports:
14//! - recursive containers (boxed, arced, tuples, vectors)
15//! - `From`/`TryFrom` conversions for safe extraction
16//! - equality comparison across all variants, including custom values
17//! - custom extension types if needed
18
19#[cfg(feature = "cube")]
20use crate::Cube;
21#[cfg(feature = "matrix")]
22use crate::Matrix;
23#[cfg(feature = "scalar_type")]
24use crate::Scalar;
25use crate::{
26    Array, Bitmask, Field, FieldArray,Table,
27    enums::error::MinarrowError, traits::custom_value::CustomValue,
28};
29use std::convert::TryFrom;
30use std::{convert::From, sync::Arc};
31
32#[cfg(feature = "views")]
33use crate::{NumericArrayV, TextArrayV};
34
35#[cfg(feature = "views")]
36#[cfg(feature = "datetime")]
37use crate::TemporalArrayV;
38
39#[cfg(feature = "chunked")]
40use crate::{SuperArray, SuperTable};
41
42#[cfg(feature = "views")]
43use crate::{ArrayV, TableV, BitmaskV};
44
45#[cfg(all(feature = "chunked", feature="views"))]
46use crate::{SuperArrayV, SuperTableV};
47
48/// # Value
49/// 
50/// Unified value enum representing any supported data structure.
51///
52/// ## Details
53/// - Wraps scalar values, arrays, array windows, full tables, or table windows
54/// under a single type for function signatures and downstream dispatch.
55/// - This can be useful when you need a global *type universe*.
56/// - It is not part of the `Arrow` specification, but is useful
57/// because of the flexibility it adds unifying all types to a single one.
58/// For example, to return `Result<Value, Error>`, particularly in engine contexts.
59/// - It's enabled optionally via the `value_type` feature.
60///
61/// ## Usage
62/// You can also use it to hold a custom type under the `Custom` entry.
63/// As long as the object implements `Debug`, `Clone`, and `PartialEq`,
64/// remains `Send + Sync`, and implements `Any` it can be stored in `Value::Custom`.
65/// `Any` is implemented automatically for all Rust types with a `'static` lifetime.
66#[derive(Debug, Clone)]
67pub enum Value {
68    #[cfg(feature = "scalar_type")]
69    Scalar(Scalar),
70    Array(Array),
71    #[cfg(feature = "views")]
72    ArrayView(ArrayV),
73    Table(Table),
74    #[cfg(feature = "views")]
75    TableView(TableV),
76    #[cfg(all(feature = "views", feature="views"))]
77    NumericArrayView(NumericArrayV),
78    #[cfg(all(feature = "views", feature="views"))]
79    TextArrayView(TextArrayV),
80    #[cfg(all(feature = "views", feature="datetime"))]
81    TemporalArrayView(TemporalArrayV),
82    Bitmask(Bitmask),
83    #[cfg(feature = "views")]
84    BitmaskView(BitmaskV),
85    #[cfg(feature = "chunked")]
86    ChunkedArray(SuperArray),
87    #[cfg(all(feature = "chunked", feature="views"))]
88    ChunkedArrayView(SuperArrayV),
89    #[cfg(feature = "chunked")]
90    ChunkedTable(SuperTable),
91    #[cfg(all(feature = "chunked", feature="views"))]
92    ChunkedTableView(SuperTableV),
93    FieldArray(FieldArray),
94    Field(Field),
95    #[cfg(feature = "matrix")]
96    Matrix(Matrix),
97    #[cfg(feature = "cube")]
98    Cube(Cube),
99    VecValue(Vec<Value>),
100    // For recursive
101    BoxValue(Box<Value>),
102    ArcValue(Arc<Value>),
103    Tuple2((Box<Value>, Box<Value>)),
104    Tuple3((Box<Value>, Box<Value>, Box<Value>)),
105    Tuple4((Box<Value>, Box<Value>, Box<Value>, Box<Value>)),
106    Tuple5((Box<Value>, Box<Value>, Box<Value>, Box<Value>, Box<Value>)),
107    Tuple6(
108        (
109            Box<Value>,
110            Box<Value>,
111            Box<Value>,
112            Box<Value>,
113            Box<Value>,
114            Box<Value>,
115        ),
116    ),
117
118    /// Arbitrary user or library-defined payload.
119    ///
120    /// As long as the object implements `Debug`, `Clone`, and `PartialEq`,
121    /// remains `Send + Sync`, and implements `Any` it can be stored in `Value::Custom`.
122    /// `Any` is implemented automatically for all Rust types with a `'static` lifetime.
123    ///
124    /// Borrowed values **cannot** be used directly.
125    /// These must be wrapped in `Arc` or otherwise promoted to `'static` to
126    /// store inside `Value`.
127    ///
128    /// It's recommended that creators also implement `From` and `TryFrom`.
129    Custom(Arc<dyn CustomValue>),
130}
131
132/// Implements `PartialEq` for `Value`
133///
134/// This includes special handling for the `Custom` type.
135impl PartialEq for Value {
136    fn eq(&self, other: &Self) -> bool {
137        use Value::*;
138        match (self, other) {
139            #[cfg(feature = "scalar_type")]
140            (Scalar(a), Scalar(b)) => a == b,
141            (Array(a), Array(b)) => a == b,
142            #[cfg(feature = "views")]
143            (ArrayView(a), ArrayView(b)) => a == b,
144            (Table(a), Table(b)) => a == b,
145            #[cfg(feature = "views")]
146            (TableView(a), TableView(b)) => a == b,
147            #[cfg(feature = "views")]
148            (NumericArrayView(a), NumericArrayView(b)) => a == b,
149            #[cfg(feature = "views")]
150            (TextArrayView(a), TextArrayView(b)) => a == b,
151            #[cfg(all(feature = "views", feature = "datetime"))]
152            (TemporalArrayView(a), TemporalArrayView(b)) => a == b,
153            (Bitmask(a), Bitmask(b)) => a == b,
154            #[cfg(feature = "views")]
155            (BitmaskView(a), BitmaskView(b)) => a == b,
156            #[cfg(feature = "chunked")]
157            (ChunkedArray(a), ChunkedArray(b)) => a == b,
158            #[cfg(all(feature = "chunked", feature = "views"))]
159            (ChunkedArrayView(a), ChunkedArrayView(b)) => a == b,
160            (FieldArray(a), FieldArray(b)) => a == b,
161            (Field(a), Field(b)) => a == b,
162            #[cfg(feature = "matrix")]
163            (Matrix(a), Matrix(b)) => a == b,
164            #[cfg(feature = "cube")]
165            (Cube(a), Cube(b)) => a == b,
166            (Custom(a), Custom(b)) => a.eq_box(&**b),
167            (VecValue(a), VecValue(b)) => a == b,
168            (BoxValue(a), BoxValue(b)) => a == b,
169            (ArcValue(a), ArcValue(b)) => a == b,
170            (Tuple2(a), Tuple2(b)) => a.0 == b.0 && a.1 == b.1,
171            (Tuple3(a), Tuple3(b)) => a.0 == b.0 && a.1 == b.1 && a.2 == b.2,
172            (Tuple4(a), Tuple4(b)) => a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3,
173            (Tuple5(a), Tuple5(b)) => {
174                a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3 && a.4 == b.4
175            }
176            (Tuple6(a), Tuple6(b)) => {
177                a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3 && a.4 == b.4 && a.5 == b.5
178            }
179            _ => false,
180        }
181    }
182}
183
184/// Macro to implement `From` for `Value` variants.
185macro_rules! impl_value_from {
186    ($variant:ident: $t:ty) => {
187        impl From<$t> for Value {
188            #[inline]
189            fn from(v: $t) -> Self {
190                Value::$variant(v)
191            }
192        }
193    };
194}
195
196/// Macro to implement `TryFrom<Value>` for `Value` variants.
197macro_rules! impl_tryfrom_value {
198    ($variant:ident: $t:ty) => {
199        impl TryFrom<Value> for $t {
200            type Error = MinarrowError;
201            fn try_from(v: Value) -> Result<Self, Self::Error> {
202                match v {
203                    Value::$variant(inner) => Ok(inner),
204                    _ => Err(MinarrowError::TypeError {
205                        from: "Value",
206                        to: stringify!($t),
207                        message: Some("Value type mismatch".to_owned()),
208                    }),
209                }
210            }
211        }
212    };
213}
214
215// Scalars
216#[cfg(feature = "scalar_type")]
217impl_value_from!(Scalar: Scalar);
218#[cfg(feature = "scalar_type")]
219impl_tryfrom_value!(Scalar: Scalar);
220
221// Array-like types
222impl_value_from!(Array: Array);
223#[cfg(feature = "views")]
224impl_value_from!(ArrayView: ArrayV);
225impl_value_from!(Table: Table);
226#[cfg(feature = "views")]
227impl_value_from!(TableView: TableV);
228impl_value_from!(Bitmask: Bitmask);
229#[cfg(feature = "views")]
230impl_value_from!(BitmaskView: BitmaskV);
231impl_value_from!(FieldArray: FieldArray);
232impl_value_from!(Field: Field);
233
234#[cfg(feature = "views")]
235impl_value_from!(NumericArrayView: NumericArrayV);
236#[cfg(feature = "views")]
237impl_value_from!(TextArrayView: TextArrayV);
238#[cfg(all(feature = "datetime", feature = "views"))]
239impl_value_from!(TemporalArrayView: TemporalArrayV);
240
241#[cfg(feature = "chunked")]
242impl_value_from!(ChunkedArray: SuperArray);
243#[cfg(all(feature = "chunked", feature="views"))]
244impl_value_from!(ChunkedArrayView: SuperArrayV);
245
246#[cfg(feature = "matrix")]
247impl_value_from!(Matrix: Matrix);
248#[cfg(feature = "cube")]
249impl_value_from!(Cube: Cube);
250
251// TryFrom for Array-like types
252impl_tryfrom_value!(Array: Array);
253#[cfg(feature = "views")]
254impl_tryfrom_value!(ArrayView: ArrayV);
255impl_tryfrom_value!(Table: Table);
256#[cfg(feature = "views")]
257impl_tryfrom_value!(TableView: TableV);
258impl_tryfrom_value!(Bitmask: Bitmask);
259#[cfg(feature = "views")]
260impl_tryfrom_value!(BitmaskView: BitmaskV);
261impl_tryfrom_value!(FieldArray: FieldArray);
262impl_tryfrom_value!(Field: Field);
263
264#[cfg(feature = "views")]
265impl_tryfrom_value!(NumericArrayView: NumericArrayV);
266#[cfg(feature = "views")]
267impl_tryfrom_value!(TextArrayView: TextArrayV);
268#[cfg(all(feature = "datetime", feature = "views"))]
269impl_tryfrom_value!(TemporalArrayView: TemporalArrayV);
270
271#[cfg(feature = "chunked")]
272impl_tryfrom_value!(ChunkedArray: SuperArray);
273#[cfg(all(feature = "chunked", feature = "views"))]
274impl_tryfrom_value!(ChunkedArrayView: SuperArrayV);
275
276#[cfg(feature = "matrix")]
277impl_tryfrom_value!(Matrix: Matrix);
278#[cfg(feature = "cube")]
279impl_tryfrom_value!(Cube: Cube);
280
281// Recursive containers
282impl From<Vec<Value>> for Value {
283    fn from(v: Vec<Value>) -> Self {
284        Value::VecValue(v)
285    }
286}
287
288impl From<(Value, Value)> for Value {
289    fn from(v: (Value, Value)) -> Self {
290        Value::Tuple2((Box::new(v.0), Box::new(v.1)))
291    }
292}
293
294impl From<(Value, Value, Value)> for Value {
295    fn from(v: (Value, Value, Value)) -> Self {
296        Value::Tuple3((Box::new(v.0), Box::new(v.1), Box::new(v.2)))
297    }
298}
299
300impl From<(Value, Value, Value, Value)> for Value {
301    fn from(v: (Value, Value, Value, Value)) -> Self {
302        Value::Tuple4((Box::new(v.0), Box::new(v.1), Box::new(v.2), Box::new(v.3)))
303    }
304}
305
306impl From<(Value, Value, Value, Value, Value)> for Value {
307    fn from(v: (Value, Value, Value, Value, Value)) -> Self {
308        Value::Tuple5((
309            Box::new(v.0),
310            Box::new(v.1),
311            Box::new(v.2),
312            Box::new(v.3),
313            Box::new(v.4),
314        ))
315    }
316}
317
318impl From<(Value, Value, Value, Value, Value, Value)> for Value {
319    fn from(v: (Value, Value, Value, Value, Value, Value)) -> Self {
320        Value::Tuple6((
321            Box::new(v.0),
322            Box::new(v.1),
323            Box::new(v.2),
324            Box::new(v.3),
325            Box::new(v.4),
326            Box::new(v.5),
327        ))
328    }
329}
330
331// TryFrom for recursive containers
332impl TryFrom<Value> for Vec<Value> {
333    type Error = MinarrowError;
334    fn try_from(v: Value) -> Result<Self, Self::Error> {
335        match v {
336            Value::VecValue(inner) => Ok(inner),
337            _ => Err(MinarrowError::TypeError {
338                from: "Value",
339                to: "Vec<Value>",
340                message: Some("Expected VecValue variant".to_owned()),
341            }),
342        }
343    }
344}
345
346impl TryFrom<Value> for (Value, Value) {
347    type Error = MinarrowError;
348    fn try_from(v: Value) -> Result<Self, Self::Error> {
349        match v {
350            Value::Tuple2((a, b)) => Ok((*a, *b)),
351            _ => Err(MinarrowError::TypeError {
352                from: "Value",
353                to: "(Value, Value)",
354                message: Some("Expected Tuple2 variant".to_owned()),
355            }),
356        }
357    }
358}
359
360impl TryFrom<Value> for (Value, Value, Value) {
361    type Error = MinarrowError;
362    fn try_from(v: Value) -> Result<Self, Self::Error> {
363        match v {
364            Value::Tuple3((a, b, c)) => Ok((*a, *b, *c)),
365            _ => Err(MinarrowError::TypeError {
366                from: "Value",
367                to: "(Value, Value, Value)",
368                message: Some("Expected Tuple3 variant".to_owned()),
369            }),
370        }
371    }
372}
373
374impl TryFrom<Value> for (Value, Value, Value, Value) {
375    type Error = MinarrowError;
376    fn try_from(v: Value) -> Result<Self, Self::Error> {
377        match v {
378            Value::Tuple4((a, b, c, d)) => Ok((*a, *b, *c, *d)),
379            _ => Err(MinarrowError::TypeError {
380                from: "Value",
381                to: "(Value, Value, Value, Value)",
382                message: Some("Expected Tuple4 variant".to_owned()),
383            }),
384        }
385    }
386}
387
388impl TryFrom<Value> for (Value, Value, Value, Value, Value) {
389    type Error = MinarrowError;
390    fn try_from(v: Value) -> Result<Self, Self::Error> {
391        match v {
392            Value::Tuple5((a, b, c, d, e)) => Ok((*a, *b, *c, *d, *e)),
393            _ => Err(MinarrowError::TypeError {
394                from: "Value",
395                to: "(Value, Value, Value, Value, Value)",
396                message: Some("Expected Tuple5 variant".to_owned()),
397            }),
398        }
399    }
400}
401
402impl TryFrom<Value> for (Value, Value, Value, Value, Value, Value) {
403    type Error = MinarrowError;
404    fn try_from(v: Value) -> Result<Self, Self::Error> {
405        match v {
406            Value::Tuple6((a, b, c, d, e, f)) => Ok((*a, *b, *c, *d, *e, *f)),
407            _ => Err(MinarrowError::TypeError {
408                from: "Value",
409                to: "(Value, Value, Value, Value, Value, Value)",
410                message: Some("Expected Tuple6 variant".to_owned()),
411            }),
412        }
413    }
414}