url_cleaner_engine/types/
set.rs

1//! `HashSet<Option<T>>` but you can check inclusivity with `Option<&T>`.
2
3use std::collections::HashSet;
4use std::hash::Hash;
5use std::borrow::Borrow;
6use std::fmt::Debug;
7
8use serde::{Serialize, Deserialize, ser::{Serializer, SerializeSeq}, de::{Deserializer, Visitor, SeqAccess}};
9
10use crate::util::*;
11
12/// Allows semantics similar to a `HashSet<Option<String>>` without having to convert `Option<&str>`s to `Option<String>`s.
13///
14/// Serializes and deserializes identically to `HashSet<Option<String>>`, though it's not yet optimized.
15/// # Examples
16/// ```
17/// use serde_json::from_str;
18/// use url_cleaner_engine::types::*;
19///
20/// assert_eq!(serde_json::from_str::<Set<String>>(r#"["abc"]"#      ).unwrap(), Set {set: ["abc".into()].into(), if_none: false});
21/// assert_eq!(serde_json::from_str::<Set<String>>(r#"["abc", null]"#).unwrap(), Set {set: ["abc".into()].into(), if_none: true });
22/// ```
23#[derive(Debug, Clone, Suitability)]
24pub struct Set<T: Debug> {
25    /// The set of `T`.
26    pub set: HashSet<T>,
27    /// If [`true`], act like [`None`] is in [`Self::set`].
28    pub if_none: bool
29}
30
31impl<T: Debug + Hash + Eq> Set<T> {
32    /// [`HashSet::with_capacity`].
33    pub fn with_capacity(capacity: usize) -> Self {
34        Self {
35            set: HashSet::with_capacity(capacity),
36            if_none: false
37        }
38    }
39
40    /// [`HashSet::contains`].
41    /// # Examples
42    /// ```
43    /// use url_cleaner_engine::types::*;
44    ///
45    /// let no_none = Set {set: ["abc"].into(), if_none: false};
46    /// assert!( no_none.contains(Some("abc")));
47    /// assert!(!no_none.contains(None::<&str>));
48    ///
49    /// let yes_none = Set {set: ["abc"].into(), if_none: true};
50    /// assert!(yes_none.contains(Some("abc")));
51    /// assert!(yes_none.contains(None::<&str>));
52    /// ```
53    pub fn contains<Q>(&self, value: Option<&Q>) -> bool where T: Borrow<Q>, Q: Debug + Hash + Eq + ?Sized {
54        debug!(Set::contains, self, value);
55        match value {
56            Some(x) => self.set.contains(x),
57            None => self.if_none
58        }
59    }
60
61    /// [`HashSet::insert`].
62    pub fn insert(&mut self, value: Option<T>) -> bool {
63        match value {
64            Some(value) => self.set.insert(value),
65            None => {let ret = !self.if_none; self.if_none = true; ret}
66        }
67    }
68
69    /// [`HashSet::insert`].
70    pub fn extend<I: IntoIterator<Item = Option<T>>>(&mut self, iter: I) {
71        for x in iter {
72            self.insert(x);
73        }
74    }
75
76    /// [`HashSet::remove`].
77    pub fn remove<Q>(&mut self, value: Option<&Q>) -> bool where T: Borrow<Q>, Q: Debug + Hash + Eq + ?Sized {
78        match value {
79            Some(value) => self.set.remove(value),
80            None => {let ret = self.if_none; self.if_none = false; ret}
81        }
82    }
83}
84
85/// Implemented manually to avoid the `T: Default` bound.
86impl<T: Debug> Default for Set<T> {
87    fn default() -> Self {
88        Self {
89            set: Default::default(),
90            if_none: Default::default()
91        }
92    }
93}
94
95impl<T: Debug + Hash + Eq> PartialEq for Set<T> {
96    fn eq(&self, other: &Self) -> bool {
97        self.set == other.set && self.if_none == other.if_none
98    }
99}
100impl<T: Debug + Hash + Eq> Eq for Set<T> {}
101
102impl<T: Debug + Eq + Hash, const N: usize> From<[Option<T>; N]> for Set<T> {
103    fn from(value: [Option<T>; N]) -> Self {
104        let mut ret = Self::default();
105        for x in value {
106            ret.insert(x);
107        }
108        ret
109    }
110}
111
112impl<T: Debug + Eq + Hash, const N: usize> From<[T; N]> for Set<T> {
113    fn from(value: [T; N]) -> Self {
114        let mut ret = Self::default();
115        for x in value {
116            ret.insert(Some(x));
117        }
118        ret
119    }
120}
121
122impl<T: Debug + Eq + Hash> FromIterator<T> for Set<T> {
123    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self{
124        let mut ret = Self::default();
125        for x in iter {
126            ret.insert(Some(x));
127        }
128        ret
129    }
130}
131
132impl<T: Debug + Eq + Hash> FromIterator<Option<T>> for Set<T> {
133    fn from_iter<I: IntoIterator<Item = Option<T>>>(iter: I) -> Self{
134        let mut ret = Self::default();
135        for x in iter {
136            ret.insert(x);
137        }
138        ret
139    }
140}
141
142impl<T: Debug + Hash + Eq> From<HashSet<Option<T>>> for Set<T> {
143    fn from(value: HashSet<Option<T>>) -> Self {
144        let mut ret = Self::default();
145        for x in value {
146            match x {
147                Some(x) => {ret.set.insert(x);},
148                None => ret.if_none = true
149            }
150        }
151        ret
152    }
153}
154
155impl<T: Debug + Hash + Eq> From<Set<T>> for HashSet<Option<T>> {
156    fn from(value: Set<T>) -> Self {
157        let mut ret = Self::default();
158        for x in value.set {
159            ret.insert(Some(x));
160        }
161        if value.if_none {ret.insert(None);}
162        ret
163    }
164}
165
166impl<T: Debug + Serialize> Serialize for Set<T> {
167    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
168        #[allow(clippy::arithmetic_side_effects, reason = "Can't happen.")]
169        let mut seq = serializer.serialize_seq(Some(self.set.len() + (self.if_none as usize)))?;
170        if self.if_none {seq.serialize_element(&None::<T>)?;}
171        for element in &self.set {
172            seq.serialize_element(element)?;
173        }
174        seq.end()
175    }
176}
177
178impl<'de, T: Debug + Deserialize<'de> + Eq + Hash> Deserialize<'de> for Set<T> {
179    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
180        deserializer.deserialize_seq(SetDeserializer::<T>(Default::default()))
181    }
182}
183
184/// Y'know, I don't actually understand why serde uses this structure.
185#[derive(Debug, Default)]
186struct SetDeserializer<T>(std::marker::PhantomData<T>);
187
188impl<'de, T: Debug + Deserialize<'de> + Eq + Hash> Visitor<'de> for SetDeserializer<T> {
189    type Value = Set<T>;
190
191    fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
192        write!(fmt, "A sequence of type {}", std::any::type_name::<Option<T>>())
193    }
194
195    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
196        let mut ret = Set::with_capacity(seq.size_hint().unwrap_or_default());
197        while let Some(x) = seq.next_element()? {
198            ret.insert(x);
199        }
200        Ok(ret)
201    }
202}