1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
/// # Examples
///
/// ```
///struct MyStruct {
/// c1: i32,
/// c2: String,
///}
///
///implement_from_tuple!(
/// MyStruct, (
/// c1: i32 => |inner: &mut MyStruct, value| {
/// if let DataValue::Int32(Some(val)) = value {
/// inner.c1 = val;
/// }
/// },
/// c2: String => |inner: &mut MyStruct, value| {
/// if let DataValue::Utf8(Some(val)) = value {
/// inner.c2 = val;
/// }
/// }
/// )
/// );
/// ```
#[macro_export]
macro_rules! implement_from_tuple {
($struct_name:ident, ($($field_name:ident : $field_type:ty => $closure:expr),+)) => {
impl From<Tuple> for $struct_name {
fn from(tuple: Tuple) -> Self {
fn try_get<T: 'static>(tuple: &Tuple, field_name: &str) -> Option<DataValue> {
let ty = LogicalType::type_trans::<T>()?;
let (idx, _) = tuple.columns
.iter()
.enumerate()
.find(|(_, col)| col.name() == field_name)?;
DataValue::clone(&tuple.values[idx])
.cast(&ty)
.ok()
}
let mut struct_instance = $struct_name::default();
$(
if let Some(value) = try_get::<$field_type>(&tuple, stringify!($field_name)) {
$closure(
&mut struct_instance,
value
);
}
)+
struct_instance
}
}
};
}
#[cfg(test)]
mod test {
use crate::catalog::{ColumnCatalog, ColumnDesc};
use crate::types::tuple::Tuple;
use crate::types::value::DataValue;
use crate::types::LogicalType;
use std::sync::Arc;
fn build_tuple() -> Tuple {
let columns = vec![
Arc::new(ColumnCatalog::new(
"c1".to_string(),
false,
ColumnDesc::new(LogicalType::Integer, true, false, None),
None,
)),
Arc::new(ColumnCatalog::new(
"c2".to_string(),
false,
ColumnDesc::new(LogicalType::Varchar(None), false, false, None),
None,
)),
];
let values = vec![
Arc::new(DataValue::Int32(Some(9))),
Arc::new(DataValue::Utf8(Some("LOL".to_string()))),
];
Tuple {
id: None,
columns,
values,
}
}
#[derive(Default, Debug, PartialEq)]
struct MyStruct {
c1: i32,
c2: String,
}
implement_from_tuple!(
MyStruct, (
c1: i32 => |inner: &mut MyStruct, value| {
if let DataValue::Int32(Some(val)) = value {
inner.c1 = val;
}
},
c2: String => |inner: &mut MyStruct, value| {
if let DataValue::Utf8(Some(val)) = value {
inner.c2 = val;
}
}
)
);
#[test]
fn test_from_tuple() {
let my_struct = MyStruct::from(build_tuple());
println!("{:?}", my_struct);
assert_eq!(my_struct.c1, 9);
assert_eq!(my_struct.c2, "LOL");
}
}