1 // TODO: used by grpc-rust, should move it into separate crate. 2 #![doc(hidden)] 3 4 use std::io::Write; 5 6 /// Field visibility. 7 pub enum Visibility { 8 Public, 9 Default, 10 } 11 12 pub struct CodeWriter<'a> { 13 writer: &'a mut (dyn Write + 'a), 14 indent: String, 15 } 16 17 impl<'a> CodeWriter<'a> { new(writer: &'a mut dyn Write) -> 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 write_line<S: AsRef<str>>(&mut self, line: S)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 write_generated(&mut self)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 write_generated_by(&mut self, pkg: &str, version: &str)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 write_generated_common(&mut self)49 fn write_generated_common(&mut self) { 50 // https://secure.phabricator.com/T784 51 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 todo(&mut self, message: &str)72 pub fn todo(&mut self, message: &str) { 73 self.write_line(format!("panic!(\"TODO: {}\");", message)); 74 } 75 unimplemented(&mut self)76 pub fn unimplemented(&mut self) { 77 self.write_line(format!("unimplemented!();")); 78 } 79 indented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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)] commented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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 pub_const(&mut self, name: &str, field_type: &str, init: &str)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 lazy_static(&mut self, name: &str, ty: &str)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 lazy_static_protobuf_path(&mut self, name: &str, ty: &str, protobuf_crate_path: &str)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 lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, init: F) where F: Fn(&mut CodeWriter),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 lazy_static_decl_get_simple(&mut self, name: &str, ty: &str, init: &str)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 block<F>(&mut self, first_line: &str, last_line: &str, cb: F) where F: Fn(&mut CodeWriter),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 expr_block<F>(&mut self, prefix: &str, cb: F) where F: Fn(&mut CodeWriter),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 stmt_block<S: AsRef<str>, F>(&mut self, prefix: S, cb: F) where F: Fn(&mut CodeWriter),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 unsafe_expr<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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 impl_self_block<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),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 impl_for_block<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F) where F: Fn(&mut CodeWriter),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 impl_args_for_block<F>(&mut self, args: &[&str], tr: &str, ty: &str, cb: F) where F: Fn(&mut CodeWriter),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 unsafe_impl(&mut self, what: &str, for_what: &str)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 pub_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),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 def_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),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 pub_enum<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_trait<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_trait_extend<F>(&mut self, name: &str, extend: &str, cb: F) where F: Fn(&mut CodeWriter),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 field_entry(&mut self, name: &str, value: &str)245 pub fn field_entry(&mut self, name: &str, value: &str) { 246 self.write_line(&format!("{}: {},", name, value)); 247 } 248 field_decl(&mut self, name: &str, field_type: &str)249 pub fn field_decl(&mut self, name: &str, field_type: &str) { 250 self.write_line(&format!("{}: {},", name, field_type)); 251 } 252 pub_field_decl(&mut self, name: &str, field_type: &str)253 pub fn pub_field_decl(&mut self, name: &str, field_type: &str) { 254 self.write_line(&format!("pub {}: {},", name, field_type)); 255 } 256 field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str)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 derive(&mut self, derive: &[&str])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 allow(&mut self, what: &[&str])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 comment(&mut self, comment: &str)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 fn_def(&mut self, sig: &str)282 pub fn fn_def(&mut self, sig: &str) { 283 self.write_line(&format!("fn {};", sig)); 284 } 285 fn_block<F>(&mut self, public: bool, sig: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_fn<F>(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter),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 def_fn<F>(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter),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 def_mod<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_mod<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 while_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),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 // if ... { ... } if_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),333 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 // if ... {} else { ... } if_else_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),341 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 // if let ... = ... { ... } if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter),352 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 // if let ... = ... { } else { ... } if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter),360 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 for_stmt<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F) where F: Fn(&mut CodeWriter),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 match_block<S: AsRef<str>, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter),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 match_expr<S: AsRef<str>, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter),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 case_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),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 case_expr<S1: AsRef<str>, S2: AsRef<str>>(&mut self, cond: S1, body: S2)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 } 399