h3ron/collections/
indexvec.rs

1use crate::{Error, FromH3Index, Index};
2use h3ron_h3_sys::H3Index;
3use std::marker::PhantomData;
4
5/// A `H3Index`-Vec intended to interface between libh3 by providing
6/// continuous memory to place h3indexes in.
7///
8/// Provides iterators to create `Index` implementing types from the primitive `H3Index`/`u64`
9/// types. The iterators automatically skip all `0` values (as created some libh3 functions).
10///
11/// The struct does not provide a `len()` method as this would create the impression that accessing
12/// this method is cheap. As a count of the contained elements requires checking each for `0`, that
13/// functionality is provided by [`IndexVec::count()`]
14#[derive(Debug)]
15pub struct IndexVec<T: FromH3Index + Index> {
16    inner_vec: Vec<H3Index>,
17    phantom: PhantomData<T>,
18}
19
20const EMPTY_H3INDEX: H3Index = 0;
21
22impl<T: FromH3Index + Index> Default for IndexVec<T> {
23    fn default() -> Self {
24        Self {
25            inner_vec: vec![EMPTY_H3INDEX; 0],
26            phantom: Default::default(),
27        }
28    }
29}
30
31impl<T: FromH3Index + Index> IndexVec<T> {
32    pub fn new() -> Self {
33        Default::default()
34    }
35
36    pub fn with_length(length: usize) -> Self {
37        Self {
38            inner_vec: vec![EMPTY_H3INDEX; length],
39            phantom: PhantomData,
40        }
41    }
42
43    /// capacity of the array, not necessarily the number of contained
44    /// element
45    pub fn capacity(&self) -> usize {
46        self.inner_vec.capacity()
47    }
48
49    pub fn clear(&mut self) {
50        unsafe {
51            std::ptr::write_bytes(self.inner_vec.as_mut_ptr(), 0, self.inner_vec.len());
52        }
53    }
54
55    pub fn as_slice(&self) -> &[H3Index] {
56        &self.inner_vec
57    }
58
59    pub fn as_mut_slice(&mut self) -> &mut [H3Index] {
60        &mut self.inner_vec
61    }
62
63    pub fn as_ptr(&self) -> *const H3Index {
64        self.inner_vec.as_ptr()
65    }
66
67    pub fn as_mut_ptr(&mut self) -> *mut H3Index {
68        self.inner_vec.as_mut_ptr()
69    }
70
71    pub fn iter(&self) -> UncheckedIter<'_, T> {
72        self.iter_unchecked()
73    }
74
75    pub fn iter_checked(&self) -> CheckedIter<'_, T> {
76        CheckedIter {
77            inner_iter: self.inner_vec.iter(),
78            phantom: Default::default(),
79        }
80    }
81
82    pub fn iter_unchecked(&self) -> UncheckedIter<'_, T> {
83        UncheckedIter {
84            inner_iter: self.inner_vec.iter(),
85            phantom: Default::default(),
86        }
87    }
88
89    pub fn first(&self) -> Option<T> {
90        self.iter_unchecked().next()
91    }
92
93    pub fn is_empty(&self) -> bool {
94        self.first().is_none()
95    }
96
97    pub fn pop(&mut self) -> Option<T> {
98        while let Some(h3index) = self.inner_vec.pop() {
99            if h3index == EMPTY_H3INDEX {
100                continue;
101            }
102            return Some(T::from_h3index(h3index));
103        }
104        None
105    }
106
107    pub fn shrink_to_fit(&mut self) {
108        // remove all empty h3indexes before shrinking
109        self.inner_vec.retain(|h3index| *h3index != EMPTY_H3INDEX);
110
111        self.inner_vec.shrink_to_fit();
112    }
113
114    pub fn drain(&mut self) -> UncheckedDrain<'_, T> {
115        UncheckedDrain {
116            inner_drain: self.inner_vec.drain(..),
117            phantom: Default::default(),
118        }
119    }
120
121    pub fn append(&mut self, other: &mut Self) {
122        self.inner_vec.append(&mut other.inner_vec);
123    }
124
125    pub fn dedup(&mut self) {
126        self.inner_vec.dedup();
127    }
128
129    pub fn sort_unstable(&mut self) {
130        self.inner_vec.sort_unstable();
131    }
132
133    pub fn count(&self) -> usize {
134        self.iter_unchecked().count()
135    }
136
137    pub fn push(&mut self, item: T) {
138        self.inner_vec.push(item.h3index());
139    }
140}
141
142impl<'a, T: FromH3Index + Index> IntoIterator for &'a IndexVec<T> {
143    type Item = T;
144    type IntoIter = UncheckedIter<'a, T>;
145
146    fn into_iter(self) -> Self::IntoIter {
147        self.iter_unchecked()
148    }
149}
150
151pub struct CheckedIter<'a, T: FromH3Index + Index> {
152    inner_iter: std::slice::Iter<'a, H3Index>,
153    phantom: PhantomData<T>,
154}
155
156impl<'a, T: FromH3Index + Index> Iterator for CheckedIter<'a, T> {
157    type Item = Result<T, Error>;
158
159    fn next(&mut self) -> Option<Self::Item> {
160        for h3index in &mut self.inner_iter {
161            if *h3index == EMPTY_H3INDEX {
162                continue;
163            }
164            let value = T::from_h3index(*h3index);
165            return match value.validate() {
166                Ok(_) => Some(Ok(value)),
167                Err(e) => Some(Err(e)),
168            };
169        }
170        None
171    }
172
173    fn size_hint(&self) -> (usize, Option<usize>) {
174        self.inner_iter.size_hint()
175    }
176}
177
178pub struct UncheckedIter<'a, T: FromH3Index + Index> {
179    inner_iter: std::slice::Iter<'a, H3Index>,
180    phantom: PhantomData<T>,
181}
182
183impl<'a, T: FromH3Index + Index> Iterator for UncheckedIter<'a, T> {
184    type Item = T;
185
186    fn next(&mut self) -> Option<Self::Item> {
187        for h3index in &mut self.inner_iter {
188            if *h3index == EMPTY_H3INDEX {
189                continue;
190            }
191            return Some(T::from_h3index(*h3index));
192        }
193        None
194    }
195
196    fn size_hint(&self) -> (usize, Option<usize>) {
197        self.inner_iter.size_hint()
198    }
199}
200
201pub struct UncheckedDrain<'a, T: FromH3Index + Index> {
202    inner_drain: std::vec::Drain<'a, H3Index>,
203    phantom: PhantomData<T>,
204}
205
206impl<'a, T: FromH3Index + Index> Iterator for UncheckedDrain<'a, T> {
207    type Item = T;
208
209    fn next(&mut self) -> Option<Self::Item> {
210        for h3index in &mut self.inner_drain {
211            if h3index == EMPTY_H3INDEX {
212                continue;
213            }
214            return Some(Self::Item::from_h3index(h3index));
215        }
216        None
217    }
218
219    fn size_hint(&self) -> (usize, Option<usize>) {
220        self.inner_drain.size_hint()
221    }
222}
223
224impl<T: FromH3Index + Index> From<IndexVec<T>> for Vec<T> {
225    fn from(mut index_vec: IndexVec<T>) -> Self {
226        index_vec.drain().collect()
227    }
228}
229
230impl<T: FromH3Index + Index> TryFrom<Vec<H3Index>> for IndexVec<T> {
231    type Error = Error;
232
233    fn try_from(h3index_vec: Vec<H3Index>) -> Result<Self, Self::Error> {
234        for h3index in &h3index_vec {
235            let value = T::from_h3index(*h3index);
236            value.validate()?;
237        }
238        Ok(Self {
239            inner_vec: h3index_vec,
240            phantom: Default::default(),
241        })
242    }
243}