use crate::{
consts::{
SUPPORTED_ALPHA2_LIST, SUPPORTED_CONTINENT_LIST, SUPPORTED_COUNTRIES_COUNT,
SUPPORTED_REGION_LIST, SUPPORTED_SUBREGION_LIST, SUPPORTED_WORLD_REGION_LIST,
},
Continent, Country, Region, SubRegion, WorldRegion,
};
#[derive(Debug, Clone, Copy, PartialEq)]
struct ArrayIterator {
offset: usize,
length: usize,
reusable: bool,
}
impl ArrayIterator {
pub fn new(length: usize) -> Self {
Self {
offset: 0,
reusable: false,
length,
}
}
pub fn new_reusable(length: usize) -> Self {
let mut new = Self::new(length);
new.reusable = true;
new
}
}
impl ArrayIterator {
fn next<I: Clone>(&mut self, array_ref: &[I]) -> Option<I> {
if self.offset < self.length {
self.offset += 1;
Some(array_ref[self.offset - 1].clone())
} else {
if self.reusable {
self.offset = 0;
}
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.length - self.offset, Some(self.length - self.offset))
}
fn count(self) -> usize {
self.length
}
fn last<I: Clone>(self, array_ref: &[I]) -> Option<I> {
Some(array_ref[self.length - 1].clone())
}
fn nth<I: Clone>(&mut self, n: usize, array_ref: &[I]) -> Option<I> {
let offset = n + self.offset;
if offset < self.length {
self.offset = offset;
Some(array_ref[offset].clone())
} else {
None
}
}
}
macro_rules! impl_iterator {
($struct_name:ident, $item:ident, $array_ref:expr, $length:expr, $mapper:expr) => {
impl $struct_name {
pub fn new() -> Self {
Self {
iterator: ArrayIterator::new($length),
}
}
pub fn new_reusable() -> Self {
Self {
iterator: ArrayIterator::new_reusable($length),
}
}
}
impl Default for $struct_name {
fn default() -> Self {
Self::new()
}
}
impl Iterator for $struct_name {
type Item = $item;
fn next(&mut self) -> Option<Self::Item> {
self.iterator.next($array_ref).map($mapper)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iterator.size_hint()
}
fn count(self) -> usize {
self.iterator.count()
}
fn last(self) -> Option<Self::Item> {
self.iterator.last($array_ref).map($mapper)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iterator.nth(n, $array_ref).map($mapper)
}
}
};
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CountryIterator {
iterator: ArrayIterator,
}
impl_iterator!(
CountryIterator,
Country,
SUPPORTED_ALPHA2_LIST,
*SUPPORTED_COUNTRIES_COUNT,
|alpha2| alpha2.to_country()
);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ContinentIterator {
iterator: ArrayIterator,
}
impl_iterator!(
ContinentIterator,
Continent,
SUPPORTED_CONTINENT_LIST,
SUPPORTED_CONTINENT_LIST.len(),
|x| x
);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RegionIterator {
iterator: ArrayIterator,
}
impl_iterator!(
RegionIterator,
Region,
SUPPORTED_REGION_LIST,
SUPPORTED_REGION_LIST.len(),
|x| x
);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SubRegionIterator {
iterator: ArrayIterator,
}
impl_iterator!(
SubRegionIterator,
SubRegion,
SUPPORTED_SUBREGION_LIST,
SUPPORTED_SUBREGION_LIST.len(),
|x| x
);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct WorldRegionIterator {
iterator: ArrayIterator,
}
impl_iterator!(
WorldRegionIterator,
WorldRegion,
SUPPORTED_WORLD_REGION_LIST,
SUPPORTED_WORLD_REGION_LIST.len(),
|x| x
);