derive_sql_common/derive/
sqltype.rs1#[derive(Debug)]
5pub enum SqlType {
6 Integer,
7 Text,
8 OptionText,
9 Boolean,
10 Float,
11 OptionFloat,
12 DateTime,
13 Date,
14 Unsupported,
15}
16
17impl From<&syn::Field> for SqlType {
18 fn from(f: &syn::Field) -> SqlType {
19 (&f.ty).into()
20 }
21}
22
23impl From<&syn::Type> for SqlType {
24 fn from(t: &syn::Type) -> SqlType {
25 SqlType::from_type(t)
26 }
27}
28
29impl SqlType {
30 pub fn from_type(ty: &syn::Type) -> SqlType {
31 match ty {
32 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("String") => SqlType::Text,
33 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("i8") => SqlType::Integer,
34 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("u8") => SqlType::Integer,
35 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("i32") => SqlType::Integer,
36 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("u32") => SqlType::Integer,
37 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("i64") => SqlType::Integer,
38 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("u64") => SqlType::Integer,
39 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("usize") => SqlType::Integer,
40 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("bool") => SqlType::Boolean,
41 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("f32") => SqlType::Float,
42 syn::Type::Path(syn::TypePath { path, .. }) if path.is_ident("f64") => SqlType::Float,
43 syn::Type::Path(syn::TypePath { path: syn::Path { segments, .. } , .. }) => {
44 match segments.last() {
45 Some(syn::PathSegment { ident, ..}) if ident == "DateTime" => SqlType::DateTime,
46 Some(syn::PathSegment { ident, ..}) if ident == "NaiveDate" => SqlType::Date,
47 Some(syn::PathSegment { ident, ..}) if ident == "NaiveDateTime" => SqlType::DateTime,
48 Some(syn::PathSegment { ident,
49 arguments: syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { args, .. } )
50 }) if ident == "Option" => {
51 match args.last() {
52 Some(syn::GenericArgument::Type(syn::Type::Path(syn::TypePath { path, .. }))) if path.is_ident("String") => SqlType::OptionText,
53 Some(syn::GenericArgument::Type(syn::Type::Path(syn::TypePath { path, .. }))) if path.is_ident("f32") => SqlType::OptionFloat,
54 Some(syn::GenericArgument::Type(syn::Type::Path(syn::TypePath { path, .. }))) if path.is_ident("f64") => SqlType::OptionFloat,
55 _ => SqlType::Unsupported,
56 }
57 },
58 _ => SqlType::Unsupported,
59 }
60 },
61 _ => SqlType::Unsupported,
62 }
63 }
64
65 pub fn to_string(&self) -> &str {
66 match self {
67 SqlType::Integer => "INTEGER",
68 SqlType::Text => "TEXT",
69 SqlType::OptionText => "TEXT",
70 SqlType::Boolean => "BOOL", SqlType::Float => "FLOAT",
72 SqlType::OptionFloat => "FLOAT",
73 SqlType::DateTime => "DATETIME",
74 SqlType::Date => "DATE",
75 SqlType::Unsupported => "",
76 }
77 }
78}
79
80#[cfg(test)]
81mod test_sql_type {
82 use super::*;
83
84 #[test]
85 fn works() -> Result<(), Box<dyn std::error::Error>> {
86 let t = syn::parse_str::<syn::Type>("[u32; 6]")?;
87 let t = SqlType::from_type(&t);
88 assert!(matches!(t, SqlType::Unsupported));
89 assert!(t.to_string().eq(""));
90
91 for k in ["u32", "usize", "i32"] {
92 let t = syn::parse_str::<syn::Type>(k)?;
93 let t = SqlType::from_type(&t);
94 assert!(matches!(t, SqlType::Integer));
95 assert!(t.to_string().eq("INTEGER"));
96 }
97
98 let t = syn::parse_str::<syn::Type>("String")?;
99 let t = SqlType::from_type(&t);
100 assert!(matches!(t, SqlType::Text));
101 assert!(t.to_string().eq("TEXT"));
102
103 let t = syn::parse_str::<syn::Type>("Option<String>")?;
104 let t = SqlType::from_type(&t);
105 assert!(matches!(t, SqlType::OptionText));
106 assert!(t.to_string().eq("TEXT"));
107
108 let t = syn::parse_str::<syn::Type>("std::option::Option<String>")?;
109 let t = SqlType::from_type(&t);
110 assert!(matches!(t, SqlType::OptionText));
111 assert!(t.to_string().eq("TEXT"));
112
113 let t = syn::parse_str::<syn::Type>("bool")?;
114 let t = SqlType::from_type(&t);
115 assert!(matches!(t, SqlType::Boolean));
116 assert!(t.to_string().eq("BOOL"));
117
118 let t = syn::parse_str::<syn::Type>("f32")?;
119 let t = SqlType::from_type(&t);
120 assert!(matches!(t, SqlType::Float));
121 assert!(t.to_string().eq("FLOAT"));
122
123 let t = syn::parse_str::<syn::Type>("DateTime")?;
124 let t = SqlType::from_type(&t);
125 assert!(matches!(t, SqlType::DateTime));
126 assert!(t.to_string().eq("DATETIME"));
127
128 let t = syn::parse_str::<syn::Type>("NaiveDate")?;
129 let t = SqlType::from_type(&t);
130 assert!(matches!(t, SqlType::Date));
131 assert!(t.to_string().eq("DATE"));
132
133 let t = syn::parse_str::<syn::Type>("NaiveDateTime")?;
134 let t = SqlType::from_type(&t);
135 assert!(matches!(t, SqlType::DateTime));
136 assert!(t.to_string().eq("DATETIME"));
137
138 Ok(())
139 }
140}