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