use crate::error::display_bytes;
pub trait ValueEnum: Sized {
const VALUES: &'static [&'static str];
#[doc(hidden)]
fn from_value(value: &str) -> Option<Self>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
#[error("{}", display_value_enum_values(.values))]
pub struct ValueEnumError {
values: &'static [&'static str],
}
impl ValueEnumError {
#[doc(hidden)]
#[must_use]
pub const fn new(values: &'static [&'static str]) -> Self {
Self { values }
}
}
fn display_value_enum_values(values: &[&str]) -> String {
if values.is_empty() {
return String::from("no values are accepted");
}
let mut rendered = String::from("expected one of: ");
for (index, value) in values.iter().enumerate() {
if index > 0 {
rendered.push_str(", ");
}
rendered.push_str(&display_bytes(value.as_bytes()));
}
rendered
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_values_do_not_emit_terminal_controls() {
static VALUES: &[&str] = &["safe", "bad\n\u{1b}[31m"];
let rendered = ValueEnumError::new(VALUES).to_string();
assert!(!rendered.contains('\n'));
assert!(!rendered.contains('\u{1b}'));
assert!(rendered.contains(r"bad\n"));
}
}