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
115
116
117
118
119
120
121
122
123
124
125
126
127
extern crate proc_macro2;

use quote::quote;

use std::env;
use std::path::Path;
use std::{fs::OpenOptions, process::Command};

use std::io::prelude::*;

mod types;

mod compile;

use crate::compile::compile_cdp_json;

pub fn init() {
    const CDP_COMMIT: &str = "15f524c8f5ce5b317ddcdf5e6f875d6eb8bdac88";
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let out_file = Path::new(&out_dir).join("protocol.rs");
    let mut file = OpenOptions::new()
        .append(true)
        .create(true)
        .open(&out_file)
        .unwrap();

    file.sync_all().unwrap();

    if file.metadata().unwrap().len() <= 0 {
        let (js_mods, js_events) = compile_cdp_json("js_protocol.json", CDP_COMMIT);

        let (browser_mods, browser_events) = compile_cdp_json("browser_protocol.json", CDP_COMMIT);

        writeln!(
            file,
            "// Auto-generated from ChromeDevTools/devtools-protocol at commit {}",
            CDP_COMMIT
        )
        .unwrap();

        let modv = quote! {
            #[allow(unused)]
            #[allow(non_camel_case_types)]
            #[allow(non_snake_case)]

            pub mod cdp {

                pub mod types {
                    use serde::{Deserialize, Serialize};
                    use std::fmt::Debug;

                    pub type JsFloat = f64;
                    pub type JsUInt = u32;

                    pub type WindowId = JsUInt;

                    pub type CallId = JsUInt;


                    #[derive(Serialize, Debug)]
                    pub struct MethodCall<T>
                    where
                    T: Debug,
                    {
                        #[serde(rename = "method")]
                        method_name: &'static str,
                        pub id: CallId,
                        params: T,
                    }

                    impl<T> MethodCall<T>
                    where
                    T: Debug,
                    {
                        pub fn get_params(&self) -> &T {
                        &self.params
                        }
                    }

                    pub trait Method: Debug {
                    const NAME: &'static str;

                    type ReturnObject: serde::de::DeserializeOwned + std::fmt::Debug;


                    fn to_method_call(self, call_id: CallId) -> MethodCall<Self>
                    where
                    Self: std::marker::Sized,
                    {
                        MethodCall {
                            id: call_id,
                             params: self,
                            method_name: Self::NAME,
                            }
                    }

                    }

                    #[derive(Deserialize, Debug, Clone, PartialEq)]
                    #[serde(tag = "method")]
                    #[allow(clippy::large_enum_variant)]
                    pub enum Event {
                        #(#browser_events)*
                        #(#js_events)*
                    }
                }

                #(#js_mods)*
                #(#browser_mods)*
            }
        };

        writeln!(file, "{}", modv.to_string()).unwrap();

        if env::var_os("DO_NOT_FORMAT").is_none() {
            Command::new("rustfmt").arg(&out_file).output().unwrap();
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test() {
        crate::init();
    }
}