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