trans_gen/gens/rust/
mod.rs

1use super::*;
2
3fn conv(name: &str) -> String {
4    name.replace("Int32", "I32")
5        .replace("Int64", "I64")
6        .replace("Float32", "F32")
7        .replace("Float64", "F64")
8}
9
10fn type_name(schema: &Schema) -> String {
11    match schema {
12        Schema::Bool => "bool".to_owned(),
13        Schema::Int32 => "i32".to_owned(),
14        Schema::Int64 => "i64".to_owned(),
15        Schema::Float32 => "f32".to_owned(),
16        Schema::Float64 => "f64".to_owned(),
17        Schema::String => "String".to_owned(),
18        Schema::Option(inner) => format!("Option<{}>", type_name(inner)),
19        Schema::Struct(Struct { name, .. }) => name.camel_case(conv),
20        Schema::OneOf { base_name, .. } => base_name.camel_case(conv),
21        Schema::Vec(inner) => format!("Vec<{}>", type_name(inner)),
22        Schema::Map(key_type, value_type) => format!(
23            "std::collections::HashMap<{}, {}>",
24            type_name(key_type),
25            type_name(value_type)
26        ),
27        Schema::Enum { base_name, .. } => base_name.camel_case(conv),
28    }
29}
30
31pub struct Generator {
32    files: HashMap<String, String>,
33}
34impl crate::Generator for Generator {
35    type Options = ();
36    fn new(name: &str, version: &str, _: ()) -> Self {
37        let mut files = HashMap::new();
38        files.insert(
39            "Cargo.toml".to_owned(),
40            include_str!("Cargo.toml.template")
41                .replace("$name", name)
42                .replace("$version", version)
43                .replace("$trans-version", trans::VERSION),
44        );
45        files.insert("src/lib.rs".to_owned(), String::new());
46        Self { files }
47    }
48    fn result(self) -> GenResult {
49        self.files.into()
50    }
51    fn add_only(&mut self, schema: &Schema) {
52        match schema {
53            Schema::Struct(Struct {
54                documentation: _,
55                name,
56                fields,
57                magic,
58            }) => {
59                let file_name = format!("src/{}.rs", name.snake_case(conv));
60                let mut content = String::new();
61                {
62                    let content = &mut content;
63
64                    writeln!(content, "use super::*;").unwrap();
65
66                    write!(content, "#[derive(Clone, Debug").unwrap();
67                    if schema.hashable() {
68                        write!(content, ", PartialEq, Eq, Hash").unwrap();
69                    }
70                    writeln!(content, ", trans::Trans)]").unwrap();
71                    if let Some(magic) = magic {
72                        writeln!(content, "#[trans(magic = \"{}\")]", magic).unwrap();
73                    }
74                    writeln!(content, "pub struct {} {{", name.camel_case(conv)).unwrap();
75                    for field in fields {
76                        writeln!(
77                            content,
78                            "    pub {}: {},",
79                            field.name.snake_case(conv),
80                            type_name(&field.schema)
81                        )
82                        .unwrap();
83                    }
84                    writeln!(content, "}}").unwrap();
85                }
86
87                let lib = self.files.get_mut("src/lib.rs").unwrap();
88                writeln!(lib).unwrap();
89                writeln!(lib, "mod {};", name.snake_case(conv)).unwrap();
90                writeln!(lib, "pub use self::{}::*;", name.snake_case(conv)).unwrap();
91
92                self.files.insert(file_name, content);
93            }
94            Schema::OneOf {
95                base_name,
96                variants,
97                documentation: _,
98            } => {
99                let file_name = format!("src/{}.rs", base_name.snake_case(conv));
100                let mut content = String::new();
101                {
102                    let content = &mut content;
103
104                    writeln!(content, "use super::*;").unwrap();
105
106                    writeln!(content, "#[derive(Clone, Debug, trans::Trans)]").unwrap();
107                    writeln!(content, "pub enum {} {{", base_name.camel_case(conv)).unwrap();
108                    for variant in variants {
109                        writeln!(content, "    {} {{", variant.name.camel_case(conv)).unwrap();
110                        for field in &variant.fields {
111                            writeln!(
112                                content,
113                                "        {}: {},",
114                                field.name.snake_case(conv),
115                                type_name(&field.schema)
116                            )
117                            .unwrap();
118                        }
119                        writeln!(content, "    }},").unwrap();
120                    }
121                    writeln!(content, "}}").unwrap();
122                }
123
124                let lib = self.files.get_mut("src/lib.rs").unwrap();
125                writeln!(lib).unwrap();
126                writeln!(lib, "mod {};", base_name.snake_case(conv)).unwrap();
127                writeln!(lib, "pub use self::{}::*;", base_name.snake_case(conv)).unwrap();
128
129                self.files.insert(file_name, content);
130            }
131            Schema::Enum {
132                base_name,
133                variants,
134                documentation: _,
135            } => {
136                let file_name = format!("src/{}.rs", base_name.snake_case(conv));
137                let mut content = String::new();
138                {
139                    let content = &mut content;
140
141                    writeln!(content, "use super::*;").unwrap();
142
143                    writeln!(
144                        content,
145                        "#[derive(Clone, Debug, PartialEq, Eq, Hash, trans::Trans)]"
146                    )
147                    .unwrap();
148                    writeln!(content, "pub enum {} {{", base_name.camel_case(conv)).unwrap();
149                    for variant in variants {
150                        writeln!(content, "    {},", variant.name.camel_case(conv)).unwrap();
151                    }
152                    writeln!(content, "}}").unwrap();
153                }
154
155                let lib = self.files.get_mut("src/lib.rs").unwrap();
156                writeln!(lib).unwrap();
157                writeln!(lib, "mod {};", base_name.snake_case(conv)).unwrap();
158                writeln!(lib, "pub use self::{}::*;", base_name.snake_case(conv)).unwrap();
159
160                self.files.insert(file_name, content);
161            }
162            Schema::Bool
163            | Schema::Int32
164            | Schema::Int64
165            | Schema::Float32
166            | Schema::Float64
167            | Schema::String
168            | Schema::Option(_)
169            | Schema::Vec(_)
170            | Schema::Map(_, _) => {}
171        }
172    }
173}