pub trait Convert<T> {
type Error;
fn convert<Tnew: TryFrom<T>>(&self) -> Result<Vec<Tnew>, Self::Error>;
fn convert_default<Tnew: TryFrom<T> + Default>(&self) -> Vec<Tnew>;
fn convert_or<Tnew: TryFrom<T> + Clone>(&self, fallback: Tnew) -> Vec<Tnew>;
}
impl<T> Convert<T> for [T]
where
T: Clone,
{
type Error = String;
fn convert_default<Tnew>(&self) -> Vec<Tnew>
where
Tnew: TryFrom<T>,
Tnew: Default, {
self.iter()
.map(|a| Tnew::try_from(a.clone()).unwrap_or_default())
.collect()
}
fn convert<Tnew: TryFrom<T>>(&self) -> Result<Vec<Tnew>, Self::Error> {
let mut vec = Vec::with_capacity(self.len());
for (i, item) in self.iter().enumerate() {
match Tnew::try_from(item.clone()) {
Ok(item) => vec.push(item),
Err(_) => return Err(format!("Could not convert item at index {i}")),
}
}
Ok(vec)
}
fn convert_or<Tnew: TryFrom<T> + Clone>(&self, fallback: Tnew) -> Vec<Tnew> {
self.iter()
.map(|a| Tnew::try_from(a.clone()).unwrap_or(fallback.clone()))
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn convert_default() {
let a = [1u32, 2, 3];
assert_eq!(a.convert_default::<f64>(), [1., 2., 3.]);
let b: Vec<u8> = a.convert_default();
assert_eq!(b, [1u8, 2, 3]);
let fail = vec![300u32, 2, 3];
let b: Vec<u8> = fail.convert_default();
assert_eq!(b, vec![0u8, 2, 3]);
}
#[test]
fn convert_or() {
let a = [1u32, 2, 3];
assert_eq!(a.convert_or::<f64>(0.), [1., 2., 3.]);
let b: Vec<u8> = a.convert_default();
assert_eq!(b, [1u8, 2, 3]);
let fail = vec![300u32, 2, 3];
let b: Vec<u8> = fail.convert_or(1);
assert_eq!(b, vec![1u8, 2, 3]);
}
#[test]
fn convert() {
let a = [1u32, 2, 3];
assert_eq!(a.convert::<f64>(), Ok(vec![1., 2., 3.]));
let b = a.convert::<u8>();
assert_eq!(b, Ok(vec![1u8, 2, 3]));
let fail = vec![300u32, 2, 3];
let b = fail.convert::<u8>();
assert_eq!(b.is_err(), true);
}
}