opening_hours_syntax/sorted_vec.rs
1use std::borrow::Borrow;
2use std::cmp::Ordering;
3use std::convert::From;
4use std::ops::Deref;
5
6/// A wrapper arround a [`Vec`] that is always sorted and with values repeating
7/// at most once.
8///
9/// ```
10/// use opening_hours_syntax::sorted_vec::UniqueSortedVec;
11///
12/// let sorted: UniqueSortedVec<_> = vec![2, 1, 3, 5, 3].into();
13/// assert_eq!(sorted.as_slice(), &[1, 2, 3, 5]);
14/// ```
15#[repr(transparent)]
16#[derive(Clone, Debug, Default, Hash, Eq, PartialEq, PartialOrd, Ord)]
17pub struct UniqueSortedVec<T>(Vec<T>);
18
19impl<T> UniqueSortedVec<T> {
20 /// Create a new empty instance.
21 #[inline]
22 pub const fn new() -> Self {
23 Self(Vec::new())
24 }
25}
26
27impl<T: Ord> UniqueSortedVec<T> {
28 /// Build a new [`UniqueSortedVec`] with borrowed content. The order is
29 /// assumed to be equivalent for borrowed content.
30 ///
31 /// ```
32 /// use opening_hours_syntax::sorted_vec::UniqueSortedVec;
33 ///
34 /// let sorted: UniqueSortedVec<_> = vec!["Hello".to_string(), "Anaïs".to_string()].into();
35 /// let sorted_ref: UniqueSortedVec<&str> = sorted.to_ref();
36 /// assert_eq!(sorted_ref.as_slice(), &["Anaïs", "Hello"]);
37 /// ```
38 #[inline]
39 pub fn to_ref<U: Ord + ?Sized>(&self) -> UniqueSortedVec<&U>
40 where
41 T: Borrow<U>,
42 {
43 UniqueSortedVec(self.0.iter().map(Borrow::borrow).collect())
44 }
45
46 /// Merge values of two [`UniqueSortedVec`] while preserving the invariants.
47 ///
48 /// ```
49 /// use opening_hours_syntax::sorted_vec::UniqueSortedVec;
50 ///
51 /// let sorted_1: UniqueSortedVec<_> = vec![1, 2, 3].into();
52 /// let sorted_2: UniqueSortedVec<_> = vec![0, 3, 4].into();
53 /// assert_eq!(sorted_1.union(sorted_2).as_slice(), &[0, 1, 2, 3, 4]);
54 /// ```
55 #[inline]
56 pub fn union(mut self, mut other: Self) -> Self {
57 match (self.as_slice(), other.as_slice()) {
58 (_, []) => self,
59 ([], _) => other,
60 ([.., tail_x], [head_y, ..]) if tail_x < head_y => {
61 self.0.extend(other.0);
62 self
63 }
64 ([head_x, ..], [.., tail_y]) if tail_y < head_x => {
65 other.0.extend(self.0);
66 other
67 }
68 ([.., tail_x], [.., tail_y]) => {
69 let last = match tail_x.cmp(tail_y) {
70 Ordering::Greater => self.0.pop().unwrap(), // move `tail_x` out
71 Ordering::Less => other.0.pop().unwrap(), // move `tail_y` out
72 Ordering::Equal => {
73 other.0.pop().unwrap(); // move `tail_x` out
74 self.0.pop().unwrap() // move `tail_y` out
75 }
76 };
77
78 let mut new_head = self.union(other);
79 new_head.0.push(last);
80 new_head
81 }
82 }
83 }
84
85 /// Returns true if the slice contains an element with the given value.
86 ///
87 /// ```
88 /// use opening_hours_syntax::sorted_vec::UniqueSortedVec;
89 ///
90 /// let sorted: UniqueSortedVec<_> = vec![10, 40, 30].into();
91 /// assert!(sorted.contains(&30));
92 /// assert!(!sorted.contains(&50));
93 /// ```
94 #[inline]
95 pub fn contains(&self, x: &T) -> bool {
96 self.0.binary_search(x).is_ok()
97 }
98
99 /// Search for the given value in the slice return a reference to it or the
100 /// next greater value if it is not found.
101 ///
102 /// ```
103 /// use opening_hours_syntax::sorted_vec::UniqueSortedVec;
104 ///
105 /// let sorted: UniqueSortedVec<_> = vec![10, 40, 30].into();
106 /// assert_eq!(sorted.find_first_following(&30), Some(&30));
107 /// assert_eq!(sorted.find_first_following(&31), Some(&40));
108 /// assert_eq!(sorted.find_first_following(&50), None);
109 /// ```
110 #[inline]
111 pub fn find_first_following(&self, x: &T) -> Option<&T> {
112 let (Ok(i) | Err(i)) = self.0.binary_search(x);
113 self.0.get(i)
114 }
115}
116
117impl<T: Ord> From<Vec<T>> for UniqueSortedVec<T> {
118 #[inline]
119 fn from(mut vec: Vec<T>) -> Self {
120 vec.sort_unstable();
121 vec.dedup();
122 Self(vec)
123 }
124}
125
126impl<T: Ord> From<UniqueSortedVec<T>> for Vec<T> {
127 #[inline]
128 fn from(val: UniqueSortedVec<T>) -> Self {
129 val.0
130 }
131}
132
133impl<T: Ord> Deref for UniqueSortedVec<T> {
134 type Target = Vec<T>;
135
136 #[inline]
137 fn deref(&self) -> &Self::Target {
138 &self.0
139 }
140}