1 // TODO: used by grpc-rust, should move it into separate crate. 2 #![doc(hidden)] 3 4 use inside::protobuf_crate_path; 5 use std::io::Write; 6 use Customize; 7 8 /// Field visibility. 9 pub enum Visibility { 10 Public, 11 Default, 12 } 13 14 pub struct CodeWriter<'a> { 15 writer: &'a mut (dyn Write + 'a), 16 indent: String, 17 } 18 19 impl<'a> CodeWriter<'a> { new(writer: &'a mut dyn Write) -> 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 write_line<S: AsRef<str>>(&mut self, line: S)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 write_generated(&mut self)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 write_generated_by(&mut self, pkg: &str, version: &str)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 write_generated_common(&mut self)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(""); 60 self.write_line("#![allow(unused_attributes)]"); 61 self.write_line("#![cfg_attr(rustfmt, rustfmt::skip)]"); 62 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)]"); 70 self.write_line("#![allow(unused_imports)]"); 71 self.write_line("#![allow(unused_results)]"); 72 } 73 todo(&mut self, message: &str)74 pub fn todo(&mut self, message: &str) { 75 self.write_line(format!("panic!(\"TODO: {}\");", message)); 76 } 77 unimplemented(&mut self)78 pub fn unimplemented(&mut self) { 79 self.write_line(format!("unimplemented!();")); 80 } 81 indented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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)] commented<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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 pub_const(&mut self, name: &str, field_type: &str, init: &str)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 lazy_static(&mut self, name: &str, ty: &str, customize: &Customize)107 pub fn lazy_static(&mut self, name: &str, ty: &str, customize: &Customize) { 108 self.write_line(&format!( 109 "static {}: {}::rt::LazyV2<{}> = {}::rt::LazyV2::INIT;", 110 name, 111 protobuf_crate_path(customize), 112 ty, 113 protobuf_crate_path(customize), 114 )); 115 } 116 lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, customize: &Customize, init: F) where F: Fn(&mut CodeWriter),117 pub fn lazy_static_decl_get<F>(&mut self, name: &str, ty: &str, customize: &Customize, init: F) 118 where 119 F: Fn(&mut CodeWriter), 120 { 121 self.lazy_static(name, ty, customize); 122 self.write_line(&format!("{}.get(|| {{", name)); 123 self.indented(|w| init(w)); 124 self.write_line(&format!("}})")); 125 } 126 lazy_static_decl_get_simple( &mut self, name: &str, ty: &str, init: &str, customize: &Customize, )127 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); 135 self.write_line(&format!("{}.get({})", name, init)); 136 } 137 block<F>(&mut self, first_line: &str, last_line: &str, cb: F) where F: Fn(&mut CodeWriter),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 expr_block<F>(&mut self, prefix: &str, cb: F) where F: Fn(&mut CodeWriter),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 stmt_block<S: AsRef<str>, F>(&mut self, prefix: S, cb: F) where F: Fn(&mut CodeWriter),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 unsafe_expr<F>(&mut self, cb: F) where F: Fn(&mut CodeWriter),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 impl_self_block<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),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 impl_for_block<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, tr: S1, ty: S2, cb: F) where F: Fn(&mut CodeWriter),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 impl_args_for_block<F>(&mut self, args: &[&str], tr: &str, ty: &str, cb: F) where F: Fn(&mut CodeWriter),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 unsafe_impl(&mut self, what: &str, for_what: &str)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 pub_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),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 def_struct<S: AsRef<str>, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter),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 pub_enum<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_trait<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_trait_extend<F>(&mut self, name: &str, extend: &str, cb: F) where F: Fn(&mut CodeWriter),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 field_entry(&mut self, name: &str, value: &str)233 pub fn field_entry(&mut self, name: &str, value: &str) { 234 self.write_line(&format!("{}: {},", name, value)); 235 } 236 field_decl(&mut self, name: &str, field_type: &str)237 pub fn field_decl(&mut self, name: &str, field_type: &str) { 238 self.write_line(&format!("{}: {},", name, field_type)); 239 } 240 pub_field_decl(&mut self, name: &str, field_type: &str)241 pub fn pub_field_decl(&mut self, name: &str, field_type: &str) { 242 self.write_line(&format!("pub {}: {},", name, field_type)); 243 } 244 field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str)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 derive(&mut self, derive: &[&str])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 allow(&mut self, what: &[&str])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 comment(&mut self, comment: &str)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 fn_def(&mut self, sig: &str)270 pub fn fn_def(&mut self, sig: &str) { 271 self.write_line(&format!("fn {};", sig)); 272 } 273 fn_block<F>(&mut self, public: bool, sig: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_fn<F>(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter),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 def_fn<F>(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter),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 def_mod<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 pub_mod<F>(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter),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 while_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),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 ... { ... } if_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),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 { ... } if_else_stmt<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),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 ... = ... { ... } if_let_stmt<F>(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter),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 { ... } if_let_else_stmt<F>(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter),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 for_stmt<S1: AsRef<str>, S2: AsRef<str>, F>(&mut self, over: S1, varn: S2, cb: F) where F: Fn(&mut CodeWriter),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 match_block<S: AsRef<str>, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter),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 match_expr<S: AsRef<str>, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter),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 case_block<S: AsRef<str>, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter),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 case_expr<S1: AsRef<str>, S2: AsRef<str>>(&mut self, cond: S1, body: S2)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 } 387