protobuf_codegen3/
code_writer.rs

1// TODO: used by grpc-rust, should move it into separate crate.
2#![doc(hidden)]
3
4use std::io::Write;
5
6use inside::protobuf_crate_path;
7use Customize;
8
9/// Field visibility.
10pub enum Visibility {
11    Public,
12    Default,
13}
14
15pub struct CodeWriter<'a> {
16    writer: &'a mut (dyn Write + 'a),
17    indent: String,
18}
19
20impl<'a> 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
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
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
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
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
75    pub fn todo(&mut self, message: &str) {
76        self.write_line(format!("panic!(\"TODO: {}\");", message));
77    }
78
79    pub fn unimplemented(&mut self) {
80        self.write_line(format!("unimplemented!();"));
81    }
82
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)]
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
234    pub fn field_entry(&mut self, name: &str, value: &str) {
235        self.write_line(&format!("{}: {},", name, value));
236    }
237
238    pub fn field_decl(&mut self, name: &str, field_type: &str) {
239        self.write_line(&format!("{}: {},", name, field_type));
240    }
241
242    pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
243        self.write_line(&format!("pub {}: {},", name, field_type));
244    }
245
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
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
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
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
271    pub fn fn_def(&mut self, sig: &str) {
272        self.write_line(&format!("fn {};", sig));
273    }
274
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
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
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
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
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
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 ... { ... }
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 { ... }
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 ... = ... { ... }
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 { ... }
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
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
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
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
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
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}