1use std::env;
7use std::num::ParseIntError;
8
9use crate as phollaits;
11use crate::{PhollaitsError, Result};
12
13pub trait BoolExtensions {
15 fn reverse(&mut self);
28}
29
30impl BoolExtensions for bool {
31 fn reverse(&mut self) {
32 match &self {
33 true => *self = false,
34 false => *self = true,
35 }
36 }
37}
38
39pub trait OptionExtensions<T> {
41 fn to_string_option(self) -> Option<String>;
42 fn to_string(self) -> String;
43}
44
45impl<T: ToString> OptionExtensions<T> for Option<T> {
46 fn to_string_option(self) -> Option<String> {
59 match self {
60 Some(x) => Some(x.to_string()),
61 None => None,
62 }
63 }
64
65 fn to_string(self) -> String {
77 match self {
78 Some(x) => x.to_string(),
79 None => phollaits::NONE.to_string()
80 }
81 }
82}
83
84pub trait StringExt {
86 fn shellexpand(self) -> String;
99
100 fn trim_newline_end(&self) -> String;
113
114 fn hex_to_bytes(self) -> Result<Vec<u8>>;
127}
128
129impl StringExt for String {
130 fn shellexpand(self) -> String {
131 if self.contains(phollaits::FORMAT_TILDA) {
132 match env::var_os(phollaits::ENV_VAR_HOME) {
133 Some(x) => match x.to_str() {
134 Some(x) => return self.replace(phollaits::FORMAT_TILDA, x),
135 None => return self,
136 },
137 None => return self,
138 }
139 }
140 self
141 }
142
143 fn trim_newline_end(&self) -> String {
144 let mut trimmed_string = self.clone();
145 loop {
146 if trimmed_string.ends_with('\n') {
147 trimmed_string.pop();
148 } else if trimmed_string.ends_with('\r') {
149 trimmed_string.pop();
150 } else {
151 break;
152 }
153 }
154 String::from(trimmed_string)
155 }
156
157 fn hex_to_bytes(self) -> Result<Vec<u8>> {
158 fn inner_hex_to_bytes(s: &str) -> std::result::Result<u8, ParseIntError> {
159 u8::from_str_radix(s, 16).map(|n| n as u8)
160 }
161 fn get_vec(chunks: Vec<String>) -> std::result::Result<Vec<u8>, ParseIntError> {
162 chunks.into_iter().map(|x| inner_hex_to_bytes(&x)).collect()
163 }
164 let mut chunks = Vec::new();
165 let mut z = self.chars().peekable();
166 while z.peek().is_some() {
167 let chunk: String = z.by_ref().take(2).collect();
168 chunks.push(chunk)
169 }
170 match get_vec(chunks) {
171 Ok(x) => Ok(x),
172 Err(e) => Err(PhollaitsError::from(e))
173 }
174 }
175}
176
177impl StringExt for &str {
178 fn shellexpand(self) -> String {
179 if self.contains(phollaits::FORMAT_TILDA) {
180 match env::var_os(phollaits::ENV_VAR_HOME) {
181 Some(x) => match x.to_str() {
182 Some(x) => return self.replace(phollaits::FORMAT_TILDA, x),
183 None => return self.to_string(),
184 },
185 None => return self.to_string(),
186 }
187 }
188 self.to_string()
189 }
190
191 fn trim_newline_end(&self) -> String {
192 let mut trimmed_string = self.to_string();
193 loop {
194 if trimmed_string.ends_with('\n') {
195 trimmed_string.pop();
196 } else if trimmed_string.ends_with('\r') {
197 trimmed_string.pop();
198 } else {
199 break;
200 }
201 }
202 String::from(trimmed_string)
203 }
204 fn hex_to_bytes(self) -> Result<Vec<u8>> {
205 fn inner_hex_to_bytes(s: &str) -> std::result::Result<u8, ParseIntError> {
206 u8::from_str_radix(s, 16).map(|n| n as u8)
207 }
208 fn get_vec(chunks: Vec<String>) -> std::result::Result<Vec<u8>, ParseIntError> {
209 chunks.into_iter().map(|x| inner_hex_to_bytes(&x)).collect()
210 }
211 let mut chunks = Vec::new();
212 let mut z = self.chars().peekable();
213 while z.peek().is_some() {
214 let chunk: String = z.by_ref().take(2).collect();
215 chunks.push(chunk)
216 }
217 match get_vec(chunks) {
218 Ok(x) => Ok(x),
219 Err(e) => Err(PhollaitsError::from(e))
220 }
221 }
222}
223
224pub trait VecExt {
226 fn to_vec_string(self) -> Vec<String>;
228}
229
230impl VecExt for Vec<&str> {
231 fn to_vec_string(self) -> Vec<String> {
246 self.into_iter().map(Into::into).collect()
247 }
248}