lumni/table/
columns.rs

1use std::any::Any;
2use std::fmt::Debug;
3
4#[derive(Debug, Clone)]
5pub enum TableColumnValue {
6    Int32Column(i32),
7    Uint64Column(u64),
8    FloatColumn(f64),
9    StringColumn(String),
10    OptionalInt32Column(Option<i32>),
11    OptionalUint64Column(Option<u64>),
12    OptionalFloatColumn(Option<f64>),
13    OptionalStringColumn(Option<String>),
14}
15
16pub trait TableColumn: Debug {
17    fn len(&self) -> usize;
18    fn append(&mut self, value: TableColumnValue) -> Result<(), String>;
19    fn as_any(&self) -> &dyn Any;
20}
21
22macro_rules! create_column_types {
23    ($TypeName:ident, $OptionalTypeName:ident, $ValueType:ty) => {
24        #[derive(Debug, Clone)]
25        pub struct $TypeName(pub Vec<$ValueType>);
26
27        #[derive(Debug, Clone)]
28        pub struct $OptionalTypeName(pub Vec<Option<$ValueType>>);
29
30        impl $TypeName {
31            #[allow(dead_code)]
32            pub fn values(&self) -> &[$ValueType] {
33                &self.0
34            }
35        }
36
37        impl $OptionalTypeName {
38            #[allow(dead_code)]
39            pub fn values(&self) -> &[Option<$ValueType>] {
40                &self.0
41            }
42        }
43
44        impl TableColumn for $TypeName {
45            fn len(&self) -> usize {
46                self.0.len()
47            }
48
49            fn append(
50                &mut self,
51                value: TableColumnValue,
52            ) -> Result<(), String> {
53                if let TableColumnValue::$TypeName(val) = value {
54                    self.0.push(val);
55                    Ok(())
56                } else {
57                    Err(format!("Type mismatch for {:?}", value))
58                }
59            }
60
61            fn as_any(&self) -> &dyn Any {
62                self
63            }
64        }
65
66        impl TableColumn for $OptionalTypeName {
67            fn len(&self) -> usize {
68                self.0.len()
69            }
70
71            fn append(
72                &mut self,
73                value: TableColumnValue,
74            ) -> Result<(), String> {
75                if let TableColumnValue::$OptionalTypeName(val) = value {
76                    self.0.push(val);
77                    Ok(())
78                } else {
79                    Err(format!("Type mismatch for {:?}", value))
80                }
81            }
82
83            fn as_any(&self) -> &dyn Any {
84                self
85            }
86        }
87    };
88}
89
90create_column_types!(Int32Column, OptionalInt32Column, i32);
91create_column_types!(Uint64Column, OptionalUint64Column, u64);
92create_column_types!(FloatColumn, OptionalFloatColumn, f64);
93create_column_types!(StringColumn, OptionalStringColumn, String);
94
95impl TableColumnValue {
96    pub fn to_string(&self) -> String {
97        // Use a generic pattern for Optional variants to return "NULL" for None values.
98        match self {
99            TableColumnValue::Int32Column(val) => val.to_string(),
100            TableColumnValue::Uint64Column(val) => val.to_string(),
101            TableColumnValue::FloatColumn(val) => val.to_string(),
102            TableColumnValue::StringColumn(val) => val.clone(),
103            // Handle optional types using a pattern that matches any Some variant and calls to_string on its content.
104            // For None, return "NULL".
105            TableColumnValue::OptionalInt32Column(Some(val)) => val.to_string(),
106            TableColumnValue::OptionalUint64Column(Some(val)) => {
107                val.to_string()
108            }
109            TableColumnValue::OptionalFloatColumn(Some(val)) => val.to_string(),
110            TableColumnValue::OptionalStringColumn(Some(val)) => val.clone(),
111            // Match any None variant for Optional types
112            _ => "NULL".to_string(),
113        }
114    }
115}