-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdsl.rs
66 lines (59 loc) · 2.18 KB
/
dsl.rs
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
/// ! to run, execute: `cargo run --bin dsl`
/// Domain Specific Language (DSL)
/// ------------------------------
///
/// DSL is a custom programming language that can be evaluated on specific type
/// of data or specific domain.
///
/// An example of DSL is SQL. SQL works for a list that contains similar type of
/// data. Not only RDBMS supports SQL, but any iterable that behaves like RDBMS
/// can be queried using SQL.
///
/// The below will use custom SQL-like query to list data from iterable that is
/// capable of querying, filtering, and ordering the data.
///
/// We use macro_rules! to create a SQL-like dsl.
macro_rules! sql {
// SELECT x from <data> WHERE <condition>
(SELECT $var: ident FROM $iter: expr, WHERE $cond: expr) => {
$iter.into_iter().filter(|&$var| $cond).collect()
};
// SELECT (ASC x as <type>) from <data> WHERE <condition>
(SELECT (ASC $var: ident AS $t:ty) FROM $iter: expr, WHERE $cond: expr) => {{
let mut x: $t = $iter.into_iter().filter(|&$var| $cond).collect();
x.sort();
x
}};
// SELECT ( DESC x as <type>) from <data> WHERE <condition>
(SELECT (DESC $var: ident AS $t:ty) FROM $iter: expr, WHERE $cond: expr) => {{
let mut x: $t = $iter.into_iter().filter(|&$var| $cond).collect();
x.sort_by(|a, b| b.cmp(a));
x
}};
}
fn main() {
let result: Vec<u32> = sql!(SELECT x FROM 1..10, WHERE x>=5);
println!("The SQL output is: {:?}", result);
let result = sql!(SELECT (ASC x AS Vec<u32>) FROM 1..10, WHERE x>=5);
println!("SQL output [ASC]: {:?}", result);
let result = sql!(SELECT (DESC x AS Vec<u32>) FROM 1..10, WHERE x>=5);
println!("SQL output [DESC]: {:?}", result);
}
#[cfg(test)]
mod tests {
#[test]
fn sql_runs_successfully() {
let x: Vec<u32> = sql!(SELECT x FROM 1..5, WHERE x<=3);
assert_eq!(x.len(), 3);
}
#[test]
fn sql_returns_ascending() {
let x: Vec<u32> = sql!(SELECT (ASC x AS Vec<u32>) FROM 1..5, WHERE x<=3);
assert_eq!(x[0], 1);
}
#[test]
fn sql_returns_descending() {
let x: Vec<u32> = sql!(SELECT (DESC x AS Vec<u32>) FROM 1..5, WHERE x<=3);
assert_eq!(x[0], 3);
}
}