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