Skip to main content

cdk_sql_common/
macros.rs

1//! Collection of macros to generate code to digest data from a generic SQL databasex
2
3/// Unpacks a vector of Column, and consumes it, parsing into individual variables, checking the
4/// vector is big enough.
5#[macro_export]
6macro_rules! unpack_into {
7    (let ($($var:ident),+) = $array:expr) => {
8        #[allow(unused_parens)]
9        let ($($var),+) = {
10            let mut vec = $array.to_vec();
11            vec.reverse();
12            let required = 0 $(+ {let _ = stringify!($var); 1})+;
13            if vec.len() < required {
14                 Err($crate::ConversionError::MissingColumn(required, vec.len()))?;
15            }
16            (
17                $(
18                    vec.pop().expect(&format!("Checked length already for {}", stringify!($var)))
19                ),+
20            )
21        };
22    };
23}
24
25/// Parses a SQL column as a string or NULL
26#[macro_export]
27macro_rules! column_as_nullable_string {
28    ($col:expr, $callback_str:expr, $callback_bytes:expr) => {
29        (match $col {
30            $crate::stmt::Column::Text(text) => Ok(Some(text).and_then($callback_str)),
31            $crate::stmt::Column::Blob(bytes) => Ok(Some(bytes).and_then($callback_bytes)),
32            $crate::stmt::Column::Null => Ok(None),
33            _ => Err($crate::ConversionError::InvalidType(
34                "String".to_owned(),
35                stringify!($col).to_owned(),
36            )),
37        })?
38    };
39    ($col:expr, $callback_str:expr) => {
40        (match $col {
41            $crate::stmt::Column::Text(text) => Ok(Some(text).and_then($callback_str)),
42            $crate::stmt::Column::Blob(bytes) => {
43                Ok(Some(String::from_utf8_lossy(&bytes)).and_then($callback_str))
44            }
45            $crate::stmt::Column::Null => Ok(None),
46            _ => Err($crate::ConversionError::InvalidType(
47                "String".to_owned(),
48                stringify!($col).to_owned(),
49            )),
50        })?
51    };
52    ($col:expr) => {
53        (match $col {
54            $crate::stmt::Column::Text(text) => Ok(Some(text.to_owned())),
55            $crate::stmt::Column::Blob(bytes) => {
56                Ok(Some(String::from_utf8_lossy(&bytes).to_string()))
57            }
58            $crate::stmt::Column::Null => Ok(None),
59            _ => Err($crate::ConversionError::InvalidType(
60                "String".to_owned(),
61                stringify!($col).to_owned(),
62            )),
63        })?
64    };
65}
66
67/// Parses a column as a number or NULL
68#[macro_export]
69macro_rules! column_as_nullable_number {
70    ($col:expr) => {
71        (match $col {
72            $crate::stmt::Column::Text(text) => Ok(Some(text.parse().map_err(|_| {
73                $crate::ConversionError::InvalidConversion(
74                    stringify!($col).to_owned(),
75                    "Number".to_owned(),
76                )
77            })?)),
78            $crate::stmt::Column::Integer(n) => Ok(Some(n.try_into().map_err(|_| {
79                $crate::ConversionError::InvalidConversion(
80                    stringify!($col).to_owned(),
81                    "Number".to_owned(),
82                )
83            })?)),
84            $crate::stmt::Column::Null => Ok(None),
85            _ => Err($crate::ConversionError::InvalidType(
86                "Number".to_owned(),
87                stringify!($col).to_owned(),
88            )),
89        })?
90    };
91}
92
93/// Parses a column as a number
94#[macro_export]
95macro_rules! column_as_number {
96    ($col:expr) => {
97        (match $col {
98            $crate::stmt::Column::Text(text) => text.parse().map_err(|_| {
99                $crate::ConversionError::InvalidConversion(
100                    stringify!($col).to_owned(),
101                    "Number".to_owned(),
102                )
103            }),
104            $crate::stmt::Column::Integer(n) => n.try_into().map_err(|_| {
105                $crate::ConversionError::InvalidConversion(
106                    stringify!($col).to_owned(),
107                    "Number".to_owned(),
108                )
109            }),
110            _ => Err($crate::ConversionError::InvalidType(
111                "Number".to_owned(),
112                stringify!($col).to_owned(),
113            )),
114        })?
115    };
116}
117
118/// Parses a column as a NULL or Binary
119#[macro_export]
120macro_rules! column_as_nullable_binary {
121    ($col:expr) => {
122        (match $col {
123            $crate::stmt::Column::Text(text) => Ok(Some(text.as_bytes().to_vec())),
124            $crate::stmt::Column::Blob(bytes) => Ok(Some(bytes.to_owned())),
125            $crate::stmt::Column::Null => Ok(None),
126            _ => Err($crate::ConversionError::InvalidType(
127                "String".to_owned(),
128                stringify!($col).to_owned(),
129            )),
130        })?
131    };
132}
133
134/// Parses a SQL column as a binary
135#[macro_export]
136macro_rules! column_as_binary {
137    ($col:expr) => {
138        (match $col {
139            $crate::stmt::Column::Text(text) => Ok(text.as_bytes().to_vec()),
140            $crate::stmt::Column::Blob(bytes) => Ok(bytes.to_owned()),
141            _ => Err($crate::ConversionError::InvalidType(
142                "String".to_owned(),
143                stringify!($col).to_owned(),
144            )),
145        })?
146    };
147}
148
149/// Parses a SQL column as a string
150#[macro_export]
151macro_rules! column_as_string {
152    ($col:expr, $callback_str:expr, $callback_bytes:expr) => {
153        (match $col {
154            $crate::stmt::Column::Text(text) => {
155                $callback_str(&text).map_err($crate::ConversionError::from)
156            }
157            $crate::stmt::Column::Blob(bytes) => {
158                $callback_bytes(&bytes).map_err($crate::ConversionError::from)
159            }
160            _ => Err($crate::ConversionError::InvalidType(
161                "String".to_owned(),
162                stringify!($col).to_owned(),
163            )),
164        })?
165    };
166    ($col:expr, $callback:expr) => {
167        (match $col {
168            $crate::stmt::Column::Text(text) => {
169                $callback(&text).map_err($crate::ConversionError::from)
170            }
171            $crate::stmt::Column::Blob(bytes) => {
172                $callback(&String::from_utf8_lossy(&bytes)).map_err($crate::ConversionError::from)
173            }
174            _ => Err($crate::ConversionError::InvalidType(
175                "String".to_owned(),
176                stringify!($col).to_owned(),
177            )),
178        })?
179    };
180    ($col:expr) => {
181        (match $col {
182            $crate::stmt::Column::Text(text) => Ok(text.to_owned()),
183            $crate::stmt::Column::Blob(bytes) => Ok(String::from_utf8_lossy(&bytes).to_string()),
184            _ => Err($crate::ConversionError::InvalidType(
185                "String".to_owned(),
186                stringify!($col).to_owned(),
187            )),
188        })?
189    };
190}