pair_utils/
pair.rs

1use crate::paired::Paired;
2use crate::side::Side;
3use std::{
4    convert::From,
5    ops::{Index, IndexMut},
6};
7
8#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
9pub struct Pair<T>([T; 2]);
10
11impl<T> Paired for Pair<T> {
12    type Item = T;
13    fn swap(&mut self) {
14        let data_ptr = self.0.as_mut_ptr();
15        unsafe {
16            std::ptr::swap(data_ptr.add(0), data_ptr.add(1));
17        }
18    }
19
20    fn get_left(&self) -> &Self::Item {
21        unsafe { self.0.get_unchecked(0) }
22    }
23
24    fn get_right(&self) -> &Self::Item {
25        unsafe { self.0.get_unchecked(1) }
26    }
27
28    fn get_left_mut(&mut self) -> &mut Self::Item {
29        unsafe { self.0.get_unchecked_mut(0) }
30    }
31
32    fn get_right_mut(&mut self) -> &mut Self::Item {
33        unsafe { self.0.get_unchecked_mut(1) }
34    }
35}
36
37impl<T> Pair<T> {
38    pub fn new(left: T, right: T) -> Self {
39        Self([left, right])
40    }
41
42    pub fn iter(&self) -> std::slice::Iter<T> {
43        self.0.iter()
44    }
45
46    pub fn iter_mut(&mut self) -> std::slice::IterMut<T> {
47        self.0.iter_mut()
48    }
49
50    pub fn map<U, F>(self, f: F) -> Pair<U>
51    where
52        F: Fn(T) -> U,
53    {
54        self.0.map(f).into()
55    }
56
57    pub fn zip<U>(self, other: Pair<U>) -> Pair<(T, U)> {
58        let [l1, r1] = self.0;
59        let [l2, r2]: [U; 2] = other.into();
60        [(l1, l2), (r1, r2)].into()
61    }
62
63    pub fn compare<'a, U>(self, other: &'a Pair<U>) -> Pair<(T, &'a U)> {
64        let [l1, r1] = self.0;
65        [(l1, other.get_left()), (r1, other.get_right())].into()
66    }
67
68    pub fn merge<U, V, F>(self, other: Pair<U>, f: F) -> Pair<V>
69    where
70        F: Fn(T, U) -> V,
71    {
72        self.zip(other).map(|(t, u)| f(t, u))
73    }
74
75    pub fn apply<U, V, F>(self, other: &Pair<U>, f: F) -> Pair<V>
76    where
77        F: Fn(T, &U) -> V,
78    {
79        self.compare(other).map(|(t, u)| f(t, u))
80    }
81}
82
83impl<T> Index<Side> for Pair<T> {
84    type Output = T;
85
86    fn index<'a>(&'a self, index: Side) -> &'a Self::Output {
87        self.get(index)
88    }
89}
90
91impl<T> IndexMut<Side> for Pair<T> {
92    fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut T {
93        self.get_mut(index)
94    }
95}
96
97impl<T> IntoIterator for Pair<T> {
98    type Item = T;
99    type IntoIter = std::array::IntoIter<T, 2>;
100
101    fn into_iter(self) -> Self::IntoIter {
102        self.0.into_iter()
103    }
104}
105
106impl<T> AsRef<[T; 2]> for Pair<T> {
107    fn as_ref(&self) -> &[T; 2] {
108        &self.0
109    }
110}
111
112impl<T> AsMut<[T; 2]> for Pair<T> {
113    fn as_mut(&mut self) -> &mut [T; 2] {
114        &mut self.0
115    }
116}
117
118impl<T> From<[T; 2]> for Pair<T> {
119    fn from(arr: [T; 2]) -> Self {
120        Pair(arr)
121    }
122}
123
124impl<T> From<Pair<T>> for [T; 2] {
125    fn from(pair: Pair<T>) -> Self {
126        pair.0
127    }
128}
129
130impl<T> From<Pair<T>> for Pair<Option<T>> {
131    fn from(pair: Pair<T>) -> Self {
132        let [left, right]: [T; 2] = pair.into();
133        Self::from([Some(left), Some(right)])
134    }
135}
136
137impl<T> Pair<Option<T>> {
138    pub fn both(&self) -> bool {
139        self.get_left().is_some() && self.get_right().is_some()
140    }
141
142    pub fn none(&self) -> bool {
143        self.get_left().is_none() && self.get_right().is_none()
144    }
145
146    pub fn any(&self) -> bool {
147        self.get_left().is_some() || self.get_right().is_some()
148    }
149
150    pub fn one(&self) -> bool {
151        if self.get_left().is_some() {
152            self.get_right().is_none()
153        } else {
154            self.get_right().is_some()
155        }
156    }
157
158    pub fn map_some<U, F>(self, f: F) -> Pair<Option<U>>
159    where
160        F: Fn(T) -> U,
161    {
162        self.map(|i| i.map(|v| f(v)))
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169
170    #[test]
171    fn from_into_array() {
172        let (left, right) = (0, 1);
173        let pair = Pair::from([left, right]);
174        assert_eq!(pair[Side::L], left);
175        assert_eq!(pair[Side::R], right);
176
177        let arr: [i32; 2] = pair.into();
178        assert_eq!(arr, [left, right]);
179    }
180
181    #[test]
182    fn index_by_side() {
183        let (left, right) = (0, 1);
184        let mut pair = Pair::new(left, right);
185
186        assert_eq!(pair[Side::L], left);
187        assert_eq!(pair[Side::R], right);
188
189        let (new_left, new_right) = (0, 1);
190        pair[Side::L] = new_left;
191        pair[Side::R] = new_right;
192
193        assert_eq!(pair[Side::L], new_left);
194        assert_eq!(pair[Side::R], new_right);
195    }
196
197    #[test]
198    fn swap() {
199        let (left, right) = (0, 1);
200        let mut pair = Pair::new(left, right);
201        pair.swap();
202
203        assert_eq!(pair, Pair::from([right, left]));
204    }
205
206    #[test]
207    fn into_iter() {
208        let (left, right) = (0, 1);
209        let pair = Pair::new(left, right);
210
211        let mut it = pair.into_iter();
212
213        assert_eq!(it.next().unwrap(), left);
214        assert_eq!(it.next().unwrap(), right);
215        assert_eq!(it.next(), None);
216    }
217
218    #[test]
219    fn option() {
220        let (left, right) = (Some(0), Some(1));
221        let both_pair = Pair::new(left, right);
222        let none_pair: Pair<Option<()>> = Pair::new(None, None);
223        let left_pair = Pair::new(left, None);
224        let right_pair = Pair::new(None, right);
225
226        assert!(both_pair.both());
227        assert!(both_pair.any());
228        assert!(!both_pair.none());
229        assert!(!both_pair.one());
230
231        assert!(!none_pair.both());
232        assert!(!none_pair.any());
233        assert!(none_pair.none());
234        assert!(!none_pair.one());
235
236        assert!(!left_pair.both());
237        assert!(left_pair.any());
238        assert!(!left_pair.none());
239        assert!(left_pair.one());
240
241        assert!(!right_pair.both());
242        assert!(right_pair.any());
243        assert!(!right_pair.none());
244        assert!(right_pair.one());
245    }
246}