Skip to main content

sexprs_macros_core/
ordered_string_set.rs

1use std::iter::{Extend, FromIterator, IntoIterator};
2use std::marker::PhantomData;
3use std::ops::{Deref, DerefMut, Index, IndexMut};
4use std::ptr::NonNull;
5
6/// `OrderedStringSet` is a safe data-structure that provides an
7/// ordered set of strings with push/insert methods to help migrate
8/// from both [`std::vec::Vec`] and [`std::collections::BTreeSet`]
9/// relatively easily
10#[derive(Clone, Hash, PartialOrd, Ord, PartialEq, Eq, Default)]
11pub struct OrderedStringSet {
12    data: Vec<String>,
13}
14impl OrderedStringSet {
15    /// `new`
16    ///
17    /// ```
18    /// use sexprs_macros_core::OrderedStringSet;
19    /// let mut set = OrderedStringSet::new();
20    /// set.add(format!("a"));
21    /// assert_eq!(set, vec!["a"]);
22    /// ```
23    pub fn new() -> OrderedStringSet {
24        OrderedStringSet::default()
25    }
26
27    /// `contains`
28    ///
29    /// ```
30    /// use sexprs_macros_core::OrderedStringSet;
31    ///
32    /// let mut set = OrderedStringSet::new();
33    /// set.add(String::from("a"));
34    ///
35    /// assert!(set.contains("a"));
36    /// assert!(set.contains(String::from("a")));
37    /// assert!(set.contains(&String::from("a")));
38    /// ```
39    pub fn contains<T: std::fmt::Display>(&mut self, string: T) -> bool {
40        let string = string.to_string();
41        self.data.contains(&string)
42    }
43
44    /// `add`
45    ///
46    /// ```
47    /// use sexprs_macros_core::OrderedStringSet;
48    ///
49    /// let mut set = OrderedStringSet::new();
50    /// set.add("a");
51    /// set.add(format!("a"));
52    /// set.add(String::from("A").to_lowercase());
53    /// assert_eq!(set, vec!["a"]);
54    /// ```
55    pub fn add<T: std::fmt::Display>(&mut self, string: T) {
56        let string = string.to_string();
57        if !self.data.contains(&string) {
58            self.data.push(string.to_string())
59        }
60    }
61
62    /// `first`
63    ///
64    /// ```
65    /// use sexprs_macros_core::OrderedStringSet;
66    ///
67    /// let set = OrderedStringSet::from(["a", "z"]);
68    ///
69    /// assert_eq!(set.first(), Some(&"a".to_string()));
70    /// ```
71    pub fn first(&self) -> Option<&String> {
72        self.data.first()
73    }
74
75    /// `last`
76    ///
77    /// ```
78    /// use sexprs_macros_core::OrderedStringSet;
79    ///
80    /// let set = OrderedStringSet::from(["a", "z"]);
81    ///
82    /// assert_eq!(set.last(), Some(&"z".to_string()));
83    /// ```
84    pub fn last(&self) -> Option<&String> {
85        self.data.last()
86    }
87
88    /// `push` - [`std::vec::Vec`] migration interface
89    ///
90    /// ```
91    /// use sexprs_macros_core::OrderedStringSet;
92    ///
93    /// let mut set = OrderedStringSet::new();
94    /// set.push("a");
95    /// set.push(format!("a"));
96    /// set.push(String::from("A").to_lowercase());
97    /// assert_eq!(set, vec!["a"]);
98    /// ```
99    pub fn push<T: std::fmt::Display>(&mut self, string: T) {
100        self.add(string)
101    }
102
103    /// `insert` - [`std::collections::BTreeSet`] migration interface
104    ///
105    /// ```
106    /// use sexprs_macros_core::OrderedStringSet;
107    ///
108    /// let mut set = OrderedStringSet::new();
109    /// set.insert("a");
110    /// set.insert(format!("a"));
111    /// set.insert(String::from("A").to_lowercase());
112    /// assert_eq!(set, vec!["a"]);
113    /// ```
114    pub fn insert<T: std::fmt::Display>(&mut self, string: T) {
115        self.push(string)
116    }
117
118    /// `len`
119    ///
120    /// ```
121    /// use sexprs_macros_core::OrderedStringSet;
122    ///
123    /// let mut set = OrderedStringSet::from(&["a", "b", "c"]);
124    /// assert_eq!(set.len(), 3);
125    /// ```
126    pub fn len(&self) -> usize {
127        self.data.len()
128    }
129
130    /// `iter_mut`
131    ///
132    /// ```
133    /// use sexprs_macros_core::OrderedStringSet;
134    ///
135    /// let mut set = OrderedStringSet::new();
136    ///
137    /// set.push("z");
138    /// set.push("c");
139    /// set.push("a");
140    /// set.push("b");
141    ///
142    /// set.extend(&["a", "b", "c", "d"]);
143    ///
144    /// for h in set.iter_mut() {
145    ///     if !["c", "d"].contains(&h.to_lowercase().as_str()) {
146    ///         *h = h.to_uppercase();
147    ///     }
148    /// }
149    ///
150    /// assert_eq!(set, vec!["Z", "c", "A", "B", "d"]);
151    /// ```
152    pub fn iter_mut(&mut self) -> OrderedStringSetIterMut {
153        OrderedStringSetIterMut::new(&mut self.data)
154    }
155
156    /// `iter`
157    ///
158    /// ```
159    /// use sexprs_macros_core::OrderedStringSet;
160    ///
161    /// let mut set = OrderedStringSet::new();
162    ///
163    /// set.push("z");
164    /// set.push("c");
165    /// set.push("a");
166    /// set.push("b");
167    ///
168    /// set.extend(&["a", "b", "c", "d"]);
169    ///
170    /// let mut data = OrderedStringSet::new();
171    /// for h in set {
172    ///     if ["c", "d"].contains(&h.to_lowercase().as_str()) {
173    ///         data.push(h.to_uppercase());
174    ///     }
175    /// }
176    ///
177    /// assert_eq!(data, vec!["C", "D"]);
178    /// ```
179    pub fn iter(&self) -> OrderedStringSetIter {
180        OrderedStringSetIter::new(&self.data)
181    }
182}
183
184/// mutable [`std::iter::Iterator`] for [`OrderedStringSet`]
185pub struct OrderedStringSetIterMut<'a> {
186    ptr: NonNull<String>,
187    end_or_len: *mut String,
188    _marker: PhantomData<&'a String>,
189}
190impl<'a> OrderedStringSetIterMut<'a> {
191    pub fn new(slice: &mut [String]) -> Self {
192        let len = slice.len();
193        let ptr: NonNull<String> = NonNull::from_ref(slice).cast();
194        unsafe {
195            let end_or_len = ptr.as_ptr().add(len);
196
197            Self {
198                ptr,
199                end_or_len,
200                _marker: PhantomData,
201            }
202        }
203    }
204}
205impl<'a> Iterator for OrderedStringSetIterMut<'a> {
206    type Item = &'a mut String;
207
208    fn next(&mut self) -> Option<Self::Item> {
209        if self.ptr.addr().get() == self.end_or_len.addr() {
210            None
211        } else {
212            unsafe {
213                let item = self.ptr.as_mut();
214                let ptr = self.ptr.add(1);
215                self.ptr = ptr;
216                Some(item)
217            }
218        }
219    }
220}
221/// [`std::iter::Iterator`] for [`OrderedStringSet`]
222pub struct OrderedStringSetIter<'a> {
223    ptr: NonNull<String>,
224    end_or_len: *const String,
225    _marker: PhantomData<&'a String>,
226}
227impl<'a> OrderedStringSetIter<'a> {
228    pub fn new(slice: &'a [String]) -> Self {
229        let len = slice.len();
230        let ptr: NonNull<String> = NonNull::from_ref(slice).cast();
231        unsafe {
232            let end_or_len = ptr.as_ptr().add(len);
233            Self {
234                ptr,
235                end_or_len,
236                _marker: PhantomData,
237            }
238        }
239    }
240}
241impl<'a> Iterator for OrderedStringSetIter<'a> {
242    type Item = &'a String;
243
244    fn next(&mut self) -> Option<Self::Item> {
245        if self.ptr.addr().get() == self.end_or_len.addr() {
246            None
247        } else {
248            unsafe {
249                let item = self.ptr.as_ref();
250                let ptr = self.ptr.add(1);
251                self.ptr = ptr;
252                Some(item)
253            }
254        }
255    }
256}
257
258impl<'a, 'b> Extend<&'a &'b String> for OrderedStringSet {
259    fn extend<T: IntoIterator<Item = &'a &'b String>>(&mut self, iter: T) {
260        for string in iter {
261            let string = string.to_string();
262            if !self.contains(&string) {
263                self.push(string);
264            }
265        }
266    }
267}
268impl<'a, 'b> Extend<&'a &'b str> for OrderedStringSet {
269    fn extend<T: IntoIterator<Item = &'a &'b str>>(&mut self, iter: T) {
270        for string in iter {
271            let string = string.to_string();
272            if !self.contains(&string) {
273                self.push(string);
274            }
275        }
276    }
277}
278impl<'a> Extend<&'a str> for OrderedStringSet {
279    fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
280        for string in iter {
281            let string = string.to_string();
282            if !self.contains(&string) {
283                self.push(string);
284            }
285        }
286    }
287}
288
289impl<'a> Extend<&'a String> for OrderedStringSet {
290    fn extend<T: IntoIterator<Item = &'a String>>(&mut self, iter: T) {
291        for string in iter {
292            if !self.contains(string) {
293                self.push(string.to_string());
294            }
295        }
296    }
297}
298impl Extend<String> for OrderedStringSet {
299    fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
300        for string in iter {
301            if !self.contains(&string) {
302                self.push(string);
303            }
304        }
305    }
306}
307impl<'a> Extend<&'a OrderedStringSet> for OrderedStringSet {
308    fn extend<T: IntoIterator<Item = &'a OrderedStringSet>>(&mut self, iter: T) {
309        for set in iter {
310            self.extend(set.iter());
311        }
312    }
313}
314impl IntoIterator for OrderedStringSet {
315    type IntoIter = std::vec::IntoIter<String>;
316    type Item = String;
317
318    fn into_iter(self) -> Self::IntoIter {
319        self.data.clone().into_iter()
320    }
321}
322
323impl<'a> IntoIterator for &'a OrderedStringSet {
324    type IntoIter = OrderedStringSetIter<'a>;
325    type Item = &'a String;
326
327    fn into_iter(self) -> Self::IntoIter {
328        self.iter()
329    }
330}
331
332impl From<Vec<String>> for OrderedStringSet {
333    fn from(iter: Vec<String>) -> OrderedStringSet {
334        let mut buf = OrderedStringSet::new();
335        buf.extend(iter);
336        buf
337    }
338}
339impl<'a, const N: usize> From<[&'a str; N]> for OrderedStringSet {
340    fn from(iter: [&'a str; N]) -> OrderedStringSet {
341        let mut buf = OrderedStringSet::new();
342        buf.extend(iter);
343        buf
344    }
345}
346impl<'a, 'b> From<&'a [&'b str]> for OrderedStringSet {
347    fn from(iter: &'a [&'b str]) -> OrderedStringSet {
348        let mut buf = OrderedStringSet::new();
349        buf.extend(iter);
350        buf
351    }
352}
353impl<'a, 'b, const N: usize> From<&'a [&'b str; N]> for OrderedStringSet {
354    fn from(iter: &'a [&'b str; N]) -> OrderedStringSet {
355        let mut buf = OrderedStringSet::new();
356        buf.extend(iter);
357        buf
358    }
359}
360impl<const N: usize> From<[String; N]> for OrderedStringSet {
361    fn from(iter: [String; N]) -> OrderedStringSet {
362        let mut buf = OrderedStringSet::new();
363        buf.extend(iter);
364        buf
365    }
366}
367impl<'a, const N: usize> From<[&'a String; N]> for OrderedStringSet {
368    fn from(iter: [&'a String; N]) -> OrderedStringSet {
369        let mut buf = OrderedStringSet::new();
370        buf.extend(iter);
371        buf
372    }
373}
374
375impl<'a, 'b> From<&'a [&'b String]> for OrderedStringSet {
376    fn from(iter: &'a [&'b String]) -> OrderedStringSet {
377        let mut buf = OrderedStringSet::new();
378        buf.extend(iter);
379        buf
380    }
381}
382impl<'a, 'b, const N: usize> From<&'a [&'b String; N]> for OrderedStringSet {
383    fn from(iter: &'a [&'b String; N]) -> OrderedStringSet {
384        let mut buf = OrderedStringSet::new();
385        buf.extend(iter);
386        buf
387    }
388}
389
390impl FromIterator<String> for OrderedStringSet {
391    fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> OrderedStringSet {
392        let mut buf = OrderedStringSet::new();
393        buf.extend(iter);
394        buf
395    }
396}
397
398impl<'a> FromIterator<&'a OrderedStringSet> for OrderedStringSet {
399    fn from_iter<I: IntoIterator<Item = &'a OrderedStringSet>>(iter: I) -> OrderedStringSet {
400        let mut buf = OrderedStringSet::new();
401        for set in iter {
402            buf.extend(set.iter());
403        }
404        buf
405    }
406}
407impl FromIterator<OrderedStringSet> for OrderedStringSet {
408    fn from_iter<I: IntoIterator<Item = OrderedStringSet>>(iter: I) -> OrderedStringSet {
409        let mut buf = OrderedStringSet::new();
410        for set in iter {
411            buf.extend(set.iter());
412        }
413        buf
414    }
415}
416impl<'a> FromIterator<&'a String> for OrderedStringSet {
417    fn from_iter<I: IntoIterator<Item = &'a String>>(iter: I) -> OrderedStringSet {
418        let mut buf = OrderedStringSet::new();
419        buf.extend(iter.into_iter().map(String::from).collect::<Vec<String>>());
420        buf
421    }
422}
423
424impl Index<usize> for OrderedStringSet {
425    type Output = String;
426
427    fn index(&self, index: usize) -> &Self::Output {
428        Index::index(&self.data, index)
429    }
430}
431
432impl IndexMut<usize> for OrderedStringSet {
433    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
434        IndexMut::index_mut(&mut self.data, index)
435    }
436}
437
438impl Deref for OrderedStringSet {
439    type Target = [String];
440
441    fn deref(&self) -> &[String] {
442        self.data.as_slice()
443    }
444}
445
446impl DerefMut for OrderedStringSet {
447    fn deref_mut(&mut self) -> &mut [String] {
448        self.data.as_mut_slice()
449    }
450}
451
452impl std::fmt::Debug for OrderedStringSet {
453    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
454        write!(f, "{:#?}", &self.data)
455    }
456}
457
458impl<'a, const N: usize> PartialEq<[&'a str; N]> for OrderedStringSet {
459    fn eq(&self, other: &[&'a str; N]) -> bool {
460        let count = self.len();
461        if count != N {
462            return false;
463        }
464        let mut index = 0;
465        while index < N {
466            if self[index].to_string() != other[index].to_string() {
467                return false;
468            }
469            index += 1;
470        }
471        true
472    }
473}
474
475impl PartialEq<Vec<&str>> for OrderedStringSet {
476    fn eq(&self, other: &Vec<&str>) -> bool {
477        let count = self.len();
478        if count != other.len() {
479            return false;
480        }
481        let mut index = 0;
482        while index < count {
483            if self[index].to_string() != other[index].to_string() {
484                return false;
485            }
486            index += 1;
487        }
488        true
489    }
490}
491
492impl PartialEq<Vec<String>> for OrderedStringSet {
493    fn eq(&self, other: &Vec<String>) -> bool {
494        let count = self.len();
495        if count != other.len() {
496            return false;
497        }
498        let mut index = 0;
499        while index < count {
500            if self[index].to_string() != other[index].to_string() {
501                return false;
502            }
503            index += 1;
504        }
505        true
506    }
507}
508
509/// `oss!` is a drop-in replacement for the [`vec!`] macro.
510///
511/// # Example
512///
513/// ```
514/// use sexprs_macros_core::oss;
515///
516/// let set = oss!["z", "a", "y", "a", "x", "c", "a", "z", "c" ];
517/// assert_eq!(set, vec!["z", "a", "y", "x", "c"]);
518/// ```
519
520#[rustfmt::skip]
521#[macro_export]
522macro_rules! oss {
523    ($( $arg:expr ),* ) => {{
524        let mut set = $crate::OrderedStringSet::new();
525        $(
526            set.push($arg);
527        )*
528        set
529    }};
530}