protoc-rust-2.27.1/.cargo_vcs_info.json0000644000000001510000000000100134230ustar { "git": { "sha1": "ec31ce829473039ac598ca6fdcb245cbd6fa82ba" }, "path_in_vcs": "protoc-rust" }protoc-rust-2.27.1/Cargo.toml0000644000000021000000000000100114150ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "protoc-rust" version = "2.27.1" authors = ["Stepan Koltsov "] description = """ protoc --rust_out=... available as API. protoc needs to be in $PATH, protoc-gen-run does not. """ homepage = "https://github.com/stepancheg/rust-protobuf/" license = "MIT" repository = "https://github.com/stepancheg/rust-protobuf/" [package.metadata.docs.rs] all-features = true [lib] doctest = false bench = false [dependencies.protobuf] version = "=2.27.1" [dependencies.protobuf-codegen] version = "=2.27.1" [dependencies.protoc] version = "=2.27.1" [dependencies.tempfile] version = "3" protoc-rust-2.27.1/Cargo.toml.orig000064400000000000000000000012170072674642500151360ustar 00000000000000[package] name = "protoc-rust" version = "2.27.1" authors = ["Stepan Koltsov "] license = "MIT" homepage = "https://github.com/stepancheg/rust-protobuf/" repository = "https://github.com/stepancheg/rust-protobuf/" description = """ protoc --rust_out=... available as API. protoc needs to be in $PATH, protoc-gen-run does not. """ [lib] doctest = false bench = false [dependencies] protoc = { path = "../protoc", version = "=2.27.1" } protobuf = { path = "../protobuf", version = "=2.27.1" } protobuf-codegen = { path = "../protobuf-codegen", version = "=2.27.1" } tempfile = "3" [package.metadata.docs.rs] all-features = true protoc-rust-2.27.1/LICENSE.txt000064400000000000000000000020420072674642500140670ustar 00000000000000Copyright (c) 2019 Stepan Koltsov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. protoc-rust-2.27.1/README.md000064400000000000000000000022240072674642500135250ustar 00000000000000 # API to generate `.rs` files using `protoc` to parse files This API requires `protoc` command present in `$PATH` or explicitly passed to `Codegen` object (but `protoc` *plugin* is not needed). ```rust extern crate protoc_rust; fn main() { protoc_rust::Codegen::new() .out_dir("src/protos") .inputs(&["protos/a.proto", "protos/b.proto"]) .include("protos") .run() .expect("Running protoc failed."); } ``` and in `build.rs`: ```toml [build-dependencies] protoc-rust = "2" ``` It is advisable that `protoc-rust` build-dependency version be the same as `protobuf` dependency. The alternative is to use [`protobuf-codegen-pure` crate](https://docs.rs/protobuf-codegen-pure). # Protoc binary This crate searches for `protoc` binary in `$PATH` by default. `protoc` binary can be obtained using [`protoc-bin-vendored` crate](https://docs.rs/protoc-bin-vendored) and supplied to `Codegen` object. # This is version 2 In branch 3 of rust-protobuf this functionality is provided by [`protobuf-codegen` crate](https://docs.rs/protobuf-codegen/%3E=3.0.0-alpha). protoc-rust-2.27.1/src/lib.rs000064400000000000000000000207400072674642500141540ustar 00000000000000//! # API to generate `.rs` files using `protoc` to parse files //! //! This API requires `protoc` command present in `$PATH` //! or explicitly passed to `Codegen` object //! (but `protoc` *plugin* is not needed). //! //! ```no_run //! extern crate protoc_rust; //! //! fn main() { //! protoc_rust::Codegen::new() //! .out_dir("src/protos") //! .inputs(&["protos/a.proto", "protos/b.proto"]) //! .include("protos") //! .run() //! .expect("Running protoc failed."); //! } //! ``` //! //! and in `build.rs`: //! //! ```toml //! [build-dependencies] //! protoc-rust = "2" //! ``` //! //! It is advisable that `protoc-rust` build-dependency version be the same as //! `protobuf` dependency. //! //! The alternative is to use //! [`protobuf-codegen-pure` crate](https://docs.rs/protobuf-codegen-pure). //! //! # Protoc binary //! //! This crate searches for `protoc` binary in `$PATH` by default. //! //! `protoc` binary can be obtained using //! [`protoc-bin-vendored` crate](https://docs.rs/protoc-bin-vendored) //! and supplied to `Codegen` object. //! //! # This is version 2 //! //! In branch 3 of rust-protobuf this functionality is provided by //! [`protobuf-codegen` crate](https://docs.rs/protobuf-codegen/%3E=3.0.0-alpha). #![deny(missing_docs)] #![deny(rustdoc::broken_intra_doc_links)] extern crate tempfile; extern crate protobuf; extern crate protobuf_codegen; extern crate protoc; mod slashes; use std::fs; use std::io; use std::io::Read; use std::path::Path; use std::path::PathBuf; use protobuf::descriptor::FileDescriptorSet; use protobuf::Message; pub use protobuf_codegen::Customize; pub use protoc::Error; use protoc::Protoc; pub use protoc::Result; use slashes::Slashes; /// `Protoc --rust_out...` args #[derive(Debug, Default)] #[deprecated(since = "2.14", note = "Use Codegen instead")] pub struct Args<'a> { /// --lang_out= param pub out_dir: &'a str, /// -I args pub includes: &'a [&'a str], /// List of .proto files to compile pub input: &'a [&'a str], /// Customize code generation pub customize: Customize, } /// `Protoc --rust_out...` args #[derive(Debug, Default)] pub struct Codegen { /// --lang_out= param out_dir: PathBuf, /// -I args includes: Vec, /// List of .proto files to compile inputs: Vec, /// Customize code generation customize: Customize, /// Protoc command path protoc: Option, } impl Codegen { /// Arguments to the `protoc` found in `$PATH` pub fn new() -> Self { Self::default() } /// Set `--LANG_out=...` param pub fn out_dir(&mut self, out_dir: impl AsRef) -> &mut Self { self.out_dir = out_dir.as_ref().to_owned(); self } /// Append a path to `-I` args pub fn include(&mut self, include: impl AsRef) -> &mut Self { self.includes.push(include.as_ref().to_owned()); self } /// Append multiple paths to `-I` args pub fn includes(&mut self, includes: impl IntoIterator>) -> &mut Self { for include in includes { self.include(include); } self } /// Append a `.proto` file path to compile pub fn input(&mut self, input: impl AsRef) -> &mut Self { self.inputs.push(input.as_ref().to_owned()); self } /// Append multiple `.proto` file paths to compile pub fn inputs(&mut self, inputs: impl IntoIterator>) -> &mut Self { for input in inputs { self.input(input); } self } /// Specify `protoc` command path to be used when invoking code generation. /// /// # Examples /// /// ```no_run /// # mod protoc_bin_vendored { /// # pub fn protoc_bin_path() -> Result { /// # unimplemented!() /// # } /// # } /// /// use protoc_rust::Codegen; /// /// Codegen::new() /// .protoc_path(protoc_bin_vendored::protoc_bin_path().unwrap()) /// // ... /// .run() /// .unwrap(); /// ``` pub fn protoc_path(&mut self, protoc: impl Into) -> &mut Self { self.protoc = Some(Protoc::from_path(&protoc.into().to_str().unwrap())); self } /// Set options to customize code generation pub fn customize(&mut self, customize: Customize) -> &mut Self { self.customize = customize; self } /// Like `protoc --rust_out=...` but without requiring `protoc-gen-rust` command in `$PATH`. pub fn run(&self) -> Result<()> { let protoc = match self.protoc.clone() { Some(protoc) => protoc, None => Protoc::from_env_path(), }; protoc.check()?; let temp_dir = tempfile::Builder::new().prefix("protoc-rust").tempdir()?; let temp_file = temp_dir.path().join("descriptor.pbbin"); let includes: Vec<&str> = self.includes.iter().map(|p| p.to_str().unwrap()).collect(); let inputs: Vec<&str> = self.inputs.iter().map(|p| p.to_str().unwrap()).collect(); protoc.write_descriptor_set(protoc::DescriptorSetOutArgs { out: temp_file.as_os_str().to_str().unwrap(), includes: &includes, input: &inputs, include_imports: true, })?; let mut fds = Vec::new(); let mut file = fs::File::open(temp_file)?; file.read_to_end(&mut fds)?; drop(file); drop(temp_dir); let fds = FileDescriptorSet::parse_from_bytes(&fds) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; let default_includes = vec![PathBuf::from(".")]; let includes = if self.includes.is_empty() { &default_includes } else { &self.includes }; let mut files_to_generate = Vec::new(); 'outer: for file in &self.inputs { for include in includes { if let Some(truncated) = remove_path_prefix(file.to_str().unwrap(), include.to_str().unwrap()) { files_to_generate.push(truncated.to_owned()); continue 'outer; } } return Err(Error::new( io::ErrorKind::Other, format!("file {:?} is not found in includes {:?}", file, includes), )); } protobuf_codegen::gen_and_write( fds.get_file(), &files_to_generate, &self.out_dir, &self.customize, ) } } /// Like `protoc --rust_out=...` but without requiring `protoc-gen-rust` command in `$PATH`. #[deprecated(since = "2.14", note = "Use Codegen instead")] #[allow(deprecated)] pub fn run(args: Args) -> Result<()> { Codegen::new() .out_dir(args.out_dir) .includes(args.includes) .inputs(args.input) .customize(args.customize) .run() } fn remove_path_prefix(mut path: &str, mut prefix: &str) -> Option { let slashes = Slashes::here(); path = slashes.remove_dot_slashes(path); prefix = slashes.remove_dot_slashes(prefix); if prefix == "" { return Some(path.to_owned()); } let path = slashes.norm_path(path); let mut prefix = slashes.norm_path(prefix); if prefix.ends_with("/") { let l = prefix.len(); prefix.truncate(l - 1); } if !path.starts_with(&prefix) { return None; } if path.len() <= prefix.len() { return None; } if path.as_bytes()[prefix.len()] == b'/' { return Some(path[prefix.len() + 1..].to_owned()); } else { return None; } } #[cfg(test)] mod test { #[test] fn remove_path_prefix() { assert_eq!( Some("abc.proto".to_owned()), super::remove_path_prefix("xxx/abc.proto", "xxx") ); assert_eq!( Some("abc.proto".to_owned()), super::remove_path_prefix("xxx/abc.proto", "xxx/") ); assert_eq!( Some("abc.proto".to_owned()), super::remove_path_prefix("../xxx/abc.proto", "../xxx/") ); assert_eq!( Some("abc.proto".to_owned()), super::remove_path_prefix("abc.proto", ".") ); assert_eq!( Some("abc.proto".to_owned()), super::remove_path_prefix("abc.proto", "./") ); assert_eq!(None, super::remove_path_prefix("xxx/abc.proto", "yyy")); assert_eq!(None, super::remove_path_prefix("xxx/abc.proto", "yyy/")); } } protoc-rust-2.27.1/src/slashes.rs000064400000000000000000000031150072674642500150450ustar 00000000000000pub(crate) enum Slashes { Unix, Windows, } impl Slashes { pub fn here() -> Slashes { if cfg!(windows) { Slashes::Windows } else if cfg!(unix) { Slashes::Unix } else { panic!("Unknown operating system") } } fn slashes(&self) -> &'static [char] { match self { &Slashes::Unix => &['/'], &Slashes::Windows => &['/', '\\'], } } fn _is_slash(&self, c: char) -> bool { self.slashes().contains(&c) } pub fn norm_path(&self, path: &str) -> String { match self { &Slashes::Unix => path.to_owned(), &Slashes::Windows => path.replace('\\', "/"), } } fn remove_dot_slash<'a>(&self, path: &'a str) -> &'a str { if path == "." { "" } else if path.starts_with(".") { let mut temp_path = &path[1..]; let mut at_least_one_slash = false; while temp_path.starts_with(self.slashes()) { temp_path = &temp_path[1..]; at_least_one_slash = true; } if at_least_one_slash { temp_path } else { path } } else { path } } /// Remove leading ./ from path pub fn remove_dot_slashes<'a>(&self, mut path: &'a str) -> &'a str { loop { let new_path = self.remove_dot_slash(path); if new_path == path { return new_path; } path = new_path; } } }