2022-02-08 14:57:16 +08:00
#![ allow(unused_imports) ]
2022-02-08 23:52:00 +08:00
#![ allow(unused_attributes) ]
2022-02-09 07:23:57 +08:00
#![ allow(dead_code) ]
2022-02-15 21:27:00 +08:00
mod ast ;
mod proto_gen ;
mod proto_info ;
mod template ;
pub use proto_gen ::* ;
pub use proto_info ::* ;
2022-02-09 13:08:49 +08:00
#[ cfg(feature = " proto_gen " ) ]
2022-02-09 09:57:03 +08:00
use log ::info ;
2022-02-08 14:57:16 +08:00
use std ::fs ::File ;
use std ::io ::Write ;
2022-02-13 12:04:34 +08:00
use std ::path ::PathBuf ;
2022-02-09 07:23:57 +08:00
use std ::process ::Command ;
2022-02-08 14:57:16 +08:00
use walkdir ::WalkDir ;
2022-02-15 21:27:00 +08:00
pub fn gen ( crate_name : & str , proto_file_dir : & str ) {
2022-02-15 13:27:54 +08:00
// 1. generate the proto files to proto_file_dir
2022-02-09 13:08:49 +08:00
#[ cfg(feature = " proto_gen " ) ]
2022-02-09 18:17:06 +08:00
let _ = gen_protos ( crate_name ) ;
2022-02-08 14:57:16 +08:00
2022-02-16 10:00:31 +08:00
let mut proto_file_paths = vec! [ ] ;
2022-02-09 13:08:49 +08:00
let mut file_names = vec! [ ] ;
2022-02-08 14:57:16 +08:00
2022-02-15 13:27:54 +08:00
for ( path , file_name ) in WalkDir ::new ( proto_file_dir )
. into_iter ( )
. filter_map ( | e | e . ok ( ) )
. map ( | e | {
let path = e . path ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ;
let file_name = e . path ( ) . file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ;
( path , file_name )
} )
{
2022-02-09 13:08:49 +08:00
if path . ends_with ( " .proto " ) {
// https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project
println! ( " cargo:rerun-if-changed= {} " , path ) ;
2022-02-16 10:00:31 +08:00
proto_file_paths . push ( path ) ;
2022-02-09 13:08:49 +08:00
file_names . push ( file_name ) ;
}
2022-02-09 09:57:03 +08:00
}
2022-02-15 13:27:54 +08:00
let protoc_bin_path = protoc_bin_vendored ::protoc_bin_path ( ) . unwrap ( ) ;
2022-02-13 12:04:34 +08:00
2022-02-15 13:27:54 +08:00
// 2. generate the protobuf files(Dart)
2022-02-17 16:32:10 +08:00
2022-02-09 13:08:49 +08:00
2022-02-15 13:27:54 +08:00
// 3. generate the protobuf files(Rust)
2022-02-16 10:00:31 +08:00
generate_rust_protobuf_files ( & protoc_bin_path , & proto_file_paths , proto_file_dir ) ;
2022-02-15 13:27:54 +08:00
}
2022-02-16 10:00:31 +08:00
fn generate_rust_protobuf_files ( protoc_bin_path : & PathBuf , proto_file_paths : & Vec < String > , proto_file_dir : & str ) {
2022-02-09 13:08:49 +08:00
protoc_rust ::Codegen ::new ( )
. out_dir ( " ./src/protobuf/model " )
2022-02-15 13:27:54 +08:00
. protoc_path ( protoc_bin_path )
2022-02-16 10:00:31 +08:00
. inputs ( proto_file_paths )
2022-02-15 13:27:54 +08:00
. include ( proto_file_dir )
2022-02-09 13:08:49 +08:00
. run ( )
. expect ( " Running protoc failed. " ) ;
2022-02-08 14:57:16 +08:00
}
#[ cfg(feature = " dart " ) ]
2022-02-15 13:27:54 +08:00
fn generate_dart_protobuf_files (
name : & str ,
root : & str ,
paths : & Vec < String > ,
file_names : & Vec < String > ,
2022-02-16 10:00:31 +08:00
protoc_bin_path : & PathBuf ,
2022-02-15 13:27:54 +08:00
) {
2022-02-09 18:35:50 +08:00
if std ::env ::var ( " CARGO_MAKE_WORKING_DIRECTORY " ) . is_err ( ) {
log ::warn! ( " CARGO_MAKE_WORKING_DIRECTORY was not set, skip generate dart pb " ) ;
return ;
}
if std ::env ::var ( " FLUTTER_FLOWY_SDK_PATH " ) . is_err ( ) {
log ::warn! ( " FLUTTER_FLOWY_SDK_PATH was not set, skip generate dart pb " ) ;
return ;
}
let workspace_dir = std ::env ::var ( " CARGO_MAKE_WORKING_DIRECTORY " ) . unwrap ( ) ;
let flutter_sdk_path = std ::env ::var ( " FLUTTER_FLOWY_SDK_PATH " ) . unwrap ( ) ;
2022-02-16 10:00:31 +08:00
let output = format! ( " {} / {} /lib/protobuf/ {} " , workspace_dir , flutter_sdk_path , name ) ;
2022-02-08 14:57:16 +08:00
if ! std ::path ::Path ::new ( & output ) . exists ( ) {
std ::fs ::create_dir_all ( & output ) . unwrap ( ) ;
}
2022-02-09 07:23:57 +08:00
check_pb_dart_plugin ( ) ;
2022-02-16 10:00:31 +08:00
let protoc_bin_path = protoc_bin_path . to_str ( ) . unwrap ( ) . to_owned ( ) ;
2022-02-08 14:57:16 +08:00
paths . iter ( ) . for_each ( | path | {
if cmd_lib ::run_cmd! {
2022-02-16 10:00:31 +08:00
$ { protoc_bin_path } - - dart_out = $ { output } - - proto_path = $ { root } $ { path }
2022-02-08 14:57:16 +08:00
}
. is_err ( )
{
2022-02-13 12:04:34 +08:00
panic! ( " Generate dart pb file failed with: {} " , path )
2022-02-08 14:57:16 +08:00
} ;
} ) ;
let protobuf_dart = format! ( " {} /protobuf.dart " , output ) ;
match std ::fs ::OpenOptions ::new ( )
. create ( true )
. write ( true )
. append ( false )
. truncate ( true )
. open ( & protobuf_dart )
{
Ok ( ref mut file ) = > {
let mut export = String ::new ( ) ;
export . push_str ( " // Auto-generated, do not edit \n " ) ;
for file_name in file_names {
let c = format! ( " export './ {} .pb.dart'; \n " , file_name ) ;
export . push_str ( c . as_ref ( ) ) ;
}
file . write_all ( export . as_bytes ( ) ) . unwrap ( ) ;
File ::flush ( file ) . unwrap ( ) ;
}
Err ( err ) = > {
panic! ( " Failed to open file: {} " , err ) ;
}
}
}
2022-02-09 07:23:57 +08:00
fn check_pb_dart_plugin ( ) {
2022-02-17 11:18:07 +08:00
if cfg! ( target_os = " windows " ) {
2022-02-17 16:32:10 +08:00
//Command::new("cmd")
// .arg("/C")
// .arg(cmd)
// .status()
// .expect("failed to execute process");
//panic!("{}", format!("\n❌ The protoc-gen-dart was not installed correctly."))
2022-02-09 07:23:57 +08:00
} else {
2022-02-17 16:32:10 +08:00
let is_success = Command ::new ( " sh " )
2022-02-09 07:23:57 +08:00
. arg ( " -c " )
2022-02-17 16:32:10 +08:00
. arg ( " command -v protoc-gen-dart " )
2022-02-09 07:23:57 +08:00
. status ( )
. expect ( " failed to execute process " )
2022-02-17 16:32:10 +08:00
. success ( ) ;
if ! is_success {
panic! ( " {} " , format! ( " \n ❌ The protoc-gen-dart was not installed correctly. \n ✅ You can fix that by adding \" {} \" to your shell's config file.(.bashrc, .bash, etc.) " , " dart pub global activate protoc_plugin " ) )
}
}
2022-02-09 07:23:57 +08:00
}
2022-02-09 13:08:49 +08:00
#[ cfg(feature = " proto_gen " ) ]
2022-02-09 18:17:06 +08:00
fn gen_protos ( crate_name : & str ) -> Vec < ProtobufCrate > {
2022-02-15 22:35:52 +08:00
let crate_path = std ::fs ::canonicalize ( " . " ) . unwrap ( ) . as_path ( ) . display ( ) . to_string ( ) ;
let crate_context = ProtoGenerator ::gen ( crate_name , & crate_path ) ;
2022-02-09 13:08:49 +08:00
let proto_crates = crate_context
. iter ( )
. map ( | info | info . protobuf_crate . clone ( ) )
. collect ::< Vec < _ > > ( ) ;
crate_context
. into_iter ( )
. map ( | info | info . files )
. flatten ( )
. for_each ( | file | {
println! ( " cargo:rerun-if-changed= {} " , file . file_path ) ;
} ) ;
proto_crates
}