kutil 0.0.6

Kutil utilities collection
Documentation
use std::{cmp::*, fmt, hash::*, str::*};

//
// IsSpecific
//

/// Is specific
pub trait IsSpecific {
    /// True if specific.
    fn is_specific(&self) -> bool;
}

//
// Selector
//

/// Selector.
#[derive(Clone, Debug, Eq)]
pub enum Selector<SelectionT> {
    /// Any.
    Any,

    /// Specific.
    Specific(SelectionT),
}

impl<SelectionT> Selector<SelectionT> {
    /// Select from candidates.
    ///
    /// If we are [Any](Selector::Any) we will select all candidates. Otherwise we will select
    /// either one or none of the candidates.
    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),
        }
    }
}