use std::borrow::Borrow;
use std::error::Error;
use std::marker::PhantomData;
use roaring::RoaringTreemap;
use crate::collections::ContainsIndex;
use crate::Index;
#[cfg(feature = "use-serde")]
pub mod serde;
#[derive(Clone)]
pub struct H3Treemap<T> {
treemap: RoaringTreemap,
phantom_data: PhantomData<T>,
}
impl<T, Q> FromIterator<Q> for H3Treemap<T>
where
Q: Borrow<T>,
T: Index,
{
fn from_iter<I: IntoIterator<Item = Q>>(iter: I) -> Self {
Self {
treemap: iter.into_iter().map(|c| c.borrow().h3index()).collect(),
phantom_data: Default::default(),
}
}
}
impl<T> Default for H3Treemap<T>
where
T: Index,
{
fn default() -> Self {
Self {
treemap: Default::default(),
phantom_data: Default::default(),
}
}
}
impl<T> H3Treemap<T>
where
T: Index,
{
#[inline]
pub fn push(&mut self, index: T) -> bool {
self.treemap.push(index.h3index())
}
#[inline]
pub fn insert(&mut self, index: T) -> bool {
self.treemap.insert(index.h3index())
}
#[inline]
pub fn len(&self) -> usize {
self.treemap.len() as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.treemap.is_empty()
}
#[inline]
pub fn contains(&self, index: &T) -> bool {
self.treemap.contains(index.h3index())
}
#[inline]
pub fn is_disjoint(&self, rhs: &Self) -> bool {
self.treemap.is_disjoint(&rhs.treemap)
}
#[inline]
pub fn is_subset(&self, rhs: &Self) -> bool {
self.treemap.is_subset(&rhs.treemap)
}
#[inline]
pub fn is_superset(&self, rhs: &Self) -> bool {
self.treemap.is_superset(&rhs.treemap)
}
pub fn iter(&self) -> Iter<T> {
Iter {
inner_iter: self.treemap.iter(),
phantom_data: Default::default(),
}
}
pub fn from_iter_with_sort<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut h3indexes: Vec<_> = iter.into_iter().map(|c| c.borrow().h3index()).collect();
h3indexes.sort_unstable();
Self {
treemap: RoaringTreemap::from_sorted_iter(h3indexes.drain(..)).unwrap(),
phantom_data: Default::default(),
}
}
pub fn from_result_iter_with_sort<E, I>(iter: I) -> Result<Self, E>
where
E: Error,
I: IntoIterator<Item = Result<T, E>>,
{
let mut h3indexes = iter
.into_iter()
.map(|c| c.map(|c| c.h3index()))
.collect::<Result<Vec<_>, E>>()?;
h3indexes.sort_unstable();
h3indexes.dedup();
Ok(Self {
treemap: RoaringTreemap::from_sorted_iter(h3indexes.drain(..)).unwrap(),
phantom_data: Default::default(),
})
}
}
impl<I: Index> ContainsIndex<I> for H3Treemap<I> {
fn contains_index(&self, index: &I) -> bool {
self.contains(index)
}
}
pub struct Iter<'a, T> {
inner_iter: roaring::treemap::Iter<'a>,
phantom_data: PhantomData<T>,
}
impl<'a, T> Iterator for Iter<'a, T>
where
T: Index,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.inner_iter.next().map(T::new)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner_iter.size_hint()
}
}
#[cfg(test)]
mod tests {
use crate::H3Cell;
use super::H3Treemap;
#[test]
fn iter() {
let idx = H3Cell::try_from(0x89283080ddbffff_u64).unwrap();
let mut treemap = H3Treemap::default();
for cell in idx.grid_disk(1).unwrap().iter() {
treemap.insert(cell);
}
assert_eq!(treemap.iter().count(), 7);
}
}