use crate::MenuError;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct MenuVec<T>(pub Vec<T>);
impl<T> AsRef<Vec<T>> for MenuVec<T> {
#[inline]
fn as_ref(&self) -> &Vec<T> {
&self.0
}
}
impl<T> AsMut<Vec<T>> for MenuVec<T> {
#[inline]
fn as_mut(&mut self) -> &mut Vec<T> {
&mut self.0
}
}
impl<T> Deref for MenuVec<T> {
type Target = Vec<T>;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T> DerefMut for MenuVec<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
#[derive(PartialEq)]
pub enum MenuVecParseError<E> {
Empty,
ItemParsed(E),
}
impl<E> From<E> for MenuVecParseError<E> {
#[inline]
fn from(err: E) -> Self {
Self::ItemParsed(err)
}
}
impl<E: Debug> Debug for MenuVecParseError<E> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let msg = match self {
Self::Empty => "empty vector".to_owned(),
Self::ItemParsed(e) => format!("parsing error: {:?}", e),
};
f.write_str(msg.as_str())
}
}
impl<T: FromStr> FromStr for MenuVec<T> {
type Err = MenuVecParseError<T::Err>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.is_empty() {
return Err(MenuVecParseError::Empty);
}
let result: Result<Vec<T>, T::Err> = s.split(' ').map(T::from_str).collect();
Ok(Self(result?))
}
}
impl<T> From<MenuVec<T>> for Vec<T> {
#[inline]
fn from(m: MenuVec<T>) -> Self {
m.0
}
}
#[derive(Clone, Copy, Eq, PartialEq, Debug, Default)]
pub struct MenuBool(pub bool);
impl Display for MenuBool {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(&self.0, f)
}
}
impl AsRef<bool> for MenuBool {
#[inline]
fn as_ref(&self) -> &bool {
&self.0
}
}
impl AsMut<bool> for MenuBool {
#[inline]
fn as_mut(&mut self) -> &mut bool {
&mut self.0
}
}
impl Deref for MenuBool {
type Target = bool;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl DerefMut for MenuBool {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
impl FromStr for MenuBool {
type Err = MenuError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"y" | "yes" | "ye" | "yep" | "yeah" | "yea" | "yup" | "true" => Ok(Self(true)),
"n" | "no" | "non" | "nop" | "nah" | "nan" | "nani" | "false" => Ok(Self(false)),
_ => Err(MenuError::Other(Box::new("incorrect boolean value"))),
}
}
}
impl From<MenuBool> for bool {
fn from(m: MenuBool) -> Self {
m.0
}
}
#[derive(Debug, PartialEq, Clone, Default)]
pub struct MenuOption<T>(pub Option<T>);
impl<T: Display> Display for MenuOption<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match &self.0 {
Some(e) => Display::fmt(e, f),
None => f.write_str(""),
}
}
}
impl<T> AsRef<Option<T>> for MenuOption<T> {
#[inline]
fn as_ref(&self) -> &Option<T> {
&self.0
}
}
impl<T> AsMut<Option<T>> for MenuOption<T> {
#[inline]
fn as_mut(&mut self) -> &mut Option<T> {
&mut self.0
}
}
impl<T> Deref for MenuOption<T> {
type Target = Option<T>;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T> DerefMut for MenuOption<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
impl<T> From<MenuOption<T>> for Option<T> {
#[inline]
fn from(mo: MenuOption<T>) -> Self {
mo.0
}
}
impl<T: FromStr> FromStr for MenuOption<T> {
type Err = T::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.trim().is_empty() {
Ok(Self(None))
} else {
Ok(Self(Some(s.parse()?)))
}
}
}