xref: /aosp_15_r20/external/bazelbuild-rules_rust/util/process_wrapper/util.rs (revision d4726bddaa87cc4778e7472feed243fa4b6c267f)
1 // Copyright 2020 The Bazel Authors. All rights reserved.
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 use std::fs::File;
16 use std::io::{BufRead, BufReader, Read};
17 
read_file_to_array(path: &str) -> Result<Vec<String>, String>18 pub(crate) fn read_file_to_array(path: &str) -> Result<Vec<String>, String> {
19     let file = File::open(path).map_err(|e| e.to_string()).map_err(|err| {
20         format!(
21             "{} reading path: {:?}, current directory: {:?}",
22             err,
23             path,
24             std::env::current_dir()
25         )
26     })?;
27 
28     read_to_array(file)
29 }
30 
read_stamp_status_to_array(path: String) -> Result<Vec<(String, String)>, String>31 pub(crate) fn read_stamp_status_to_array(path: String) -> Result<Vec<(String, String)>, String> {
32     let file = File::open(path).map_err(|e| e.to_string())?;
33     stamp_status_to_array(file)
34 }
35 
read_to_array(reader: impl Read) -> Result<Vec<String>, String>36 fn read_to_array(reader: impl Read) -> Result<Vec<String>, String> {
37     let reader = BufReader::new(reader);
38     let mut ret = vec![];
39     let mut escaped_line = String::new();
40     for l in reader.lines() {
41         let line = l.map_err(|e| e.to_string())?;
42         if line.is_empty() {
43             continue;
44         }
45         // a \ at the end of a line allows us to escape the new line break,
46         // \\ yields a single \, so \\\ translates to a single \ and a new line
47         // escape
48         let end_backslash_count = line.chars().rev().take_while(|&c| c == '\\').count();
49         // a 0 or even number of backslashes do not lead to a new line escape
50         let escape = end_backslash_count % 2 == 1;
51         //  remove backslashes and add back two for every one
52         let l = line.trim_end_matches('\\');
53         escaped_line.push_str(l);
54         for _ in 0..end_backslash_count / 2 {
55             escaped_line.push('\\');
56         }
57         if escape {
58             // we add a newline as we expect a line after this
59             escaped_line.push('\n');
60         } else {
61             ret.push(escaped_line);
62             escaped_line = String::new();
63         }
64     }
65     Ok(ret)
66 }
67 
stamp_status_to_array(reader: impl Read) -> Result<Vec<(String, String)>, String>68 fn stamp_status_to_array(reader: impl Read) -> Result<Vec<(String, String)>, String> {
69     let escaped_lines = read_to_array(reader)?;
70     escaped_lines
71         .into_iter()
72         .map(|l| {
73             let (s1, s2) = l
74                 .split_once(' ')
75                 .ok_or_else(|| format!("wrong workspace status file format for \"{l}\""))?;
76             Ok((s1.to_owned(), s2.to_owned()))
77         })
78         .collect()
79 }
80 
81 #[cfg(test)]
82 mod test {
83     use super::*;
84 
85     #[test]
test_read_to_array()86     fn test_read_to_array() {
87         let input = r"some escaped \\\
88 string
89 with other lines"
90             .to_owned();
91         let expected = vec![
92             r"some escaped \
93 string",
94             "with other lines",
95         ];
96         let got = read_to_array(input.as_bytes()).unwrap();
97         assert_eq!(expected, got);
98     }
99 
100     #[test]
test_stamp_status_to_array()101     fn test_stamp_status_to_array() {
102         let lines = "aaa bbb\\\nvvv\nccc ddd\neee fff";
103         let got = stamp_status_to_array(lines.as_bytes()).unwrap();
104         let expected = vec![
105             ("aaa".to_owned(), "bbb\nvvv".to_owned()),
106             ("ccc".to_owned(), "ddd".to_owned()),
107             ("eee".to_owned(), "fff".to_owned()),
108         ];
109         assert_eq!(expected, got);
110     }
111 }
112