protoc_bin_vendored/
lib.rs1#![deny(missing_docs)]
24#![deny(rustdoc::broken_intra_doc_links)]
25
26use std::env;
27use std::fmt;
28use std::path::PathBuf;
29
30#[derive(Debug)]
32pub struct Error {
33 os: &'static str,
34 arch: &'static str,
35}
36
37impl fmt::Display for Error {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(
40 f,
41 "protoc binary cannot be found for platform {}-{}",
42 self.os, self.arch
43 )
44 }
45}
46
47impl std::error::Error for Error {}
48
49#[allow(non_camel_case_types)]
50enum ArchCrate {
51 Linux_X86_32,
52 Linux_X86_64,
53 Linux_Aarch_64,
54 Linux_Ppcle_64,
55 Linux_S390_64,
56 Macos_Aarch_64,
57 Macos_x86_64,
58 Win32,
59}
60
61impl ArchCrate {
62 fn detect() -> Result<ArchCrate, Error> {
63 Ok(match (env::consts::OS, env::consts::ARCH) {
64 ("linux", "x86") => ArchCrate::Linux_X86_32,
65 ("linux", "x86_64") => ArchCrate::Linux_X86_64,
66 ("linux", "aarch64") => ArchCrate::Linux_Aarch_64,
67 ("linux", "powerpc64") => ArchCrate::Linux_Ppcle_64,
68 ("linux", "s390x") => ArchCrate::Linux_S390_64,
69 ("macos", "x86_64") => ArchCrate::Macos_x86_64,
70 ("macos", "aarch64") => ArchCrate::Macos_Aarch_64,
71 ("windows", _) => ArchCrate::Win32,
72 (os, arch) => return Err(Error { os, arch }),
73 })
74 }
75}
76
77pub fn protoc_bin_path() -> Result<PathBuf, Error> {
82 Ok(match ArchCrate::detect()? {
83 ArchCrate::Linux_X86_32 => protoc_bin_vendored_linux_x86_32::protoc_bin_path(),
84 ArchCrate::Linux_X86_64 => protoc_bin_vendored_linux_x86_64::protoc_bin_path(),
85 ArchCrate::Linux_Aarch_64 => protoc_bin_vendored_linux_aarch_64::protoc_bin_path(),
86 ArchCrate::Linux_Ppcle_64 => protoc_bin_vendored_linux_ppcle_64::protoc_bin_path(),
87 ArchCrate::Linux_S390_64 => protoc_bin_vendored_linux_s390_64::protoc_bin_path(),
88 ArchCrate::Macos_Aarch_64 => protoc_bin_vendored_macos_aarch_64::protoc_bin_path(),
89 ArchCrate::Macos_x86_64 => protoc_bin_vendored_macos_x86_64::protoc_bin_path(),
90 ArchCrate::Win32 => protoc_bin_vendored_win32::protoc_bin_path(),
91 })
92}
93
94pub(crate) fn include_path_for_arch(arch_crate: &ArchCrate) -> PathBuf {
95 match arch_crate {
96 ArchCrate::Linux_X86_32 => protoc_bin_vendored_linux_x86_32::include_path(),
97 ArchCrate::Linux_X86_64 => protoc_bin_vendored_linux_x86_64::include_path(),
98 ArchCrate::Linux_Aarch_64 => protoc_bin_vendored_linux_aarch_64::include_path(),
99 ArchCrate::Linux_Ppcle_64 => protoc_bin_vendored_linux_ppcle_64::include_path(),
100 ArchCrate::Linux_S390_64 => protoc_bin_vendored_linux_s390_64::include_path(),
101 ArchCrate::Macos_Aarch_64 => protoc_bin_vendored_macos_aarch_64::include_path(),
102 ArchCrate::Macos_x86_64 => protoc_bin_vendored_macos_x86_64::include_path(),
103 ArchCrate::Win32 => protoc_bin_vendored_win32::include_path(),
104 }
105}
106
107pub fn include_path() -> Result<PathBuf, Error> {
111 Ok(include_path_for_arch(&ArchCrate::detect()?))
112}
113
114#[cfg(test)]
115mod test {
116 use std::fs;
117 use std::io::Read;
118 use std::path::Path;
119 use std::path::PathBuf;
120 use std::process;
121
122 use crate::include_path_for_arch;
123 use crate::ArchCrate;
124
125 #[test]
126 fn include_path() {
127 assert!(crate::include_path()
128 .unwrap()
129 .join("google/protobuf/descriptor.proto")
130 .exists());
131 }
132
133 #[test]
134 fn arch_crates_includes_identical() {
135 fn compare_recursively(a: &Path, b: &Path) {
136 assert_eq!(a.is_file(), b.is_file());
137 if a.is_file() {
138 let a_content = fs::read(a).unwrap();
139 let b_content = fs::read(b).unwrap();
140 assert_eq!(a_content, b_content);
141 } else {
142 let mut a_files: Vec<PathBuf> = fs::read_dir(a)
143 .unwrap()
144 .map(|e| e.unwrap().path())
145 .collect();
146 let mut b_files: Vec<PathBuf> = fs::read_dir(b)
147 .unwrap()
148 .map(|e| e.unwrap().path())
149 .collect();
150 a_files.sort();
151 b_files.sort();
152 let mut a_files = a_files.as_slice();
153 let mut b_files = b_files.as_slice();
154 while !a_files.is_empty() || !b_files.is_empty() {
155 let (a_next, a_rem) = a_files.split_first().unwrap();
156 let (b_next, b_rem) = b_files.split_first().unwrap();
157
158 compare_recursively(a_next, b_next);
159
160 a_files = a_rem;
161 b_files = b_rem;
162 }
163 assert!(a_files.is_empty());
164 assert!(b_files.is_empty());
165 }
166 }
167
168 compare_recursively(
169 &include_path_for_arch(&ArchCrate::Linux_X86_64),
170 &include_path_for_arch(&ArchCrate::Linux_X86_64),
171 );
172 compare_recursively(
173 &include_path_for_arch(&ArchCrate::Linux_X86_64),
174 &include_path_for_arch(&ArchCrate::Linux_X86_32),
175 );
176 compare_recursively(
177 &include_path_for_arch(&ArchCrate::Linux_X86_64),
178 &include_path_for_arch(&ArchCrate::Linux_Aarch_64),
179 );
180 compare_recursively(
181 &include_path_for_arch(&ArchCrate::Linux_X86_64),
182 &include_path_for_arch(&ArchCrate::Linux_Ppcle_64),
183 );
184 compare_recursively(
185 &include_path_for_arch(&ArchCrate::Linux_X86_64),
186 &include_path_for_arch(&ArchCrate::Linux_S390_64),
187 );
188 compare_recursively(
189 &include_path_for_arch(&ArchCrate::Linux_X86_64),
190 &include_path_for_arch(&ArchCrate::Macos_Aarch_64),
191 );
192 compare_recursively(
193 &include_path_for_arch(&ArchCrate::Linux_X86_64),
194 &include_path_for_arch(&ArchCrate::Macos_x86_64),
195 );
196 compare_recursively(
197 &include_path_for_arch(&ArchCrate::Linux_X86_64),
198 &include_path_for_arch(&ArchCrate::Win32),
199 );
200 }
201
202 #[test]
203 fn smoke() {
204 let process = process::Command::new(crate::protoc_bin_path().unwrap())
205 .arg("--version")
206 .stdin(process::Stdio::null())
207 .stdout(process::Stdio::piped())
208 .spawn()
209 .unwrap();
210 let mut stdout = String::new();
211 process.stdout.unwrap().read_to_string(&mut stdout).unwrap();
212 assert!(stdout.contains("libprotoc"), "stdout is: {:?}", stdout)
213 }
214}