use std::{ffi::OsString, fmt, str::FromStr};
use crate::{Error, ValueEnum, ValueEnumError};
pub fn comma_values(values: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
let mut split = Vec::new();
for value in values {
split.extend(value.split(|byte| *byte == b',').map(<[u8]>::to_vec));
}
split
}
pub fn text_value(value: Vec<u8>, name: &'static str) -> Result<String, Error> {
text_bytes(value, name)
}
pub fn text_values(values: Vec<Vec<u8>>, name: &'static str) -> Result<Vec<String>, Error> {
let mut parsed = Vec::with_capacity(values.len());
for value in values {
parsed.push(text_bytes(value, name)?);
}
Ok(parsed)
}
pub fn parsed_value<T>(value: Vec<u8>, name: &'static str) -> Result<T, Error>
where
T: FromStr,
T::Err: fmt::Display,
{
let text = text_bytes(value, name)?;
T::from_str(&text).map_err(|reason| Error::InvalidValue {
name,
value: text,
reason: reason.to_string(),
})
}
pub fn parsed_values<T>(values: Vec<Vec<u8>>, name: &'static str) -> Result<Vec<T>, Error>
where
T: FromStr,
T::Err: fmt::Display,
{
let mut parsed = Vec::with_capacity(values.len());
for value in values {
let text = text_bytes(value, name)?;
parsed.push(T::from_str(&text).map_err(|reason| Error::InvalidValue {
name,
value: text,
reason: reason.to_string(),
})?);
}
Ok(parsed)
}
pub fn value_enum_value<T>(value: Vec<u8>, name: &'static str) -> Result<T, Error>
where
T: ValueEnum,
{
let text = text_bytes(value, name)?;
T::from_value(&text).ok_or_else(|| Error::InvalidValue {
name,
value: text,
reason: ValueEnumError::new(T::VALUES).to_string(),
})
}
pub fn value_enum_values<T>(values: Vec<Vec<u8>>, name: &'static str) -> Result<Vec<T>, Error>
where
T: ValueEnum,
{
let mut parsed = Vec::with_capacity(values.len());
for value in values {
let text = text_bytes(value, name)?;
let Some(value) = T::from_value(&text) else {
return Err(Error::InvalidValue {
name,
value: text,
reason: ValueEnumError::new(T::VALUES).to_string(),
});
};
parsed.push(value);
}
Ok(parsed)
}
pub fn os_value<T>(value: Vec<u8>) -> T
where
T: From<OsString>,
{
T::from(os_string(value))
}
pub fn os_values<T>(values: Vec<Vec<u8>>) -> Vec<T>
where
T: From<OsString>,
{
values.into_iter().map(|value| T::from(os_string(value))).collect()
}
fn text_bytes(value: Vec<u8>, name: &'static str) -> Result<String, Error> {
String::from_utf8(value).map_err(|bad| Error::InvalidUtf8 { name, value: bad.into_bytes() })
}
fn os_string(value: Vec<u8>) -> OsString {
use std::os::unix::ffi::OsStringExt as _;
OsString::from_vec(value)
}