engineer/
lib.rs

1extern crate engineer_derive;
2
3pub use engineer_derive::*;
4
5pub trait Builder<T>
6where
7    T: Engineer,
8    T::Builder: Builder<T>,
9{
10    fn done(self) -> T;
11}
12
13pub trait Engineer
14where
15    Self: Sized,
16    Self::Builder: Builder<Self>,
17{
18    const NORMAL_FIELDS: usize;
19    const OPTIONAL_FIELDS: usize;
20
21    type Builder;
22    type Params;
23
24    fn builder(required: Self::Params) -> Self::Builder;
25
26    fn build(required: Self::Params) -> Self {
27        Self::builder(required).done()
28    }
29
30    fn build_default() -> Self
31    where
32        Self::Params: Default,
33    {
34        Self::build(Default::default())
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[allow(dead_code)]
43    #[derive(Debug, Default)]
44    enum Gender {
45        Male,
46        Female,
47
48        #[default]
49        NotSaying,
50    }
51
52    #[allow(dead_code)]
53    #[derive(Debug, Engineer)]
54    #[engineer(new, str_retype)]
55    struct User {
56        id: usize,          // No default.
57        first_name: String, // No default.
58        // Default on none option.
59        #[engineer(default)]
60        gender: Gender, // Default should be Default::default() (Gender::NotSaying).
61        // Default value on none option.
62        #[engineer(default_value = r#"String::from("fa")"#)]
63        lang_code: String, // Default should be String("fa").
64        last_name: Option<String>, // Default should be None.
65        // Default on option.
66        #[engineer(default)] // Educated, not educated, no data
67        is_educated: Option<bool>, // Default should be Some(Default::default()) (Some(false)).
68        // Default value on option.
69        #[engineer(default_value = "true")]
70        is_human: Option<bool>, // Default should be Some(true).
71    }
72
73    #[test]
74    fn basic_test() {
75        let arash = User::new(1, "Arash").done();
76
77        assert_eq!(arash.id, 1);
78        assert_eq!(arash.first_name, "Arash");
79        assert_eq!(arash.last_name, None);
80        assert!(matches!(arash.gender, Gender::NotSaying));
81        assert_eq!(arash.lang_code, "fa".to_string());
82        assert!(matches!(arash.is_educated, Some(false)));
83        assert!(matches!(arash.is_human, Some(true)));
84    }
85
86    #[test]
87    fn basic_test_2() {
88        let model = User::new(1, "Monkey")
89            .last_name("Donkey")
90            .gender(Gender::NotSaying)
91            .lang_code("en")
92            .is_human(false)
93            .is_educated(true)
94            .done();
95
96        assert_eq!(model.id, 1);
97        assert_eq!(model.first_name, "Monkey");
98        assert_eq!(model.last_name, Some("Donkey".to_string()));
99        assert!(matches!(model.gender, Gender::NotSaying));
100        assert_eq!(model.lang_code, "en".to_string());
101        assert!(matches!(model.is_educated, Some(true)));
102        assert!(matches!(model.is_human, Some(false)));
103    }
104}