blob: 8b53bc630c9621ea453e2cc7161258e170aee5eb [file] [log] [blame]
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -07001// TODO: used by grpc-rust, should move it into separate crate.
2#![doc(hidden)]
3
Haibo Huangba676d32020-08-12 13:52:13 -07004use inside::protobuf_crate_path;
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -07005use std::io::Write;
Haibo Huangba676d32020-08-12 13:52:13 -07006use Customize;
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -07007
8/// Field visibility.
9pub enum Visibility {
10 Public,
11 Default,
12}
13
14pub struct CodeWriter<'a> {
15 writer: &'a mut (dyn Write + 'a),
16 indent: String,
17}
18
19impl<'a> 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
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
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
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
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("");
Haibo Huang72fec012020-07-10 20:24:04 -070060 self.write_line("#![allow(unused_attributes)]");
Chih-Hung Hsieh07f32d92020-10-06 01:50:33 -070061 self.write_line("#![rustfmt::skip]");
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -070062 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)]");
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -070070 self.write_line("#![allow(unused_imports)]");
71 self.write_line("#![allow(unused_results)]");
72 }
73
74 pub fn todo(&mut self, message: &str) {
75 self.write_line(format!("panic!(\"TODO: {}\");", message));
76 }
77
78 pub fn unimplemented(&mut self) {
79 self.write_line(format!("unimplemented!();"));
80 }
81
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)]
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
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
Haibo Huangba676d32020-08-12 13:52:13 -0700107 pub fn lazy_static(&mut self, name: &str, ty: &str, customize: &Customize) {
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700108 self.write_line(&format!(
Haibo Huang72fec012020-07-10 20:24:04 -0700109 "static {}: {}::rt::LazyV2<{}> = {}::rt::LazyV2::INIT;",
Haibo Huangba676d32020-08-12 13:52:13 -0700110 name,
111 protobuf_crate_path(customize),
112 ty,
113 protobuf_crate_path(customize),
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700114 ));
115 }
116
Haibo Huangba676d32020-08-12 13:52:13 -0700117 pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, customize: &Customize, init: F)
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700118 where
119 F: Fn(&mut CodeWriter),
120 {
Haibo Huangba676d32020-08-12 13:52:13 -0700121 self.lazy_static(name, ty, customize);
Haibo Huang72fec012020-07-10 20:24:04 -0700122 self.write_line(&format!("{}.get(|| {{", name));
123 self.indented(|w| init(w));
124 self.write_line(&format!("}})"));
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700125 }
126
Haibo Huangba676d32020-08-12 13:52:13 -0700127 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);
Haibo Huang72fec012020-07-10 20:24:04 -0700135 self.write_line(&format!("{}.get({})", name, init));
Chih-Hung Hsieh92ff6052020-06-10 20:18:39 -0700136 }
137
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
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
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
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
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
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
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
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
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
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
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
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
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
233 pub fn field_entry(&mut self, name: &str, value: &str) {
234 self.write_line(&format!("{}: {},", name, value));
235 }
236
237 pub fn field_decl(&mut self, name: &str, field_type: &str) {
238 self.write_line(&format!("{}: {},", name, field_type));
239 }
240
241 pub fn pub_field_decl(&mut self, name: &str, field_type: &str) {
242 self.write_line(&format!("pub {}: {},", name, field_type));
243 }
244
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
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
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
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
270 pub fn fn_def(&mut self, sig: &str) {
271 self.write_line(&format!("fn {};", sig));
272 }
273
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
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
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
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
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
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 ... { ... }
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 { ... }
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 ... = ... { ... }
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 { ... }
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
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
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
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
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
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}