1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #[cfg(feature = "cargo")]
16 pub mod ukey2_all_proto {
17     include!(concat!(env!("OUT_DIR"), "/proto/mod.rs"));
18 }
19 
20 #[cfg(not(feature = "cargo"))]
21 pub mod ukey2_all_proto {
22     pub mod device_to_device_messages;
23     pub mod securegcm;
24     pub mod securemessage;
25     pub mod ukey;
26 }
27 
28 pub use protobuf;
29 
30 #[cfg(all(test, feature = "cargo"))]
31 mod tests {
32     use std::{fs, path::Path};
33 
34     #[test]
check_proto_needs_update()35     fn check_proto_needs_update() {
36         let proto_src_dir = concat!(env!("CARGO_MANIFEST_DIR"), "/src/ukey2_all_proto/");
37         for file in fs::read_dir(proto_src_dir).unwrap() {
38             let actual_file = file.unwrap();
39             let file_name_str = actual_file.file_name();
40             if actual_file.file_type().unwrap().is_file()
41                 && file_name_str.to_string_lossy().ends_with(".rs")
42             {
43                 println!("Checking file {}", &file_name_str.to_string_lossy());
44                 let newly_generated_file_path =
45                     env!("OUT_DIR").to_string() + "/proto/" + &file_name_str.to_string_lossy();
46                 let current_file_path = proto_src_dir.to_owned() + file_name_str.to_str().unwrap();
47                 if let Some(diff_str) = diff_file(&newly_generated_file_path, &current_file_path) {
48                     panic!(
49                         "file '{}' needs to be updated.\n\n{}\n",
50                         file_name_str.to_string_lossy(),
51                         diff_str
52                     );
53                 }
54             }
55         }
56     }
57 
58     // Ignore the first 17 lines of the generated proto files, since that contains the apache header and
59     // version numbers of rust-protobuf and protoc that may differ based on the host machine configuration.
60     const DIFF_IGNORE_LINES: usize = 17;
61 
diff_file<P: AsRef<Path>>(left: P, right: P) -> Option<String>62     fn diff_file<P: AsRef<Path>>(left: P, right: P) -> Option<String> {
63         let left_content = fs::read_to_string(left).unwrap();
64         let right_content = fs::read_to_string(right).unwrap();
65         let diff = &diff::lines(&left_content, &right_content)[DIFF_IGNORE_LINES..];
66         let line_diffs = diff
67             .iter()
68             .filter_map(|d| match d {
69                 diff::Result::Left(l) => Some(format!("-{l}")),
70                 diff::Result::Both(_, _) => None,
71                 diff::Result::Right(r) => Some(format!("+{r}")),
72             })
73             .collect::<Vec<String>>();
74         if line_diffs.is_empty() {
75             None
76         } else {
77             Some(line_diffs.join("\n"))
78         }
79     }
80 }
81