blob: 9f3f3a0cf54fdf1e06df34449b19e072416626b5 [file] [log] [blame]
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -07001// TODO: used by grpc-rust, should move it into separate crate.
2#![doc(hidden)]
3
4use std::io::Write;
5
6/// Field visibility.
7pub enum Visibility {
8 Public,
9 Default,
10}
11
12pub struct CodeWriter<'a> {
13 writer: &'a mut (dyn Write + 'a),
14 indent: String,
15}
16
17impl<'a> CodeWriter<'a> {
18 pub fn new(writer: &'a mut dyn Write) -> CodeWriter<'a> {
19 CodeWriter {
20 writer: writer,
21 indent: "".to_string(),
22 }
23 }
24
25 pub fn write_line<S: AsRef<str>>(&mut self, line: S) {
26 (if line.as_ref().is_empty() {
27 self.writer.write_all("\n".as_bytes())
28 } else {
29 let s: String = [self.indent.as_ref(), line.as_ref(), "\n"].concat();
30 self.writer.write_all(s.as_bytes())
31 })
32 .unwrap();
33 }
34
35 pub fn write_generated(&mut self) {
36 self.write_line("// This file is generated. Do not edit");
37 self.write_generated_common();
38 }
39
40 pub fn write_generated_by(&mut self, pkg: &str, version: &str) {
41 self.write_line(format!(
42 "// This file is generated by {pkg} {version}. Do not edit",
43 pkg = pkg,
44 version = version
45 ));
46 self.write_generated_common();
47 }
48
49 fn write_generated_common(&mut self) {
50 // https://secure.phabricator.com/T784
51 self.write_line("// @generated");
52
53 self.write_line("");
54 self.comment("https://github.com/rust-lang/rust-clippy/issues/702");
55 self.write_line("#![allow(unknown_lints)]");
56 self.write_line("#![allow(clippy::all)]");
57 self.write_line("");
Haibo Huang72fec012020-07-10 20:24:04 -070058 self.write_line("#![allow(unused_attributes)]");
59 self.write_line("#![rustfmt::skip]");
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -070060 self.write_line("");
61 self.write_line("#![allow(box_pointers)]");
62 self.write_line("#![allow(dead_code)]");
63 self.write_line("#![allow(missing_docs)]");
64 self.write_line("#![allow(non_camel_case_types)]");
65 self.write_line("#![allow(non_snake_case)]");
66 self.write_line("#![allow(non_upper_case_globals)]");
67 self.write_line("#![allow(trivial_casts)]");
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -070068 self.write_line("#![allow(unused_imports)]");
69 self.write_line("#![allow(unused_results)]");
70 }
71
72 pub fn todo(&mut self, message: &str) {
73 self.write_line(format!("panic!(\"TODO: {}\");", message));
74 }
75
76 pub fn unimplemented(&mut self) {
77 self.write_line(format!("unimplemented!();"));
78 }
79
80 pub fn indented<F>(&mut self, cb: F)
81 where
82 F: Fn(&mut CodeWriter),
83 {
84 cb(&mut CodeWriter {
85 writer: self.writer,
86 indent: format!("{} ", self.indent),
87 });
88 }
89
90 #[allow(dead_code)]
91 pub fn commented<F>(&mut self, cb: F)
92 where
93 F: Fn(&mut CodeWriter),
94 {
95 cb(&mut CodeWriter {
96 writer: self.writer,
97 indent: format!("// {}", self.indent),
98 });
99 }
100
101 pub fn pub_const(&mut self, name: &str, field_type: &str, init: &str) {
102 self.write_line(&format!("pub const {}: {} = {};", name, field_type, init));
103 }
104
105 pub fn lazy_static(&mut self, name: &str, ty: &str) {
106 self.lazy_static_protobuf_path(name, ty, "::protobuf")
107 }
108
109 pub fn lazy_static_protobuf_path(&mut self, name: &str, ty: &str, protobuf_crate_path: &str) {
110 self.write_line(&format!(
Haibo Huang72fec012020-07-10 20:24:04 -0700111 "static {}: {}::rt::LazyV2<{}> = {}::rt::LazyV2::INIT;",
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700112 name, protobuf_crate_path, ty, protobuf_crate_path,
113 ));
114 }
115
116 pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F)
117 where
118 F: Fn(&mut CodeWriter),
119 {
120 self.lazy_static(name, ty);
Haibo Huang72fec012020-07-10 20:24:04 -0700121 self.write_line(&format!("{}.get(|| {{", name));
122 self.indented(|w| init(w));
123 self.write_line(&format!("}})"));
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700124 }
125
126 pub fn lazy_static_decl_get_simple(&mut self, name: &str, ty: &str, init: &str) {
127 self.lazy_static(name, ty);
Haibo Huang72fec012020-07-10 20:24:04 -0700128 self.write_line(&format!("{}.get({})", name, init));
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700129 }
130
131 pub fn block<F>(&mut self, first_line: &str, last_line: &str, cb: F)
132 where
133 F: Fn(&mut CodeWriter),
134 {
135 self.write_line(first_line);
136 self.indented(cb);
137 self.write_line(last_line);
138 }
139
140 pub fn expr_block<F>(&mut self, prefix: &str, cb: F)
141 where
142 F: Fn(&mut CodeWriter),
143 {
144 self.block(&format!("{} {{", prefix), "}", cb);
145 }
146
147 pub fn stmt_block<S: AsRef<str>, F>(&mut self, prefix: S, cb: F)
148 where
149 F: Fn(&mut CodeWriter),
150 {
151 self.block(&format!("{} {{", prefix.as_ref()), "};", cb);
152 }
153
154 pub fn unsafe_expr<F>(&mut self, cb: F)
155 where
156 F: Fn(&mut CodeWriter),
157 {
158 self.expr_block("unsafe", cb);
159 }
160
161 pub fn impl_self_block<S: AsRef<str>, F>(&mut self, name: S, cb: F)
162 where
163 F: Fn(&mut CodeWriter),
164 {
165 self.expr_block(&format!("impl {}", name.as_ref()), cb);
166 }
167
168 pub fn impl_for_block<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F)
169 where
170 F: Fn(&mut CodeWriter),
171 {
172 self.impl_args_for_block(&[], tr.as_ref(), ty.as_ref(), cb);
173 }
174
175 pub fn impl_args_for_block<F>(&mut self, args: &[&str], tr: &str, ty: &str, cb: F)
176 where
177 F: Fn(&mut CodeWriter),
178 {
179 let args_str = if args.is_empty() {
180 "".to_owned()
181 } else {
182 format!("<{}>", args.join(", "))
183 };
184 self.expr_block(&format!("impl{} {} for {}", args_str, tr, ty), cb);
185 }
186
187 pub fn unsafe_impl(&mut self, what: &str, for_what: &str) {
188 self.write_line(&format!("unsafe impl {} for {} {{}}", what, for_what));
189 }
190
191 pub fn pub_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F)
192 where
193 F: Fn(&mut CodeWriter),
194 {
195 self.expr_block(&format!("pub struct {}", name.as_ref()), cb);
196 }
197
198 pub fn def_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F)
199 where
200 F: Fn(&mut CodeWriter),
201 {
202 self.expr_block(&format!("struct {}", name.as_ref()), cb);
203 }
204
205 pub fn pub_enum<F>(&mut self, name: &str, cb: F)
206 where
207 F: Fn(&mut CodeWriter),
208 {
209 self.expr_block(&format!("pub enum {}", name), cb);
210 }
211
212 pub fn pub_trait<F>(&mut self, name: &str, cb: F)
213 where
214 F: Fn(&mut CodeWriter),
215 {
216 self.expr_block(&format!("pub trait {}", name), cb);
217 }
218
219 pub fn pub_trait_extend<F>(&mut self, name: &str, extend: &str, cb: F)
220 where
221 F: Fn(&mut CodeWriter),
222 {
223 self.expr_block(&format!("pub trait {} : {}", name, extend), cb);
224 }
225
226 pub fn field_entry(&mut self, name: &str, value: &str) {
227 self.write_line(&format!("{}: {},", name, value));
228 }
229
230 pub fn field_decl(&mut self, name: &str, field_type: &str) {
231 self.write_line(&format!("{}: {},", name, field_type));
232 }
233
234 pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
235 self.write_line(&format!("pub {}: {},", name, field_type));
236 }
237
238 pub fn field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str) {
239 match vis {
240 Visibility::Public => self.pub_field_decl(name, field_type),
241 Visibility::Default => self.field_decl(name, field_type),
242 }
243 }
244
245 pub fn derive(&mut self, derive: &[&str]) {
246 let v: Vec<String> = derive.iter().map(|&s| s.to_string()).collect();
247 self.write_line(&format!("#[derive({})]", v.join(",")));
248 }
249
250 pub fn allow(&mut self, what: &[&str]) {
251 let v: Vec<String> = what.iter().map(|&s| s.to_string()).collect();
252 self.write_line(&format!("#[allow({})]", v.join(",")));
253 }
254
255 pub fn comment(&mut self, comment: &str) {
256 if comment.is_empty() {
257 self.write_line("//");
258 } else {
259 self.write_line(&format!("// {}", comment));
260 }
261 }
262
263 pub fn fn_def(&mut self, sig: &str) {
264 self.write_line(&format!("fn {};", sig));
265 }
266
267 pub fn fn_block<F>(&mut self, public: bool, sig: &str, cb: F)
268 where
269 F: Fn(&mut CodeWriter),
270 {
271 if public {
272 self.expr_block(&format!("pub fn {}", sig), cb);
273 } else {
274 self.expr_block(&format!("fn {}", sig), cb);
275 }
276 }
277
278 pub fn pub_fn<F>(&mut self, sig: &str, cb: F)
279 where
280 F: Fn(&mut CodeWriter),
281 {
282 self.fn_block(true, sig, cb);
283 }
284
285 pub fn def_fn<F>(&mut self, sig: &str, cb: F)
286 where
287 F: Fn(&mut CodeWriter),
288 {
289 self.fn_block(false, sig, cb);
290 }
291
292 pub fn def_mod<F>(&mut self, name: &str, cb: F)
293 where
294 F: Fn(&mut CodeWriter),
295 {
296 self.expr_block(&format!("mod {}", name), cb)
297 }
298
299 pub fn pub_mod<F>(&mut self, name: &str, cb: F)
300 where
301 F: Fn(&mut CodeWriter),
302 {
303 self.expr_block(&format!("pub mod {}", name), cb)
304 }
305
306 pub fn while_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
307 where
308 F: Fn(&mut CodeWriter),
309 {
310 self.expr_block(&format!("while {}", cond.as_ref()), cb);
311 }
312
313 // if ... { ... }
314 pub fn if_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
315 where
316 F: Fn(&mut CodeWriter),
317 {
318 self.expr_block(&format!("if {}", cond.as_ref()), cb);
319 }
320
321 // if ... {} else { ... }
322 pub fn if_else_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
323 where
324 F: Fn(&mut CodeWriter),
325 {
326 self.write_line(&format!("if {} {{", cond.as_ref()));
327 self.write_line("} else {");
328 self.indented(cb);
329 self.write_line("}");
330 }
331
332 // if let ... = ... { ... }
333 pub fn if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
334 where
335 F: Fn(&mut CodeWriter),
336 {
337 self.if_stmt(&format!("let {} = {}", decl, expr), cb);
338 }
339
340 // if let ... = ... { } else { ... }
341 pub fn if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
342 where
343 F: Fn(&mut CodeWriter),
344 {
345 self.if_else_stmt(&format!("let {} = {}", decl, expr), cb);
346 }
347
348 pub fn for_stmt<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F)
349 where
350 F: Fn(&mut CodeWriter),
351 {
352 self.stmt_block(&format!("for {} in {}", varn.as_ref(), over.as_ref()), cb)
353 }
354
355 pub fn match_block<S: AsRef<str>, F>(&mut self, value: S, cb: F)
356 where
357 F: Fn(&mut CodeWriter),
358 {
359 self.stmt_block(&format!("match {}", value.as_ref()), cb);
360 }
361
362 pub fn match_expr<S: AsRef<str>, F>(&mut self, value: S, cb: F)
363 where
364 F: Fn(&mut CodeWriter),
365 {
366 self.expr_block(&format!("match {}", value.as_ref()), cb);
367 }
368
369 pub fn case_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
370 where
371 F: Fn(&mut CodeWriter),
372 {
373 self.block(&format!("{} => {{", cond.as_ref()), "},", cb);
374 }
375
376 pub fn case_expr<S1: AsRef<str>, S2: AsRef<str>>(&mut self, cond: S1, body: S2) {
377 self.write_line(&format!("{} => {},", cond.as_ref(), body.as_ref()));
378 }
379}