use std::{cmp::*, fmt, hash::*, str::*};
pub trait IsSpecific {
fn is_specific(&self) -> bool;
}
#[derive(Clone, Debug, Eq)]
pub enum Selector<SelectionT> {
Any,
Specific(SelectionT),
}
impl<SelectionT> Selector<SelectionT> {
pub fn select<'context>(&'context self, candidates: &'context [SelectionT]) -> Vec<&'context SelectionT>
where
SelectionT: Eq,
{
match self {
Self::Any => candidates.iter().collect(),
Self::Specific(selection) => {
if candidates.contains(&selection) {
vec![selection]
} else {
Default::default()
}
}
}
}
}
impl<SelectionT> IsSpecific for Selector<SelectionT> {
fn is_specific(&self) -> bool {
matches!(self, Self::Specific(_))
}
}
impl<SelectionT> PartialEq for Selector<SelectionT>
where
SelectionT: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Any, Self::Any) => true,
(Self::Specific(selection), Self::Specific(other_selection)) => selection.eq(other_selection),
_ => false,
}
}
}
impl<SelectionT> PartialEq<SelectionT> for Selector<SelectionT>
where
SelectionT: PartialEq,
{
fn eq(&self, other: &SelectionT) -> bool {
match self {
Self::Any => false,
Self::Specific(selection) => selection.eq(other),
}
}
}
impl<SelectionT> Hash for Selector<SelectionT>
where
SelectionT: Hash,
{
fn hash<HasherT>(&self, state: &mut HasherT)
where
HasherT: Hasher,
{
match self {
Self::Any => {
state.write_u8(0);
}
Self::Specific(selection) => {
state.write_u8(1);
selection.hash(state);
}
}
}
}
impl<SelectionT> From<SelectionT> for Selector<SelectionT> {
fn from(selection: SelectionT) -> Self {
Self::Specific(selection)
}
}
impl<SelectionT> FromStr for Selector<SelectionT>
where
SelectionT: FromStr,
{
type Err = SelectionT::Err;
fn from_str(representation: &str) -> Result<Self, Self::Err> {
Ok(if representation == "*" { Self::Any } else { Self::Specific(representation.parse()?) })
}
}
impl<SelectionT> fmt::Display for Selector<SelectionT>
where
SelectionT: fmt::Display,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Any => fmt::Display::fmt("*", formatter),
Self::Specific(selector) => fmt::Display::fmt(selector, formatter),
}
}
}