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