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}