1#![doc(hidden)]
3
4use std::io::Write;
5
6pub 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 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
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.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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
245 pub fn field_entry(&mut self, name: &str, value: &str) {
246 self.write_line(&format!("{}: {},", name, value));
247 }
248
249 pub fn field_decl(&mut self, name: &str, field_type: &str) {
250 self.write_line(&format!("{}: {},", name, field_type));
251 }
252
253 pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
254 self.write_line(&format!("pub {}: {},", name, field_type));
255 }
256
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
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
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
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
282 pub fn fn_def(&mut self, sig: &str) {
283 self.write_line(&format!("fn {};", sig));
284 }
285
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
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
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
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
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
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 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 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 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 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
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
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
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
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
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}