aabel_identifier_rs/
lib.rs

1/// Identity trait represents data which can be used
2/// as identifiers. Given two identifiers we just need
3/// to determine if they are equal (represent the same entity)
4/// or not.
5///
6/// # Example
7///
8/// ```
9/// use aabel_identifier_rs::*;
10///
11/// fn test_identifier(_id: impl Identifier) {
12///     assert!(true);
13/// }
14///
15/// let id = 10_u8;
16/// test_identifier(id);
17/// ```
18pub trait Identifier: Eq {}
19impl<T> Identifier for T where T: Eq {}
20
21/// The PartialOrdIdentity trait represents data which can be
22/// used for concurrent actions. Given two such identifiers, we
23/// can tell if they are equal and we could potentially compare them.
24pub trait PartialOrdIdentifier: Identifier + PartialOrd {}
25impl<T> PartialOrdIdentifier for T where T: Eq + PartialOrd {}
26
27/// The IntoIdentityIterator trait allows to create a sequence of
28/// identifiers starting with a given identifier value and using a
29/// given function which computes a new identifier.
30///
31/// # Example
32///
33/// ```
34/// use aabel_identifier_rs::*;
35///
36/// let id = 10_u8;
37/// let mut iter = id.into_ids_iterator(|id| id + 1);
38/// assert_eq!(iter.next(), Some(10));
39/// assert_eq!(iter.next(), Some(11));
40/// ```
41pub trait IntoIdentifierIterator {
42    type Item: Identifier;
43
44    fn into_ids_iterator<F>(self, next: F) -> impl Iterator<Item = Self::Item>
45    where
46        F: Fn(&Self::Item) -> Self::Item;
47}
48
49/// Internal implementation of the [`IntoIdentityIterator`] trait.
50/// The iterator will return an [`Identifier`] instance. The identifier
51/// type must also implement [`Copy`] trait.
52struct IdentifierIterator<F, I>
53where
54    F: Fn(&I) -> I,
55    I: Copy,
56{
57    current_id: I,
58    get_next_id: F,
59}
60
61impl<F, I> Iterator for IdentifierIterator<F, I>
62where
63    F: Fn(&I) -> I,
64    I: Copy,
65{
66    type Item = I;
67
68    fn next(&mut self) -> Option<Self::Item> {
69        let nxt = self.current_id;
70        self.current_id = (self.get_next_id)(&self.current_id);
71        Some(nxt)
72    }
73}
74
75impl<T> IntoIdentifierIterator for T
76where
77    T: Copy + Identifier,
78{
79    type Item = Self;
80
81    fn into_ids_iterator<F>(self, next: F) -> impl Iterator<Item = Self::Item>
82    where
83        F: Fn(&Self::Item) -> Self::Item,
84    {
85        IdentifierIterator {
86            current_id: self,
87            get_next_id: next,
88        }
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    fn test_identifier(_id: impl Identifier) {
97        assert!(true);
98    }
99
100    fn test_partialord_identifier(_id: impl PartialOrdIdentifier) {
101        assert!(true);
102    }
103
104    #[test]
105    fn identifier_u8() {
106        let id = 10_u8;
107        test_identifier(id)
108    }
109
110    #[test]
111    fn identifier_u64() {
112        let id = 10_u64;
113        test_identifier(id)
114    }
115
116    #[test]
117    fn identifier_str() {
118        let id = "test";
119        test_identifier(id)
120    }
121
122    #[test]
123    fn identifier_arr() {
124        let id = [1, 2, 3];
125        test_identifier(id)
126    }
127
128    #[test]
129    fn identifier_vec() {
130        let id = vec![1, 2, 3];
131        test_identifier(id)
132    }
133
134    #[test]
135    fn identifier_eq() {
136        fn cmp_identifiers<I>(a: I, b: I) -> bool
137        where
138            I: Identifier,
139        {
140            a == b
141        }
142
143        assert!(cmp_identifiers(10_u16, 10_u16));
144        assert!(!cmp_identifiers(10_u16, 20_u16));
145    }
146
147    #[test]
148    fn partialord_identifier_u8() {
149        let id = 10_u8;
150        test_partialord_identifier(id)
151    }
152
153    #[test]
154    fn partialord_identifier_u64() {
155        let id = 10_u64;
156        test_partialord_identifier(id)
157    }
158
159    #[test]
160    fn partialord_identity_str() {
161        let id = "test";
162        test_partialord_identifier(id)
163    }
164
165    #[test]
166    fn partialord_identifier_arr() {
167        let id = [1, 2, 3];
168        test_partialord_identifier(id)
169    }
170
171    #[test]
172    fn partialord_identifier_vec() {
173        let id = vec![1, 2, 3];
174        test_partialord_identifier(id)
175    }
176
177    #[test]
178    fn partialord_idenitifier_cmp() {
179        fn cmp_identifiers<I>(a: I, b: &I) -> Option<std::cmp::Ordering>
180        where
181            I: PartialOrdIdentifier,
182        {
183            a.partial_cmp(b)
184        }
185
186        assert!(cmp_identifiers(10_u8, &10_u8).is_some());
187        assert!(cmp_identifiers("az", &"za").is_some());
188    }
189
190    #[test]
191    fn iter_u8() {
192        let id = 10_u8;
193        let mut iter = id.into_ids_iterator(|id| id + 1);
194        assert_eq!(iter.next(), Some(10));
195        assert_eq!(iter.next(), Some(11));
196    }
197
198    #[test]
199    fn iter_u64() {
200        let id = 10_u64;
201        let mut iter = id.into_ids_iterator(|id| id + 1);
202        assert_eq!(iter.next(), Some(10));
203        assert_eq!(iter.next(), Some(11));
204    }
205
206    #[test]
207    fn iter_str() {
208        let id = "a";
209        let mut iter = id.into_ids_iterator(|id| id);
210        assert_eq!(iter.next(), Some("a"));
211        assert_eq!(iter.next(), Some("a"));
212    }
213
214    #[test]
215    fn iter_string() {
216        let id = "a".to_string();
217        let mut iter = id.into_ids_iterator(|id| id);
218        assert_eq!(iter.next(), Some(&"a".into()));
219        assert_eq!(iter.next(), Some(&"a".into()));
220    }
221}