phollaits/
stdext.rs

1/*************************************************************************
2* ph0llux:4fcc63e8c9eac6fae126761c91ea5dca3e9f6303efb0efc6939d58f2c124774c
3*************************************************************************/
4//! stdext module
5// - STD
6use std::env;
7use std::num::ParseIntError;
8 
9// - internal
10use crate as phollaits;
11use crate::{PhollaitsError, Result};
12
13/// Trait contains some extensions for [bool].
14pub trait BoolExtensions {
15	/// method to reverse the value of a bool.
16	/// # Example
17	/// ```
18	/// extern crate phollaits;
19	/// use phollaits::{BoolExtensions};
20	///
21	/// fn main() {
22	/// 	let mut a = true;
23	/// 	a.reverse();
24	/// 	assert_eq!(a, false);
25	/// }
26	/// ```
27	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
39/// Trait contains some extensions for [Option].
40pub 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	/// method to allow a conversion of Option<str> to Option<String> directly.
47	/// # Example
48	/// ```
49	///
50	/// extern crate phollaits;
51	/// use phollaits::*;
52	/// fn main() {
53	/// 		let a = Some("Yes yes yeeesss!");
54	/// 		assert_eq!(a, Some("Yes yes yeeesss!"));
55	/// 		assert_eq!(a.to_string_option(), Some("Yes yes yeeesss!".to_string()))
56	/// }
57	/// ```
58	fn to_string_option(self) -> Option<String> {
59		match self {
60			Some(x) => Some(x.to_string()),
61			None => None,
62		}
63	}
64
65	/// method to allow a conversion of Option<T> to String directly (if T implements the [ToString]-trait).
66	/// # Example
67	/// ```
68	///
69	/// extern crate phollaits;
70	/// use phollaits::*;
71	/// fn main() {
72	/// 		let a = Some("test");
73	///			assert_eq!("test".to_string(), a.to_string())
74	/// }
75	/// ```
76	fn to_string(self) -> String {
77		match self {
78			Some(x) => x.to_string(),
79			None => phollaits::NONE.to_string()
80		}
81	}
82}
83
84/// Trait contains some extensions for [String].
85pub trait StringExt {
86	/// method to allow shell-like expansions in [String].
87	/// # Example to expand tilda
88	/// ```no_run
89	/// extern crate phollaits;
90	/// use phollaits::*;
91	///
92	/// fn main() {
93	/// 	let a = "~/projects/phollaits".to_string();
94	/// 	let b = a.shellexpand();
95	/// 	assert_eq!(b, "/home/ph0llux/projects/phollaits".to_string());
96	/// }
97	/// ```
98	fn shellexpand(self) -> String;
99
100	/// method to trims newline at the end of the string.
101	/// # Example to expand tilda
102	/// ```
103	/// extern crate phollaits;
104	/// use phollaits::*;
105	///
106	/// fn main() {
107	/// 	let a = "This \n is \n a \n string\n\n\r\n".to_string();
108	/// 	let b = a.trim_newline_end();
109	/// 	assert_eq!(b, String::from("This \n is \n a \n string"));
110	/// }
111	/// ```
112	fn trim_newline_end(&self) -> String;
113
114	/// converts a 'hexified' String to a Vec of Bytes.
115	/// # Example
116	/// ```
117	///	use phollaits::{StringExt, PhollaitsError};
118	///
119	/// fn main() -> Result<(), PhollaitsError> {
120	/// 	let m = "6f5902ac237024bdd0c176cb93063dc4".to_string();
121	/// 	let m_as_bytes = m.hex_to_bytes()?;
122	/// 	assert_eq!(m_as_bytes, [111, 89, 2, 172, 35, 112, 36, 189, 208, 193, 118, 203, 147, 6, 61, 196]);
123	/// 	Ok(())
124	/// }
125	/// ```
126	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
224/// Trait contains some extensions for [Vec].
225pub trait VecExt {
226	/// method to convert into Vec<String>.
227	fn to_vec_string(self) -> Vec<String>;
228}
229
230impl VecExt for Vec<&str> {
231	/// method to convert Vec<&str> into Vec<String>.
232	/// # Example
233	/// ```
234	/// extern crate phollaits;
235	/// use phollaits::*;
236	/// 
237	///	const a: [&'static str; 3] = [ "a", "b", "c" ];
238	///
239	/// fn main() {
240	/// 	let b = a.to_vec();
241	///		let c = vec!("a".to_string(), "b".to_string(), "c".to_string());
242	/// 	assert_eq!(b.to_vec_string(), c);
243	/// }
244	/// ```
245	fn to_vec_string(self) -> Vec<String> {
246		self.into_iter().map(Into::into).collect()
247	}
248}