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 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 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 _ => "NULL".to_string(),
113 }
114 }
115}