kutil_http/headers/preferences/
selector.rs

1use super::super::super::cache::*;
2
3use std::{cmp::*, fmt, hash::*, str::*};
4
5//
6// IsSpecific
7//
8
9/// Is specific
10pub trait IsSpecific {
11    /// True if specific.
12    fn is_specific(&self) -> bool;
13}
14
15//
16// Selector
17//
18
19/// Selector.
20#[derive(Clone, Debug, Eq)]
21pub enum Selector<SelectionT> {
22    /// Any.
23    Any,
24
25    /// Specific.
26    Specific(SelectionT),
27}
28
29impl<SelectionT> Selector<SelectionT> {
30    /// Select from candidates.
31    ///
32    /// If we are [Any](Selector::Any) we will select all candidates. Otherwise we will select
33    /// either one or none of the candidates.
34    pub fn select<'own>(&'own self, candidates: &'own [SelectionT]) -> Vec<&'own SelectionT>
35    where
36        SelectionT: Eq,
37    {
38        match self {
39            Self::Any => candidates.iter().collect(),
40
41            Self::Specific(selection) => {
42                if candidates.contains(&selection) {
43                    vec![selection]
44                } else {
45                    Vec::new()
46                }
47            }
48        }
49    }
50}
51
52impl<SelectionT> IsSpecific for Selector<SelectionT> {
53    fn is_specific(&self) -> bool {
54        matches!(self, Self::Specific(_))
55    }
56}
57
58impl<SelectionT> CacheWeight for Selector<SelectionT>
59where
60    SelectionT: CacheWeight,
61{
62    fn cache_weight(&self) -> usize {
63        let mut size = size_of::<Self>();
64        if let Self::Specific(selection) = self {
65            size += selection.cache_weight();
66        }
67        size
68    }
69}
70
71impl<SelectionT> PartialEq for Selector<SelectionT>
72where
73    SelectionT: PartialEq,
74{
75    fn eq(&self, other: &Self) -> bool {
76        match self {
77            Self::Any => matches!(other, Self::Any),
78            Self::Specific(selection) => match other {
79                Self::Any => false,
80                Self::Specific(other_selection) => selection.eq(other_selection),
81            },
82        }
83    }
84}
85
86impl<SelectionT> PartialEq<SelectionT> for Selector<SelectionT>
87where
88    SelectionT: PartialEq,
89{
90    fn eq(&self, other: &SelectionT) -> bool {
91        match self {
92            Self::Any => false,
93            Self::Specific(selection) => selection.eq(other),
94        }
95    }
96}
97
98impl<SelectionT> Hash for Selector<SelectionT>
99where
100    SelectionT: Hash,
101{
102    fn hash<HasherT>(&self, state: &mut HasherT)
103    where
104        HasherT: Hasher,
105    {
106        match self {
107            Self::Any => {
108                state.write_u8(0);
109            }
110
111            Self::Specific(selection) => {
112                state.write_u8(1);
113                selection.hash(state);
114            }
115        }
116    }
117}
118
119impl<SelectionT> From<SelectionT> for Selector<SelectionT> {
120    fn from(selection: SelectionT) -> Self {
121        Self::Specific(selection)
122    }
123}
124
125impl<SelectionT> FromStr for Selector<SelectionT>
126where
127    SelectionT: FromStr,
128{
129    type Err = SelectionT::Err;
130
131    fn from_str(representation: &str) -> Result<Self, Self::Err> {
132        Ok(if representation == "*" { Self::Any } else { Self::Specific(representation.parse()?) })
133    }
134}
135
136impl<SelectionT> fmt::Display for Selector<SelectionT>
137where
138    SelectionT: fmt::Display,
139{
140    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
141        match self {
142            Self::Any => fmt::Display::fmt("*", formatter),
143            Self::Specific(selector) => fmt::Display::fmt(selector, formatter),
144        }
145    }
146}