#![allow(clippy::bool_comparison)]
use bitstring::BitString;
#[derive(Clone, Debug)]
pub struct IterInclusive<K> {
first: K, last: K, shared_len: usize, }
impl<K> IterInclusive<K>
where
K: BitString + Clone,
{
fn empty() -> Self {
Self {
first: K::null(),
last: K::null(),
shared_len: 1,
}
}
fn all() -> Self {
Self {
first: K::null(),
last: K::null(),
shared_len: 0,
}
}
}
impl<K> Default for IterInclusive<K>
where
K: BitString + Clone,
{
fn default() -> Self {
Self::empty()
}
}
impl<K> Iterator for IterInclusive<K>
where
K: BitString + Clone,
{
type Item = K;
fn next(&mut self) -> Option<Self::Item> {
let first_len = self.first.len();
if self.shared_len > first_len {
return None;
}
if first_len == self.shared_len {
let last_len = self.last.len();
if last_len == self.shared_len {
self.shared_len = !0;
self.first.clip(0);
return Some(self.last.clone());
} else {
debug_assert!(
last_len == self.shared_len,
"first was shared prefix, but last was longer"
);
return None; }
}
let result = self.first.clone();
for pos in (self.shared_len + 1..first_len).rev() {
if false == self.first.get(pos) {
self.first.clip(pos + 1); self.first.flip(pos); return Some(result);
}
}
if true == self.first.get(self.shared_len) {
debug_assert!(
!self.first.get(self.shared_len),
"first should have a '0' after shared prefix"
);
return None; }
if false == self.last.get(self.shared_len) {
debug_assert!(
self.last.get(self.shared_len),
"last should have a '1' after shared prefix"
);
return None; }
self.first = self.last.clone();
let check_from = self.shared_len + 1; self.shared_len = self.last.len(); for pos in check_from..self.shared_len {
if self.first.get(pos) {
self.first.clip(pos + 1);
self.first.flip(pos);
self.shared_len = pos;
break;
}
}
Some(result)
}
}
pub fn iter_inclusive<K>(mut first: K, mut last: K) -> IterInclusive<K>
where
K: BitString + Clone,
{
let mut first_len = first.len();
while first_len > 0 && false == first.get(first_len - 1) {
first_len -= 1;
}
first.clip(first_len);
let mut last_len = last.len();
while last_len > 0 && true == last.get(last_len - 1) {
last_len -= 1;
}
last.clip(last_len);
let mut shared_len = first.shared_prefix_len(&last);
if shared_len == first_len {
while shared_len < last_len && false == last.get(shared_len) {
shared_len += 1;
}
first = last.clone();
if shared_len == last_len {
first.clip(shared_len);
} else {
first.clip(shared_len + 1);
first.flip(shared_len);
}
} else if shared_len == last_len {
while shared_len < first_len && true == first.get(shared_len) {
shared_len += 1;
}
last = first.clone();
if shared_len == first_len {
last.clip(shared_len);
} else {
last.clip(shared_len + 1);
last.flip(shared_len);
}
} else if first.get(shared_len) > last.get(shared_len) {
return IterInclusive::empty();
}
IterInclusive {
first,
last,
shared_len,
}
}
#[derive(Clone, Debug)]
pub struct IterBetween<K> {
range: IterInclusive<K>,
}
impl<K> Default for IterBetween<K>
where
K: BitString + Clone,
{
fn default() -> Self {
Self {
range: IterInclusive::empty(),
}
}
}
impl<K> Iterator for IterBetween<K>
where
K: BitString + Clone,
{
type Item = K;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.range.next()
}
}
fn increment<K>(key: &mut K) -> bool
where
K: BitString + Clone,
{
for pos in (0..key.len()).rev() {
if false == key.get(pos) {
key.clip(pos + 1);
key.flip(pos);
return true;
}
}
false
}
fn decrement<K>(key: &mut K) -> bool
where
K: BitString + Clone,
{
for pos in (0..key.len()).rev() {
if true == key.get(pos) {
key.clip(pos + 1);
key.flip(pos);
return true;
}
}
false
}
pub fn iter_between<K>(mut after: Option<K>, mut before: Option<K>) -> IterBetween<K>
where
K: BitString + Clone,
{
if let Some(start) = after.as_mut() {
if !increment(start) {
return IterBetween {
range: IterInclusive::empty(),
};
}
}
if let Some(end) = before.as_mut() {
if !decrement(end) {
return IterBetween {
range: IterInclusive::empty(),
};
}
}
let range = match (after, before) {
(Some(first), Some(last)) => iter_inclusive(first, last),
(Some(first), None) => {
let mut last = first.clone();
for pos in 0..last.len() {
if false == last.get(pos) {
last.clip(pos + 1);
last.flip(pos);
break;
}
}
iter_inclusive(first, last)
},
(None, Some(last)) => {
let mut first = last.clone();
for pos in 0..first.len() {
if true == first.get(pos) {
first.clip(pos + 1);
first.flip(pos);
break;
}
}
iter_inclusive(first, last)
},
(None, None) => IterInclusive::all(),
};
IterBetween { range }
}
#[cfg(test)]
mod tests {
use super::iter_inclusive;
use alloc::vec::Vec;
use bitstring::BitLengthString;
use core::net::{
Ipv4Addr,
Ipv6Addr,
};
type Ipv4Cidr = BitLengthString<Ipv4Addr>;
type Ipv6Cidr = BitLengthString<Ipv6Addr>;
fn c4(a: &str, net: usize) -> Ipv4Cidr {
Ipv4Cidr::new(a.parse().unwrap(), net)
}
fn c6(a: &str, net: usize) -> Ipv6Cidr {
Ipv6Cidr::new(a.parse().unwrap(), net)
}
#[test]
fn testv4_1() {
assert_eq!(
iter_inclusive(c4("192.168.0.6", 32), c4("192.168.0.6", 32)).collect::<Vec<_>>(),
alloc::vec![c4("192.168.0.6", 32),]
);
}
#[test]
fn testv6_1() {
assert_eq!(
iter_inclusive(c6("::f0:4", 128), c6("::f0:10", 128)).collect::<Vec<_>>(),
alloc::vec![c6("::f0:4", 126), c6("::f0:8", 125), c6("::f0:10", 128),]
);
}
}