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