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