// TODO: used by grpc-rust, should move it into separate crate. #![doc(hidden)] use std::io::Write; use inside::protobuf_crate_path; use Customize; /// Field visibility. pub enum Visibility { Public, Default, } pub struct CodeWriter<'a> { writer: &'a mut (dyn Write + 'a), indent: String, } impl<'a> CodeWriter<'a> { pub fn new(writer: &'a mut dyn Write) -> CodeWriter<'a> { CodeWriter { writer: writer, indent: "".to_string(), } } pub fn write_line>(&mut self, line: S) { (if line.as_ref().is_empty() { self.writer.write_all("\n".as_bytes()) } else { let s: String = [self.indent.as_ref(), line.as_ref(), "\n"].concat(); self.writer.write_all(s.as_bytes()) }) .unwrap(); } pub fn write_generated(&mut self) { self.write_line("// This file is generated. Do not edit"); self.write_generated_common(); } pub fn write_generated_by(&mut self, pkg: &str, version: &str) { self.write_line(format!( "// This file is generated by {pkg} {version}. Do not edit", pkg = pkg, version = version )); self.write_generated_common(); } fn write_generated_common(&mut self) { // https://secure.phabricator.com/T784 self.write_line("// @generated"); self.write_line(""); self.comment("https://github.com/rust-lang/rust-clippy/issues/702"); self.write_line("#![allow(unknown_lints)]"); self.write_line("#![allow(clippy::all)]"); self.write_line(""); self.write_line("#![allow(unused_attributes)]"); self.write_line("#![cfg_attr(rustfmt, rustfmt::skip)]"); self.write_line(""); self.write_line("#![allow(box_pointers)]"); self.write_line("#![allow(dead_code)]"); self.write_line("#![allow(missing_docs)]"); self.write_line("#![allow(non_camel_case_types)]"); self.write_line("#![allow(non_snake_case)]"); self.write_line("#![allow(non_upper_case_globals)]"); self.write_line("#![allow(trivial_casts)]"); self.write_line("#![allow(unused_imports)]"); self.write_line("#![allow(unused_results)]"); } pub fn todo(&mut self, message: &str) { self.write_line(format!("panic!(\"TODO: {}\");", message)); } pub fn unimplemented(&mut self) { self.write_line(format!("unimplemented!();")); } pub fn indented(&mut self, cb: F) where F: Fn(&mut CodeWriter), { cb(&mut CodeWriter { writer: self.writer, indent: format!("{} ", self.indent), }); } #[allow(dead_code)] pub fn commented(&mut self, cb: F) where F: Fn(&mut CodeWriter), { cb(&mut CodeWriter { writer: self.writer, indent: format!("// {}", self.indent), }); } pub fn pub_const(&mut self, name: &str, field_type: &str, init: &str) { self.write_line(&format!("pub const {}: {} = {};", name, field_type, init)); } pub fn lazy_static(&mut self, name: &str, ty: &str, customize: &Customize) { self.write_line(&format!( "static {}: {}::rt::LazyV2<{}> = {}::rt::LazyV2::INIT;", name, protobuf_crate_path(customize), ty, protobuf_crate_path(customize), )); } pub fn lazy_static_decl_get(&mut self, name: &str, ty: &str, customize: &Customize, init: F) where F: Fn(&mut CodeWriter), { self.lazy_static(name, ty, customize); self.write_line(&format!("{}.get(|| {{", name)); self.indented(|w| init(w)); self.write_line(&format!("}})")); } pub fn lazy_static_decl_get_simple( &mut self, name: &str, ty: &str, init: &str, customize: &Customize, ) { self.lazy_static(name, ty, customize); self.write_line(&format!("{}.get({})", name, init)); } pub fn block(&mut self, first_line: &str, last_line: &str, cb: F) where F: Fn(&mut CodeWriter), { self.write_line(first_line); self.indented(cb); self.write_line(last_line); } pub fn expr_block(&mut self, prefix: &str, cb: F) where F: Fn(&mut CodeWriter), { self.block(&format!("{} {{", prefix), "}", cb); } pub fn stmt_block, F>(&mut self, prefix: S, cb: F) where F: Fn(&mut CodeWriter), { self.block(&format!("{} {{", prefix.as_ref()), "};", cb); } pub fn unsafe_expr(&mut self, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block("unsafe", cb); } pub fn impl_self_block, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("impl {}", name.as_ref()), cb); } pub fn impl_for_block, S2: AsRef, F>(&mut self, tr: S1, ty: S2, cb: F) where F: Fn(&mut CodeWriter), { self.impl_args_for_block(&[], tr.as_ref(), ty.as_ref(), cb); } pub fn impl_args_for_block(&mut self, args: &[&str], tr: &str, ty: &str, cb: F) where F: Fn(&mut CodeWriter), { let args_str = if args.is_empty() { "".to_owned() } else { format!("<{}>", args.join(", ")) }; self.expr_block(&format!("impl{} {} for {}", args_str, tr, ty), cb); } pub fn unsafe_impl(&mut self, what: &str, for_what: &str) { self.write_line(&format!("unsafe impl {} for {} {{}}", what, for_what)); } pub fn pub_struct, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("pub struct {}", name.as_ref()), cb); } pub fn def_struct, F>(&mut self, name: S, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("struct {}", name.as_ref()), cb); } pub fn pub_enum(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("pub enum {}", name), cb); } pub fn pub_trait(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("pub trait {}", name), cb); } pub fn pub_trait_extend(&mut self, name: &str, extend: &str, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("pub trait {} : {}", name, extend), cb); } pub fn field_entry(&mut self, name: &str, value: &str) { self.write_line(&format!("{}: {},", name, value)); } pub fn field_decl(&mut self, name: &str, field_type: &str) { self.write_line(&format!("{}: {},", name, field_type)); } pub fn pub_field_decl(&mut self, name: &str, field_type: &str) { self.write_line(&format!("pub {}: {},", name, field_type)); } pub fn field_decl_vis(&mut self, vis: Visibility, name: &str, field_type: &str) { match vis { Visibility::Public => self.pub_field_decl(name, field_type), Visibility::Default => self.field_decl(name, field_type), } } pub fn derive(&mut self, derive: &[&str]) { let v: Vec = derive.iter().map(|&s| s.to_string()).collect(); self.write_line(&format!("#[derive({})]", v.join(","))); } pub fn allow(&mut self, what: &[&str]) { let v: Vec = what.iter().map(|&s| s.to_string()).collect(); self.write_line(&format!("#[allow({})]", v.join(","))); } pub fn comment(&mut self, comment: &str) { if comment.is_empty() { self.write_line("//"); } else { self.write_line(&format!("// {}", comment)); } } pub fn fn_def(&mut self, sig: &str) { self.write_line(&format!("fn {};", sig)); } pub fn fn_block(&mut self, public: bool, sig: &str, cb: F) where F: Fn(&mut CodeWriter), { if public { self.expr_block(&format!("pub fn {}", sig), cb); } else { self.expr_block(&format!("fn {}", sig), cb); } } pub fn pub_fn(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter), { self.fn_block(true, sig, cb); } pub fn def_fn(&mut self, sig: &str, cb: F) where F: Fn(&mut CodeWriter), { self.fn_block(false, sig, cb); } pub fn def_mod(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("mod {}", name), cb) } pub fn pub_mod(&mut self, name: &str, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("pub mod {}", name), cb) } pub fn while_block, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("while {}", cond.as_ref()), cb); } // if ... { ... } pub fn if_stmt, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("if {}", cond.as_ref()), cb); } // if ... {} else { ... } pub fn if_else_stmt, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter), { self.write_line(&format!("if {} {{", cond.as_ref())); self.write_line("} else {"); self.indented(cb); self.write_line("}"); } // if let ... = ... { ... } pub fn if_let_stmt(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter), { self.if_stmt(&format!("let {} = {}", decl, expr), cb); } // if let ... = ... { } else { ... } pub fn if_let_else_stmt(&mut self, decl: &str, expr: &str, cb: F) where F: Fn(&mut CodeWriter), { self.if_else_stmt(&format!("let {} = {}", decl, expr), cb); } pub fn for_stmt, S2: AsRef, F>(&mut self, over: S1, varn: S2, cb: F) where F: Fn(&mut CodeWriter), { self.stmt_block(&format!("for {} in {}", varn.as_ref(), over.as_ref()), cb) } pub fn match_block, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter), { self.stmt_block(&format!("match {}", value.as_ref()), cb); } pub fn match_expr, F>(&mut self, value: S, cb: F) where F: Fn(&mut CodeWriter), { self.expr_block(&format!("match {}", value.as_ref()), cb); } pub fn case_block, F>(&mut self, cond: S, cb: F) where F: Fn(&mut CodeWriter), { self.block(&format!("{} => {{", cond.as_ref()), "},", cb); } pub fn case_expr, S2: AsRef>(&mut self, cond: S1, body: S2) { self.write_line(&format!("{} => {},", cond.as_ref(), body.as_ref())); } }