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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
pub mod format;
mod functions;
pub mod templates;

use std::sync::{Arc, Mutex};

use dagger_core::introspection::Schema;
use eyre::Context;
use genco::prelude::rust;

use crate::functions::CommonFunctions;
use crate::generator::Generator;
use crate::visitor::{VisitHandlers, Visitor};

use self::format::FormatTypeFunc;
use self::templates::enum_tmpl::render_enum;
use self::templates::input_tmpl::render_input;
use self::templates::object_tmpl::render_object;
use self::templates::scalar_tmpl::render_scalar;

pub struct RustGenerator {}

impl Generator for RustGenerator {
    fn generate(&self, schema: Schema) -> eyre::Result<String> {
        let render = Arc::new(Mutex::new(rust::Tokens::new()));
        let common_funcs = Arc::new(CommonFunctions::new(Arc::new(FormatTypeFunc {})));
        println!("generating dagger for rust");

        let visitor = Visitor {
            schema,
            handlers: VisitHandlers {
                visit_scalar: Arc::new({
                    let render = render.clone();
                    let _common_funcs = common_funcs.clone();

                    move |t| {
                        println!("generating scalar");
                        let rendered_scalar = render_scalar(t)?;

                        let mut render = render.lock().unwrap();

                        render.append(rendered_scalar);
                        render.push();

                        println!("generated scalar");

                        Ok(())
                    }
                }),
                visit_object: Arc::new({
                    let render = render.clone();
                    let common_funcs = common_funcs.clone();

                    move |t| {
                        println!("generating object");
                        let rendered_scalar = render_object(&common_funcs, t)?;

                        let mut render = render.lock().unwrap();

                        render.append(rendered_scalar);
                        render.push();
                        println!("generated object");

                        Ok(())
                    }
                }),
                visit_input: Arc::new({
                    let render = render.clone();
                    let common_funcs = common_funcs.clone();

                    move |t| {
                        println!("generating input");
                        let rendered_scalar = render_input(&common_funcs, t)?;

                        let mut render = render.lock().unwrap();

                        render.append(rendered_scalar);
                        render.push();
                        println!("generated input");

                        Ok(())
                    }
                }),
                visit_enum: Arc::new({
                    let render = render.clone();
                    let _common_funcs = common_funcs.clone();

                    move |t| {
                        println!("generating enum");
                        let rendered_scalar = render_enum(t)?;

                        let mut render = render.lock().unwrap();

                        render.append(rendered_scalar);
                        render.push();
                        println!("generated enum");

                        Ok(())
                    }
                }),
            },
        };

        visitor.run()?;

        println!("done generating objects");

        let rendered = render.lock().unwrap();

        rendered
            .to_file_string()
            .context("could not render to file string")
    }
}