1 // TODO: used by grpc-rust, should move it into separate crate.
2 #![doc(hidden)]
3 
4 use std::io::Write;
5 
6 /// Field visibility.
7 pub enum Visibility {
8     Public,
9     Default,
10 }
11 
12 pub struct CodeWriter<'a> {
13     writer: &'a mut (dyn Write + 'a),
14     indent: String,
15 }
16 
17 impl<'a> CodeWriter<'a> {
new(writer: &'a mut dyn Write) -> 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 
write_line<S: AsRef<str>>(&mut self, line: S)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 
write_generated(&mut self)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 
write_generated_by(&mut self, pkg: &str, version: &str)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 
write_generated_common(&mut self)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/Manishearth/rust-clippy/issues/702");
55         self.write_line("#![allow(unknown_lints)]");
56         self.write_line("#![allow(clippy::all)]");
57         self.write_line("");
58         self.write_line("#![cfg_attr(rustfmt, rustfmt_skip)]");
59         self.write_line("");
60         self.write_line("#![allow(box_pointers)]");
61         self.write_line("#![allow(dead_code)]");
62         self.write_line("#![allow(missing_docs)]");
63         self.write_line("#![allow(non_camel_case_types)]");
64         self.write_line("#![allow(non_snake_case)]");
65         self.write_line("#![allow(non_upper_case_globals)]");
66         self.write_line("#![allow(trivial_casts)]");
67         self.write_line("#![allow(unsafe_code)]");
68         self.write_line("#![allow(unused_imports)]");
69         self.write_line("#![allow(unused_results)]");
70     }
71 
todo(&mut self, message: &str)72     pub fn todo(&mut self, message: &str) {
73         self.write_line(format!("panic!(\"TODO: {}\");", message));
74     }
75 
unimplemented(&mut self)76     pub fn unimplemented(&mut self) {
77         self.write_line(format!("unimplemented!();"));
78     }
79 
indented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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)]
commented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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 
pub_const(&mut self, name: &str, field_type: &str, init: &str)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 
lazy_static(&mut self, name: &str, ty: &str)105     pub fn lazy_static(&mut self, name: &str, ty: &str) {
106         self.stmt_block(
107             &format!(
108                 "static mut {}: ::protobuf::lazy::Lazy<{}> = ::protobuf::lazy::Lazy",
109                 name, ty
110             ),
111             |w| {
112                 w.field_entry("lock", "::protobuf::lazy::ONCE_INIT");
113                 w.field_entry("ptr", &format!("0 as *const {}", ty));
114             },
115         );
116     }
117 
lazy_static_protobuf_path(&mut self, name: &str, ty: &str, protobuf_crate_path: &str)118     pub fn lazy_static_protobuf_path(&mut self, name: &str, ty: &str, protobuf_crate_path: &str) {
119         self.stmt_block(
120             &format!(
121                 "static mut {}: {}::lazy::Lazy<{}> = ::protobuf::lazy::Lazy",
122                 name, protobuf_crate_path, ty
123             ),
124             |w| {
125                 w.field_entry("lock", &format!("{}::lazy::ONCE_INIT", protobuf_crate_path));
126                 w.field_entry("ptr", &format!("0 as *const {}", ty));
127             },
128         );
129     }
130 
lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F) where F: Fn(&mut CodeWriter),131     pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F)
132     where
133         F: Fn(&mut CodeWriter),
134     {
135         self.lazy_static(name, ty);
136         self.unsafe_expr(|w| {
137             w.write_line(&format!("{}.get(|| {{", name));
138             w.indented(|w| init(w));
139             w.write_line(&format!("}})"));
140         });
141     }
142 
lazy_static_decl_get_simple(&mut self, name: &str, ty: &str, init: &str)143     pub fn lazy_static_decl_get_simple(&mut self, name: &str, ty: &str, init: &str) {
144         self.lazy_static(name, ty);
145         self.unsafe_expr(|w| {
146             w.write_line(&format!("{}.get({})", name, init));
147         });
148     }
149 
block<F>(&mut self, first_line: &str, last_line: &str, cb: F) where F: Fn(&mut CodeWriter),150     pub fn block<F>(&mut self, first_line: &str, last_line: &str, cb: F)
151     where
152         F: Fn(&mut CodeWriter),
153     {
154         self.write_line(first_line);
155         self.indented(cb);
156         self.write_line(last_line);
157     }
158 
expr_block<F>(&mut self, prefix: &str, cb: F) where F: Fn(&mut CodeWriter),159     pub fn expr_block<F>(&mut self, prefix: &str, cb: F)
160     where
161         F: Fn(&mut CodeWriter),
162     {
163         self.block(&format!("{} {{", prefix), "}", cb);
164     }
165 
stmt_block<S: AsRef<str>, F>(&mut self, prefix: S, cb: F) where F: Fn(&mut CodeWriter),166     pub fn stmt_block<S: AsRef<str>, F>(&mut self, prefix: S, cb: F)
167     where
168         F: Fn(&mut CodeWriter),
169     {
170         self.block(&format!("{} {{", prefix.as_ref()), "};", cb);
171     }
172 
unsafe_expr<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),173     pub fn unsafe_expr<F>(&mut self, cb: F)
174     where
175         F: Fn(&mut CodeWriter),
176     {
177         self.expr_block("unsafe", cb);
178     }
179 
impl_self_block<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),180     pub fn impl_self_block<S: AsRef<str>, F>(&mut self, name: S, cb: F)
181     where
182         F: Fn(&mut CodeWriter),
183     {
184         self.expr_block(&format!("impl {}", name.as_ref()), cb);
185     }
186 
impl_for_block<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F) where F: Fn(&mut CodeWriter),187     pub fn impl_for_block<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F)
188     where
189         F: Fn(&mut CodeWriter),
190     {
191         self.impl_args_for_block(&[], tr.as_ref(), ty.as_ref(), cb);
192     }
193 
impl_args_for_block<F>(&mut self, args: &[&str], tr: &str, ty: &str, cb: F) where F: Fn(&mut CodeWriter),194     pub fn impl_args_for_block<F>(&mut self, args: &[&str], tr: &str, ty: &str, cb: F)
195     where
196         F: Fn(&mut CodeWriter),
197     {
198         let args_str = if args.is_empty() {
199             "".to_owned()
200         } else {
201             format!("<{}>", args.join(", "))
202         };
203         self.expr_block(&format!("impl{} {} for {}", args_str, tr, ty), cb);
204     }
205 
unsafe_impl(&mut self, what: &str, for_what: &str)206     pub fn unsafe_impl(&mut self, what: &str, for_what: &str) {
207         self.write_line(&format!("unsafe impl {} for {} {{}}", what, for_what));
208     }
209 
pub_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),210     pub fn pub_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F)
211     where
212         F: Fn(&mut CodeWriter),
213     {
214         self.expr_block(&format!("pub struct {}", name.as_ref()), cb);
215     }
216 
def_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),217     pub fn def_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F)
218     where
219         F: Fn(&mut CodeWriter),
220     {
221         self.expr_block(&format!("struct {}", name.as_ref()), cb);
222     }
223 
pub_enum<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),224     pub fn pub_enum<F>(&mut self, name: &str, cb: F)
225     where
226         F: Fn(&mut CodeWriter),
227     {
228         self.expr_block(&format!("pub enum {}", name), cb);
229     }
230 
pub_trait<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),231     pub fn pub_trait<F>(&mut self, name: &str, cb: F)
232     where
233         F: Fn(&mut CodeWriter),
234     {
235         self.expr_block(&format!("pub trait {}", name), cb);
236     }
237 
pub_trait_extend<F>(&mut self, name: &str, extend: &str, cb: F) where F: Fn(&mut CodeWriter),238     pub fn pub_trait_extend<F>(&mut self, name: &str, extend: &str, cb: F)
239     where
240         F: Fn(&mut CodeWriter),
241     {
242         self.expr_block(&format!("pub trait {} : {}", name, extend), cb);
243     }
244 
field_entry(&mut self, name: &str, value: &str)245     pub fn field_entry(&mut self, name: &str, value: &str) {
246         self.write_line(&format!("{}: {},", name, value));
247     }
248 
field_decl(&mut self, name: &str, field_type: &str)249     pub fn field_decl(&mut self, name: &str, field_type: &str) {
250         self.write_line(&format!("{}: {},", name, field_type));
251     }
252 
pub_field_decl(&mut self, name: &str, field_type: &str)253     pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
254         self.write_line(&format!("pub {}: {},", name, field_type));
255     }
256 
field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str)257     pub fn field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str) {
258         match vis {
259             Visibility::Public => self.pub_field_decl(name, field_type),
260             Visibility::Default => self.field_decl(name, field_type),
261         }
262     }
263 
derive(&mut self, derive: &[&str])264     pub fn derive(&mut self, derive: &[&str]) {
265         let v: Vec<String> = derive.iter().map(|&s| s.to_string()).collect();
266         self.write_line(&format!("#[derive({})]", v.join(",")));
267     }
268 
allow(&mut self, what: &[&str])269     pub fn allow(&mut self, what: &[&str]) {
270         let v: Vec<String> = what.iter().map(|&s| s.to_string()).collect();
271         self.write_line(&format!("#[allow({})]", v.join(",")));
272     }
273 
comment(&mut self, comment: &str)274     pub fn comment(&mut self, comment: &str) {
275         if comment.is_empty() {
276             self.write_line("//");
277         } else {
278             self.write_line(&format!("// {}", comment));
279         }
280     }
281 
fn_def(&mut self, sig: &str)282     pub fn fn_def(&mut self, sig: &str) {
283         self.write_line(&format!("fn {};", sig));
284     }
285 
fn_block<F>(&mut self, public: bool, sig: &str, cb: F) where F: Fn(&mut CodeWriter),286     pub fn fn_block<F>(&mut self, public: bool, sig: &str, cb: F)
287     where
288         F: Fn(&mut CodeWriter),
289     {
290         if public {
291             self.expr_block(&format!("pub fn {}", sig), cb);
292         } else {
293             self.expr_block(&format!("fn {}", sig), cb);
294         }
295     }
296 
pub_fn<F>(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter),297     pub fn pub_fn<F>(&mut self, sig: &str, cb: F)
298     where
299         F: Fn(&mut CodeWriter),
300     {
301         self.fn_block(true, sig, cb);
302     }
303 
def_fn<F>(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter),304     pub fn def_fn<F>(&mut self, sig: &str, cb: F)
305     where
306         F: Fn(&mut CodeWriter),
307     {
308         self.fn_block(false, sig, cb);
309     }
310 
def_mod<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),311     pub fn def_mod<F>(&mut self, name: &str, cb: F)
312     where
313         F: Fn(&mut CodeWriter),
314     {
315         self.expr_block(&format!("mod {}", name), cb)
316     }
317 
pub_mod<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),318     pub fn pub_mod<F>(&mut self, name: &str, cb: F)
319     where
320         F: Fn(&mut CodeWriter),
321     {
322         self.expr_block(&format!("pub mod {}", name), cb)
323     }
324 
while_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),325     pub fn while_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
326     where
327         F: Fn(&mut CodeWriter),
328     {
329         self.expr_block(&format!("while {}", cond.as_ref()), cb);
330     }
331 
332     // if ... { ... }
if_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),333     pub fn if_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
334     where
335         F: Fn(&mut CodeWriter),
336     {
337         self.expr_block(&format!("if {}", cond.as_ref()), cb);
338     }
339 
340     // if ... {} else { ... }
if_else_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),341     pub fn if_else_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
342     where
343         F: Fn(&mut CodeWriter),
344     {
345         self.write_line(&format!("if {} {{", cond.as_ref()));
346         self.write_line("} else {");
347         self.indented(cb);
348         self.write_line("}");
349     }
350 
351     // if let ... = ... { ... }
if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter),352     pub fn if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
353     where
354         F: Fn(&mut CodeWriter),
355     {
356         self.if_stmt(&format!("let {} = {}", decl, expr), cb);
357     }
358 
359     // if let ... = ... { } else { ... }
if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter),360     pub fn if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F)
361     where
362         F: Fn(&mut CodeWriter),
363     {
364         self.if_else_stmt(&format!("let {} = {}", decl, expr), cb);
365     }
366 
for_stmt<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F) where F: Fn(&mut CodeWriter),367     pub fn for_stmt<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F)
368     where
369         F: Fn(&mut CodeWriter),
370     {
371         self.stmt_block(&format!("for {} in {}", varn.as_ref(), over.as_ref()), cb)
372     }
373 
match_block<S: AsRef<str>, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter),374     pub fn match_block<S: AsRef<str>, F>(&mut self, value: S, cb: F)
375     where
376         F: Fn(&mut CodeWriter),
377     {
378         self.stmt_block(&format!("match {}", value.as_ref()), cb);
379     }
380 
match_expr<S: AsRef<str>, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter),381     pub fn match_expr<S: AsRef<str>, F>(&mut self, value: S, cb: F)
382     where
383         F: Fn(&mut CodeWriter),
384     {
385         self.expr_block(&format!("match {}", value.as_ref()), cb);
386     }
387 
case_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),388     pub fn case_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F)
389     where
390         F: Fn(&mut CodeWriter),
391     {
392         self.block(&format!("{} => {{", cond.as_ref()), "},", cb);
393     }
394 
case_expr<S1: AsRef<str>, S2: AsRef<str>>(&mut self, cond: S1, body: S2)395     pub fn case_expr<S1: AsRef<str>, S2: AsRef<str>>(&mut self, cond: S1, body: S2) {
396         self.write_line(&format!("{} => {},", cond.as_ref(), body.as_ref()));
397     }
398 }
399