use std::{ffi::OsString, fmt, str::FromStr};
use crate::{Error, InvalidValue, 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(Box::new(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(Box::new(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(Box::new(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(Box::new(InvalidValue {
name,
value: text,
reason: ValueEnumError::new(T::VALUES).to_string(),
})));
};
parsed.push(value);
}
Ok(parsed)
}
pub fn os_value<T>(value: Vec<u8>, name: &'static str) -> Result<T, Error>
where
T: From<OsString>,
{
Ok(T::from(os_string(value, name)?))
}
pub fn os_values<T>(values: Vec<Vec<u8>>, name: &'static str) -> Result<Vec<T>, Error>
where
T: From<OsString>,
{
let mut parsed = Vec::with_capacity(values.len());
for value in values {
parsed.push(T::from(os_string(value, name)?));
}
Ok(parsed)
}
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>, name: &'static str) -> Result<OsString, Error> {
#[cfg(unix)]
{
use std::os::unix::ffi::OsStringExt as _;
let _ = name;
Ok(OsString::from_vec(value))
}
#[cfg(not(unix))]
{
match String::from_utf8(value) {
Ok(text) => Ok(OsString::from(text)),
Err(bad) => Err(Error::InvalidOsValue { name, value: bad.into_bytes() }),
}
}
}