protoc-2.27.1/.cargo_vcs_info.json0000644000000001440000000000100124320ustar { "git": { "sha1": "ec31ce829473039ac598ca6fdcb245cbd6fa82ba" }, "path_in_vcs": "protoc" }protoc-2.27.1/Cargo.toml0000644000000016700000000000100104350ustar # 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" version = "2.27.1" authors = ["Stepan Koltsov "] description = """ Protobuf protoc command as API """ homepage = "https://github.com/stepancheg/rust-protobuf/tree/master/protoc/" license = "MIT" repository = "https://github.com/stepancheg/rust-protobuf/tree/master/protoc/" [package.metadata.docs.rs] all-features = true [lib] doctest = false bench = false [dependencies.log] version = "0.*" [dependencies.which] version = "4.0" protoc-2.27.1/Cargo.toml.orig000064400000000000000000000007050072674642500141440ustar 00000000000000[package] name = "protoc" version = "2.27.1" authors = ["Stepan Koltsov "] license = "MIT" homepage = "https://github.com/stepancheg/rust-protobuf/tree/master/protoc/" repository = "https://github.com/stepancheg/rust-protobuf/tree/master/protoc/" description = """ Protobuf protoc command as API """ [lib] doctest = false bench = false [dependencies] log = "0.*" which = "4.0" [package.metadata.docs.rs] all-features = true protoc-2.27.1/LICENSE.txt000064400000000000000000000020410072674642500130730ustar 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-2.27.1/README.md000064400000000000000000000005440072674642500125350ustar 00000000000000 # API to invoke `protoc` command programmatically API to invoke `protoc` command using API (e. g. from `build.rs`). Note that to generate `rust` code from `.proto`, [protoc-rust](https://docs.rs/protoc-rust) crate can be used, which does not require `protoc-gen-rust` present in `$PATH`. protoc-2.27.1/src/lib.rs000064400000000000000000000264340072674642500131670ustar 00000000000000//! # API to invoke `protoc` command programmatically //! //! API to invoke `protoc` command using API (e. g. from `build.rs`). //! //! Note that to generate `rust` code from `.proto`, //! [protoc-rust](https://docs.rs/protoc-rust) crate can be used, //! which does not require `protoc-gen-rust` present in `$PATH`. #![deny(missing_docs)] #![deny(rustdoc::broken_intra_doc_links)] use std::ffi::OsStr; use std::ffi::OsString; use std::io; use std::path::Path; use std::path::PathBuf; use std::process; #[macro_use] extern crate log; /// Alias for io::Error pub type Error = io::Error; /// Alias for io::Error pub type Result = io::Result; fn err_other(s: impl AsRef) -> Error { Error::new(io::ErrorKind::Other, s.as_ref().to_owned()) } /// `protoc --lang_out=... ...` command builder and spawner. /// /// # Examples /// /// ```no_run /// use protoc::ProtocLangOut; /// ProtocLangOut::new() /// .lang("go") /// .include("protos") /// .include("more-protos") /// .out_dir("generated-protos") /// .run() /// .unwrap(); /// ``` #[derive(Default)] pub struct ProtocLangOut { protoc: Option, /// `LANG` part in `--LANG_out=...` lang: Option, /// `--LANG_out=...` param out_dir: Option, /// `--plugin` param. Not needed if plugin is in `$PATH` plugin: Option, /// `-I` args includes: Vec, /// List of `.proto` files to compile inputs: Vec, } impl ProtocLangOut { /// Arguments to the `protoc` found in `$PATH` pub fn new() -> Self { Self::default() } /// Set `LANG` part in `--LANG_out=...` pub fn lang(&mut self, lang: &str) -> &mut Self { self.lang = Some(lang.to_owned()); self } /// Set `--LANG_out=...` param pub fn out_dir(&mut self, out_dir: impl AsRef) -> &mut Self { self.out_dir = Some(out_dir.as_ref().to_owned()); self } /// Set `--plugin` param. Not needed if plugin is in `$PATH` pub fn plugin(&mut self, plugin: impl AsRef) -> &mut Self { self.plugin = Some(plugin.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 } /// Execute `protoc` with given args pub fn run(&self) -> Result<()> { let protoc = match &self.protoc { Some(protoc) => protoc.clone(), None => { let protoc = Protoc::from_env_path(); // Check with have good `protoc` protoc.check()?; protoc } }; if self.inputs.is_empty() { return Err(err_other("input is empty")); } let out_dir = self .out_dir .as_ref() .ok_or_else(|| err_other("out_dir is empty"))?; let lang = self .lang .as_ref() .ok_or_else(|| err_other("lang is empty"))?; // --{lang}_out={out_dir} let mut lang_out_flag = OsString::from("--"); lang_out_flag.push(lang); lang_out_flag.push("_out="); lang_out_flag.push(out_dir); // --plugin={plugin} let plugin_flag = self.plugin.as_ref().map(|plugin| { let mut flag = OsString::from("--plugin="); flag.push(plugin); flag }); // -I{include} let include_flags = self.includes.iter().map(|include| { let mut flag = OsString::from("-I"); flag.push(include); flag }); let mut cmd_args = Vec::new(); cmd_args.push(lang_out_flag); cmd_args.extend(self.inputs.iter().map(|path| path.as_os_str().to_owned())); cmd_args.extend(plugin_flag); cmd_args.extend(include_flags); protoc.run_with_args(cmd_args) } } /// `Protoc --lang_out...` args #[derive(Default)] #[deprecated(since = "2.13", note = "Use ProtocLangOut instead")] pub struct Args<'a> { /// `LANG` part in `--LANG_out=...` pub lang: &'a str, /// `--LANG_out=...` param pub out_dir: &'a str, /// `--plugin` param. Not needed if plugin is in `$PATH` pub plugin: Option<&'a str>, /// `-I` args pub includes: &'a [&'a str], /// List of `.proto` files to compile pub input: &'a [&'a str], } /// `Protoc --descriptor_set_out...` args #[derive(Debug)] pub struct DescriptorSetOutArgs<'a> { /// `--file_descriptor_out=...` param pub out: &'a str, /// `-I` args pub includes: &'a [&'a str], /// List of `.proto` files to compile pub input: &'a [&'a str], /// `--include_imports` pub include_imports: bool, } /// Protoc command. #[derive(Clone, Debug)] pub struct Protoc { exec: OsString, } impl Protoc { /// New `protoc` command from `$PATH` pub fn from_env_path() -> Protoc { match which::which("protoc") { Ok(path) => Protoc { exec: path.into_os_string(), }, Err(e) => { panic!("protoc binary not found: {}", e); } } } /// New `protoc` command from specified path /// /// # Examples /// /// ```no_run /// # mod protoc_bin_vendored { /// # pub fn protoc_bin_path() -> Result { /// # unimplemented!() /// # } /// # } /// /// // Use a binary from `protoc-bin-vendored` crate /// let protoc = protoc::Protoc::from_path( /// protoc_bin_vendored::protoc_bin_path().unwrap()); /// ``` pub fn from_path(path: impl AsRef) -> Protoc { Protoc { exec: path.as_ref().to_owned(), } } /// Check `protoc` command found and valid pub fn check(&self) -> Result<()> { self.version().map(|_| ()) } fn spawn(&self, cmd: &mut process::Command) -> io::Result { info!("spawning command {:?}", cmd); cmd.spawn() .map_err(|e| Error::new(e.kind(), format!("failed to spawn `{:?}`: {}", cmd, e))) } /// Obtain `protoc` version pub fn version(&self) -> Result { let child = self.spawn( process::Command::new(&self.exec) .stdin(process::Stdio::null()) .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) .args(&["--version"]), )?; let output = child.wait_with_output()?; if !output.status.success() { return Err(err_other("protoc failed with error")); } let output = String::from_utf8(output.stdout).map_err(|e| Error::new(io::ErrorKind::Other, e))?; let output = match output.lines().next() { None => return Err(err_other("output is empty")), Some(line) => line, }; let prefix = "libprotoc "; if !output.starts_with(prefix) { return Err(err_other("output does not start with prefix")); } let output = &output[prefix.len()..]; if output.is_empty() { return Err(err_other("version is empty")); } let first = output.chars().next().unwrap(); if !first.is_digit(10) { return Err(err_other("version does not start with digit")); } Ok(Version { version: output.to_owned(), }) } /// Execute `protoc` command with given args, check it completed correctly. fn run_with_args(&self, args: Vec) -> Result<()> { let mut cmd = process::Command::new(&self.exec); cmd.stdin(process::Stdio::null()); cmd.args(args); let mut child = self.spawn(&mut cmd)?; if !child.wait()?.success() { return Err(err_other(&format!( "protoc ({:?}) exited with non-zero exit code", cmd ))); } Ok(()) } /// Execute configured `protoc` with given args #[deprecated(since = "2.13", note = "Use ProtocLangOut instead")] #[allow(deprecated)] pub fn run(&self, args: Args) -> Result<()> { let mut cmd_args: Vec = Vec::new(); if args.out_dir.is_empty() { return Err(err_other("out_dir is empty")); } if args.lang.is_empty() { return Err(err_other("lang is empty")); } cmd_args.push(format!("--{}_out={}", args.lang, args.out_dir).into()); if args.input.is_empty() { return Err(err_other("input is empty")); } cmd_args.extend(args.input.into_iter().map(|a| OsString::from(*a))); if let Some(plugin) = args.plugin { cmd_args.push(format!("--plugin={}", plugin).into()); } for include in args.includes { cmd_args.push(format!("-I{}", include).into()); } self.run_with_args(cmd_args) } /// Execute `protoc --descriptor_set_out=` pub fn write_descriptor_set(&self, args: DescriptorSetOutArgs) -> Result<()> { let mut cmd_args: Vec = Vec::new(); for include in args.includes { cmd_args.push(format!("-I{}", include).into()); } if args.out.is_empty() { return Err(err_other("out is empty")); } cmd_args.push(format!("--descriptor_set_out={}", args.out).into()); if args.include_imports { cmd_args.push("--include_imports".into()); } if args.input.is_empty() { return Err(err_other("input is empty")); } cmd_args.extend(args.input.into_iter().map(|a| OsString::from(*a))); self.run_with_args(cmd_args) } } /// Deprecated version of [`ProtocLangOut`]. #[deprecated(since = "2.13", note = "Use ProtocLangOut instead")] #[allow(deprecated)] pub fn run(args: Args) -> Result<()> { let mut protoc_lang_out = ProtocLangOut::new(); if !args.lang.is_empty() { protoc_lang_out.lang(args.lang); } if !args.out_dir.is_empty() { protoc_lang_out.out_dir(args.out_dir); } if let Some(plugin) = args.plugin { protoc_lang_out.plugin(plugin); } if !args.includes.is_empty() { protoc_lang_out.includes(args.includes); } if !args.input.is_empty() { protoc_lang_out.inputs(args.input); } protoc_lang_out.run() } /// Protobuf (protoc) version. pub struct Version { version: String, } impl Version { /// `true` if the protoc major version is 3. pub fn is_3(&self) -> bool { self.version.starts_with("3") } } #[cfg(test)] mod test { use super::*; #[test] fn version() { Protoc::from_env_path().version().expect("version"); } } protoc-2.27.1/test.sh000075500000000000000000000004110072674642500125650ustar 00000000000000#!/bin/sh -e cd $(dirname $0) ( echo "building protoc-gen-rust" cd ../protobuf-codegen cargo build --bin=protoc-gen-rust ) echo "cargo check in test-protoc" cd test-protoc exec cargo check --features=$RUST_PROTOBUF_FEATURES # vim: set ts=4 sw=4 et: