xref: /aosp_15_r20/system/librustutils/system_properties/parsers_formatters.rs (revision e51878c104ea269309bae357ae559a9fff179380)
1*e51878c1SAndroid Build Coastguard Worker //! Parsers and formatters.
2*e51878c1SAndroid Build Coastguard Worker //!
3*e51878c1SAndroid Build Coastguard Worker //! These functions should only be used in the system properties generated code.
4*e51878c1SAndroid Build Coastguard Worker 
5*e51878c1SAndroid Build Coastguard Worker use std::str::FromStr;
6*e51878c1SAndroid Build Coastguard Worker use std::string::ToString;
7*e51878c1SAndroid Build Coastguard Worker 
8*e51878c1SAndroid Build Coastguard Worker type Result<T> = std::result::Result<T, String>;
9*e51878c1SAndroid Build Coastguard Worker 
10*e51878c1SAndroid Build Coastguard Worker // Parsers.
11*e51878c1SAndroid Build Coastguard Worker 
12*e51878c1SAndroid Build Coastguard Worker /// Parses the given string as a `T`, or returns an error including the string value.
parse<T: FromStr>(s: &str) -> Result<T>13*e51878c1SAndroid Build Coastguard Worker pub fn parse<T: FromStr>(s: &str) -> Result<T> {
14*e51878c1SAndroid Build Coastguard Worker     s.parse::<T>()
15*e51878c1SAndroid Build Coastguard Worker         .map_err(|_| format!("Can't convert '{}' to '{}'.", s, std::any::type_name::<T>()))
16*e51878c1SAndroid Build Coastguard Worker }
17*e51878c1SAndroid Build Coastguard Worker 
18*e51878c1SAndroid Build Coastguard Worker /// Parses the given string as a boolean or returns an error message including the string.
19*e51878c1SAndroid Build Coastguard Worker ///
20*e51878c1SAndroid Build Coastguard Worker /// `true` and `1` are both considered true, `false` and `0` are false. Any other value is invalid.
parse_bool(s: &str) -> Result<bool>21*e51878c1SAndroid Build Coastguard Worker pub fn parse_bool(s: &str) -> Result<bool> {
22*e51878c1SAndroid Build Coastguard Worker     match s {
23*e51878c1SAndroid Build Coastguard Worker         "1" | "true" => Ok(true),
24*e51878c1SAndroid Build Coastguard Worker         "0" | "false" => Ok(false),
25*e51878c1SAndroid Build Coastguard Worker         _ => Err(format!("Can't convert '{}' to 'bool'.", s)),
26*e51878c1SAndroid Build Coastguard Worker     }
27*e51878c1SAndroid Build Coastguard Worker }
28*e51878c1SAndroid Build Coastguard Worker 
parse_list_with<T, F>(s: &str, f: F) -> Result<Vec<T>> where F: Fn(&str) -> Result<T>,29*e51878c1SAndroid Build Coastguard Worker fn parse_list_with<T, F>(s: &str, f: F) -> Result<Vec<T>>
30*e51878c1SAndroid Build Coastguard Worker where
31*e51878c1SAndroid Build Coastguard Worker     F: Fn(&str) -> Result<T>,
32*e51878c1SAndroid Build Coastguard Worker {
33*e51878c1SAndroid Build Coastguard Worker     let mut result = Vec::new();
34*e51878c1SAndroid Build Coastguard Worker     if s.is_empty() {
35*e51878c1SAndroid Build Coastguard Worker         return Ok(result);
36*e51878c1SAndroid Build Coastguard Worker     }
37*e51878c1SAndroid Build Coastguard Worker 
38*e51878c1SAndroid Build Coastguard Worker     let mut chars = s.chars();
39*e51878c1SAndroid Build Coastguard Worker     let mut current = chars.next();
40*e51878c1SAndroid Build Coastguard Worker     while current.is_some() {
41*e51878c1SAndroid Build Coastguard Worker         // Extract token.
42*e51878c1SAndroid Build Coastguard Worker         let mut token = String::with_capacity(s.len());
43*e51878c1SAndroid Build Coastguard Worker         while let Some(value) = current {
44*e51878c1SAndroid Build Coastguard Worker             if value == ',' {
45*e51878c1SAndroid Build Coastguard Worker                 break;
46*e51878c1SAndroid Build Coastguard Worker             }
47*e51878c1SAndroid Build Coastguard Worker             if value == '\\' {
48*e51878c1SAndroid Build Coastguard Worker                 current = chars.next()
49*e51878c1SAndroid Build Coastguard Worker             }
50*e51878c1SAndroid Build Coastguard Worker             if let Some(value) = current {
51*e51878c1SAndroid Build Coastguard Worker                 token.push(value);
52*e51878c1SAndroid Build Coastguard Worker             }
53*e51878c1SAndroid Build Coastguard Worker             current = chars.next();
54*e51878c1SAndroid Build Coastguard Worker         }
55*e51878c1SAndroid Build Coastguard Worker         // Parse token.
56*e51878c1SAndroid Build Coastguard Worker         result.push(f(token.as_str())?);
57*e51878c1SAndroid Build Coastguard Worker         current = chars.next()
58*e51878c1SAndroid Build Coastguard Worker     }
59*e51878c1SAndroid Build Coastguard Worker 
60*e51878c1SAndroid Build Coastguard Worker     Ok(result)
61*e51878c1SAndroid Build Coastguard Worker }
62*e51878c1SAndroid Build Coastguard Worker 
63*e51878c1SAndroid Build Coastguard Worker /// Parses the given string as a comma-separated list of `T`s.
64*e51878c1SAndroid Build Coastguard Worker ///
65*e51878c1SAndroid Build Coastguard Worker /// Literal commas can be escaped with `\`.
parse_list<T: FromStr>(s: &str) -> Result<Vec<T>>66*e51878c1SAndroid Build Coastguard Worker pub fn parse_list<T: FromStr>(s: &str) -> Result<Vec<T>> {
67*e51878c1SAndroid Build Coastguard Worker     parse_list_with(s, parse)
68*e51878c1SAndroid Build Coastguard Worker }
69*e51878c1SAndroid Build Coastguard Worker 
70*e51878c1SAndroid Build Coastguard Worker /// Parses the given string as a comma-separated list of booleans.
71*e51878c1SAndroid Build Coastguard Worker ///
72*e51878c1SAndroid Build Coastguard Worker /// Literal commas can be escaped with `\`.
parse_bool_list(s: &str) -> Result<Vec<bool>>73*e51878c1SAndroid Build Coastguard Worker pub fn parse_bool_list(s: &str) -> Result<Vec<bool>> {
74*e51878c1SAndroid Build Coastguard Worker     parse_list_with(s, parse_bool)
75*e51878c1SAndroid Build Coastguard Worker }
76*e51878c1SAndroid Build Coastguard Worker 
77*e51878c1SAndroid Build Coastguard Worker // Formatters.
78*e51878c1SAndroid Build Coastguard Worker 
79*e51878c1SAndroid Build Coastguard Worker /// Converts the given value to a string.
format<T: ToString>(v: &T) -> String80*e51878c1SAndroid Build Coastguard Worker pub fn format<T: ToString>(v: &T) -> String {
81*e51878c1SAndroid Build Coastguard Worker     v.to_string()
82*e51878c1SAndroid Build Coastguard Worker }
83*e51878c1SAndroid Build Coastguard Worker 
84*e51878c1SAndroid Build Coastguard Worker /// Converts the given value to a string `true` or `false`.
format_bool(v: &bool) -> String85*e51878c1SAndroid Build Coastguard Worker pub fn format_bool(v: &bool) -> String {
86*e51878c1SAndroid Build Coastguard Worker     if *v {
87*e51878c1SAndroid Build Coastguard Worker         return "true".into();
88*e51878c1SAndroid Build Coastguard Worker     }
89*e51878c1SAndroid Build Coastguard Worker     "false".into()
90*e51878c1SAndroid Build Coastguard Worker }
91*e51878c1SAndroid Build Coastguard Worker 
92*e51878c1SAndroid Build Coastguard Worker /// Converts the given value to a string `1` or `0`.
format_bool_as_int(v: &bool) -> String93*e51878c1SAndroid Build Coastguard Worker pub fn format_bool_as_int(v: &bool) -> String {
94*e51878c1SAndroid Build Coastguard Worker     if *v {
95*e51878c1SAndroid Build Coastguard Worker         return "1".into();
96*e51878c1SAndroid Build Coastguard Worker     }
97*e51878c1SAndroid Build Coastguard Worker     "0".into()
98*e51878c1SAndroid Build Coastguard Worker }
99*e51878c1SAndroid Build Coastguard Worker 
format_list_with<T, F>(v: &[T], f: F) -> String where F: Fn(&T) -> String,100*e51878c1SAndroid Build Coastguard Worker fn format_list_with<T, F>(v: &[T], f: F) -> String
101*e51878c1SAndroid Build Coastguard Worker where
102*e51878c1SAndroid Build Coastguard Worker     F: Fn(&T) -> String,
103*e51878c1SAndroid Build Coastguard Worker {
104*e51878c1SAndroid Build Coastguard Worker     let mut result = String::new();
105*e51878c1SAndroid Build Coastguard Worker     for item in v {
106*e51878c1SAndroid Build Coastguard Worker         let formatted = f(item);
107*e51878c1SAndroid Build Coastguard Worker         result.push_str(formatted.as_str());
108*e51878c1SAndroid Build Coastguard Worker         result.push(',');
109*e51878c1SAndroid Build Coastguard Worker     }
110*e51878c1SAndroid Build Coastguard Worker     result.pop();
111*e51878c1SAndroid Build Coastguard Worker     result
112*e51878c1SAndroid Build Coastguard Worker }
113*e51878c1SAndroid Build Coastguard Worker 
114*e51878c1SAndroid Build Coastguard Worker /// Converts the given list of values to a string, separated by commas.
format_list<T: ToString>(v: &[T]) -> String115*e51878c1SAndroid Build Coastguard Worker pub fn format_list<T: ToString>(v: &[T]) -> String {
116*e51878c1SAndroid Build Coastguard Worker     format_list_with(v, format)
117*e51878c1SAndroid Build Coastguard Worker }
118*e51878c1SAndroid Build Coastguard Worker 
119*e51878c1SAndroid Build Coastguard Worker /// Converts the given list of booleans to a string, separated by commas.
format_bool_list(v: &[bool]) -> String120*e51878c1SAndroid Build Coastguard Worker pub fn format_bool_list(v: &[bool]) -> String {
121*e51878c1SAndroid Build Coastguard Worker     format_list_with(v, format_bool)
122*e51878c1SAndroid Build Coastguard Worker }
123*e51878c1SAndroid Build Coastguard Worker 
124*e51878c1SAndroid Build Coastguard Worker /// Converts the given list of booleans to a string of `0`s and `1`s separated by commas.
format_bool_list_as_int(v: &[bool]) -> String125*e51878c1SAndroid Build Coastguard Worker pub fn format_bool_list_as_int(v: &[bool]) -> String {
126*e51878c1SAndroid Build Coastguard Worker     format_list_with(v, format_bool_as_int)
127*e51878c1SAndroid Build Coastguard Worker }
128