use std::cmp::{max, min, Ordering};
use std::mem::replace;
use super::{CheckedIterator, HasMaxDepth, HpxCell, HpxHash, MOCIterator};
pub fn not<H, T>(it: T) -> NotMocIter<H, CheckedIterator<H, T>>
where
H: HpxHash,
T: MOCIterator<H>,
{
let it = CheckedIterator::new(it);
not_unchecked(it)
}
pub fn not_unchecked<H, T>(it: T) -> NotMocIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
NotMocIter::new_unchecked(it)
}
pub fn and<H, T1, T2>(
left_it: T1,
right_it: T2,
) -> AndMocIter<H, CheckedIterator<H, T1>, CheckedIterator<H, T2>>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
let left_it = CheckedIterator::new(left_it);
let right_it = CheckedIterator::new(right_it);
and_unchecked(left_it, right_it)
}
pub fn and_unchecked<H, T1, T2>(left_it: T1, right_it: T2) -> AndMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
AndMocIter::new_unchecked(left_it, right_it)
}
pub fn or<H, T1, T2>(
left_it: T1,
right_it: T2,
) -> OrMocIter<H, CheckedIterator<H, T1>, CheckedIterator<H, T2>>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
let left_it = CheckedIterator::new(left_it);
let right_it = CheckedIterator::new(right_it);
or_unchecked(left_it, right_it)
}
pub fn or_unchecked<H, T1, T2>(left_it: T1, right_it: T2) -> OrMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
OrMocIter::new_unchecked(left_it, right_it)
}
pub struct MergeIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
it: T,
to_be_possibly_packed: Vec<HpxCell<H>>,
flush_stack: u8,
}
impl<H, T> MergeIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
pub fn new(it: T) -> MergeIter<H, T> {
let depth_max = it.depth_max();
MergeIter {
it,
to_be_possibly_packed: Vec::with_capacity(3 * depth_max as usize), flush_stack: 0,
}
}
fn pack_stack(&mut self) {
let h0 = H::zero();
let h1 = H::one();
let h2 = h1 << 1;
let h3 = h2 | h1;
while self.to_be_possibly_packed.len() >= 4 {
let len = &self.to_be_possibly_packed.len();
let one = &self.to_be_possibly_packed[len - 4];
let two = &self.to_be_possibly_packed[len - 3];
let thr = &self.to_be_possibly_packed[len - 2];
let fou = &self.to_be_possibly_packed[len - 1];
if one.hash & h3 == h0
&& one.depth == two.depth
&& one.depth == thr.depth
&& one.depth == fou.depth
&& one.hash + h1 == two.hash
&& one.hash + h2 == thr.hash
&& one.hash + h3 == fou.hash
{
let depth = one.depth - 1;
let hash = one.hash >> 2;
self.to_be_possibly_packed.truncate(len - 4);
self.to_be_possibly_packed.push(HpxCell { depth, hash });
if depth == 0 {
debug_assert_eq!(self.to_be_possibly_packed.len(), 1);
self.flush_stack = 1;
}
} else {
break;
}
}
}
}
impl<H, T> HasMaxDepth for MergeIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
fn depth_max(&self) -> u8 {
self.it.depth_max()
}
}
impl<H, T> Iterator for MergeIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
type Item = HpxCell<H>;
fn next(&mut self) -> Option<Self::Item> {
if self.flush_stack > 0 {
self.flush_stack -= 1;
Some(self.to_be_possibly_packed.remove(0))
} else {
let h0 = H::zero();
let h1 = H::one();
let h2 = h1 << 1;
let h3 = h2 & h1;
let new = self.it.next();
match new {
Some(curr) => {
if !self.to_be_possibly_packed.is_empty() {
let prev = self.to_be_possibly_packed.last().unwrap();
if curr.depth == prev.depth && curr.hash == prev.hash + H::one() {
let pack = curr.hash & h3 == h3;
self.to_be_possibly_packed.push(curr);
if pack {
self.pack_stack();
}
} else if curr.depth > prev.depth
&& curr.hash == (prev.hash + h1) << (((curr.depth - prev.depth) << 1) as usize)
{
debug_assert_eq!(curr.hash & h3, h0);
self.to_be_possibly_packed.push(curr);
} else {
let curr_d = curr.depth;
let curr_h = curr.hash;
self.to_be_possibly_packed.push(curr);
self.flush_stack = if curr_d > 0 && curr_h & h3 == h0 {
self.to_be_possibly_packed.len() - 1
} else {
self.to_be_possibly_packed.len()
} as u8;
}
self.next()
} else if curr.depth > 0 && curr.hash & h3 == h0 {
self.to_be_possibly_packed.push(curr);
self.next()
} else {
Some(curr)
}
}
None => {
if !self.to_be_possibly_packed.is_empty() {
self.flush_stack = self.to_be_possibly_packed.len() as u8;
self.next()
} else {
None
}
}
}
}
}
}
pub struct MinusOnSingleDepthCellsIter<H, T1, T2>
where
H: HpxHash,
T1: Iterator<Item = H>,
T2: Iterator<Item = H>,
{
depth: u8,
left_it: T1,
right_it: T2,
left: Option<HpxCell<H>>,
right: Option<HpxCell<H>>,
to_be_possibly_packed: Vec<HpxCell<H>>,
flush_stack: u8,
}
impl<H, T1, T2> MinusOnSingleDepthCellsIter<H, T1, T2>
where
H: HpxHash,
T1: Iterator<Item = H>,
T2: Iterator<Item = H>,
{
pub fn new(
depth: u8,
mut left_it: T1,
mut right_it: T2,
) -> MinusOnSingleDepthCellsIter<H, T1, T2> {
let left = left_it.next().map(|hash| HpxCell { depth, hash });
let right = right_it.next().map(|hash| HpxCell { depth, hash });
MinusOnSingleDepthCellsIter {
depth,
left_it,
right_it,
left,
right,
to_be_possibly_packed: Default::default(),
flush_stack: 0,
}
}
fn pack_stack(&mut self) {
let h0 = H::zero();
let h1 = H::one();
let h2 = h1 << 1;
let h3 = h2 | h1;
while self.to_be_possibly_packed.len() >= 4 {
let len = &self.to_be_possibly_packed.len();
let one = &self.to_be_possibly_packed[len - 4];
let two = &self.to_be_possibly_packed[len - 3];
let thr = &self.to_be_possibly_packed[len - 2];
let fou = &self.to_be_possibly_packed[len - 1];
if one.hash & h3 == h0
&& one.depth == two.depth
&& one.depth == thr.depth
&& one.depth == fou.depth
&& one.hash + h1 == two.hash
&& one.hash + h2 == thr.hash
&& one.hash + h3 == fou.hash
{
let depth = one.depth - 1;
let hash = one.hash >> 2;
self.to_be_possibly_packed.truncate(len - 4);
self.to_be_possibly_packed.push(HpxCell { depth, hash });
if depth == 0 {
debug_assert_eq!(self.to_be_possibly_packed.len(), 1);
self.flush_stack = 1;
}
} else {
break;
}
}
}
fn unpacked_next(&mut self) -> Option<HpxCell<H>> {
let depth = self.depth;
match (&self.left, &self.right) {
(Some(l), Some(r)) => match l.hash.cmp(&r.hash) {
Ordering::Less => replace(
&mut self.left,
self.left_it.next().map(|hash| HpxCell { depth, hash }),
),
Ordering::Greater => {
self.right = self.right_it.next().map(|hash| HpxCell { depth, hash });
self.unpacked_next()
}
Ordering::Equal => {
self.left = self.left_it.next().map(|hash| HpxCell { depth, hash });
self.right = self.right_it.next().map(|hash| HpxCell { depth, hash });
self.unpacked_next()
}
},
(Some(_l), None) => replace(
&mut self.left,
self.left_it.next().map(|hash| HpxCell { depth, hash }),
),
(None, _) => None,
}
}
}
impl<H, T1, T2> HasMaxDepth for MinusOnSingleDepthCellsIter<H, T1, T2>
where
H: HpxHash,
T1: Iterator<Item = H>,
T2: Iterator<Item = H>,
{
fn depth_max(&self) -> u8 {
self.depth
}
}
impl<H, T1, T2> Iterator for MinusOnSingleDepthCellsIter<H, T1, T2>
where
H: HpxHash,
T1: Iterator<Item = H>,
T2: Iterator<Item = H>,
{
type Item = HpxCell<H>;
fn next(&mut self) -> Option<Self::Item> {
let h0 = H::zero();
let h1 = H::one();
let h2 = h1 << 1;
let h3 = h2 & h1;
if self.flush_stack > 0 {
self.flush_stack -= 1;
Some(self.to_be_possibly_packed.remove(0))
} else {
let new = self.unpacked_next();
match new {
Some(curr) => {
if !self.to_be_possibly_packed.is_empty() {
let prev = self.to_be_possibly_packed.last().unwrap();
if curr.depth == prev.depth && curr.hash == prev.hash + H::one() {
let pack = curr.hash & h3 == h3;
self.to_be_possibly_packed.push(curr);
if pack {
self.pack_stack();
}
} else if curr.depth > prev.depth
&& curr.hash == (prev.hash + h1) << (((curr.depth - prev.depth) << 1) as usize)
{
debug_assert_eq!(curr.hash & h3, h0);
self.to_be_possibly_packed.push(curr);
} else {
let curr_d = curr.depth;
let curr_h = curr.hash;
self.to_be_possibly_packed.push(curr);
self.flush_stack = if curr_d > 0 && curr_h & h3 == h0 {
self.to_be_possibly_packed.len() - 1
} else {
self.to_be_possibly_packed.len()
} as u8;
}
self.next()
} else if curr.depth > 0 && curr.hash & h3 == h0 {
self.to_be_possibly_packed.push(curr);
self.next()
} else {
Some(curr)
}
}
None => {
if !self.to_be_possibly_packed.is_empty() {
self.flush_stack = self.to_be_possibly_packed.len() as u8;
self.next()
} else {
None
}
}
}
}
}
}
pub struct NotMocIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
it: T,
curr: Option<HpxCell<H>>,
curr_d: u8,
curr_h: H,
}
impl<H, T> NotMocIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
fn new_unchecked(mut it: T) -> NotMocIter<H, T> {
let curr = it.next();
NotMocIter {
it,
curr,
curr_d: 0,
curr_h: H::zero(),
}
}
fn get_current_cell(&self) -> HpxCell<H> {
HpxCell {
depth: self.curr_d,
hash: self.curr_h,
}
}
fn next_cell(&mut self) {
self.curr_h += H::one();
self.go_up_if_needed();
}
fn go_up_if_needed(&mut self) {
let dd = self
.curr_d
.min(self.curr_h.trailing_zeros() as u8 / 2)
.min(self.curr_d);
self.curr_d -= dd;
self.curr_h >>= dd << 1;
}
}
impl<H, T> HasMaxDepth for NotMocIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
fn depth_max(&self) -> u8 {
self.it.depth_max()
}
}
impl<H, T> Iterator for NotMocIter<H, T>
where
H: HpxHash,
T: MOCIterator<H>,
{
type Item = HpxCell<H>;
fn next(&mut self) -> Option<Self::Item> {
match &self.curr {
Some(c) => {
while self.curr_d < c.depth
&& self.curr_h == (c.hash >> ((c.depth - self.curr_d) << 1) as usize)
{
self.curr_d += 1;
self.curr_h <<= 2;
}
if self.curr_d == c.depth && self.curr_h == c.hash {
self.next_cell();
self.curr = self.it.next();
self.next()
} else {
let c = self.get_current_cell();
self.next_cell();
Some(c)
}
}
None => {
let twelve = (H::one() + (H::one() << 1)) << 2_usize; if self.curr_h < twelve << ((self.curr_d << 1) as usize) {
let c = self.get_current_cell();
self.next_cell();
Some(c)
} else {
None
}
}
}
}
}
pub struct AndMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
left_it: T1,
right_it: T2,
depth_max: u8,
left: Option<HpxCell<H>>,
right: Option<HpxCell<H>>,
}
impl<H, T1, T2> AndMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
fn new_unchecked(mut left_it: T1, mut right_it: T2) -> AndMocIter<H, T1, T2> {
let depth_max = max(left_it.depth_max(), right_it.depth_max());
let left = left_it.next();
let right = right_it.next();
AndMocIter {
left_it,
right_it,
depth_max,
left,
right,
}
}
}
impl<H, T1, T2> HasMaxDepth for AndMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
fn depth_max(&self) -> u8 {
self.depth_max
}
}
impl<H, T1, T2> Iterator for AndMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
type Item = HpxCell<H>;
fn next(&mut self) -> Option<Self::Item> {
while let (Some(l), Some(r)) = (&self.left, &self.right) {
match l.depth.cmp(&r.depth) {
Ordering::Less => {
let hr_at_dl = r.hash.unsigned_shr(((r.depth - l.depth) << 1) as u32);
match l.hash.cmp(&hr_at_dl) {
Ordering::Less => self.left = self.left_it.next(),
Ordering::Greater => self.right = self.right_it.next(),
Ordering::Equal => {
return replace(&mut self.right, self.right_it.next());
}
}
}
Ordering::Greater => {
let hl_at_dr = l.hash.unsigned_shr(((l.depth - r.depth) << 1) as u32);
match hl_at_dr.cmp(&r.hash) {
Ordering::Less => self.left = self.left_it.next(),
Ordering::Greater => self.right = self.right_it.next(),
Ordering::Equal => {
return replace(&mut self.left, self.left_it.next());
}
}
}
Ordering::Equal => match l.hash.cmp(&r.hash) {
Ordering::Less => self.left = self.left_it.next(),
Ordering::Greater => self.right = self.right_it.next(),
Ordering::Equal => {
self.left = self.left_it.next();
return replace(&mut self.right, self.right_it.next());
}
},
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size_hint_l = self.left_it.size_hint();
let size_hint_r = self.right_it.size_hint();
if let (Some(n1), Some(n2)) = (size_hint_l.1, size_hint_r.1) {
(0, Some(1 + n1 + n2))
} else {
(0, None)
}
}
}
pub struct OrMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
left_it: T1,
right_it: T2,
depth_max: u8,
left: Option<HpxCell<H>>,
right: Option<HpxCell<H>>,
to_be_possibly_packed: Vec<HpxCell<H>>,
flush_stack: u8,
}
impl<H, T1, T2> OrMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
fn new_unchecked(mut left_it: T1, mut right_it: T2) -> OrMocIter<H, T1, T2> {
let depth_max = max(left_it.depth_max(), right_it.depth_max());
let left = left_it.next();
let right = right_it.next();
OrMocIter {
left_it,
right_it,
depth_max,
left,
right,
to_be_possibly_packed: Default::default(),
flush_stack: 0, }
}
pub fn depth_max(&self) -> u8 {
self.depth_max
}
fn pack_stack(&mut self) {
let h0 = H::zero();
let h1 = H::one();
let h2 = h1 << 1;
let h3 = h2 | h1;
while self.to_be_possibly_packed.len() >= 4 {
let len = &self.to_be_possibly_packed.len();
let one = &self.to_be_possibly_packed[len - 4];
let two = &self.to_be_possibly_packed[len - 3];
let thr = &self.to_be_possibly_packed[len - 2];
let fou = &self.to_be_possibly_packed[len - 1];
if one.hash & h3 == h0
&& one.depth == two.depth
&& one.depth == thr.depth
&& one.depth == fou.depth
&& one.hash + h1 == two.hash
&& one.hash + h2 == thr.hash
&& one.hash + h3 == fou.hash
{
let depth = one.depth - 1;
let hash = one.hash >> 2;
self.to_be_possibly_packed.truncate(len - 4);
self.to_be_possibly_packed.push(HpxCell { depth, hash });
if depth == 0 {
debug_assert_eq!(self.to_be_possibly_packed.len(), 1);
self.flush_stack = 1;
}
} else {
break;
}
}
}
fn unpacked_next(&mut self) -> Option<HpxCell<H>> {
match (&self.left, &self.right) {
(Some(l), Some(r)) => match l.depth.cmp(&r.depth) {
Ordering::Less => {
let hr_at_dl = r.hash.unsigned_shr(((r.depth - l.depth) << 1) as u32);
match l.hash.cmp(&hr_at_dl) {
Ordering::Less => replace(&mut self.left, self.left_it.next()),
Ordering::Greater => replace(&mut self.right, self.right_it.next()),
Ordering::Equal => {
self.right = consume_overlapped_cells(&mut self.right_it, l);
replace(&mut self.left, self.left_it.next())
}
}
}
Ordering::Greater => {
let hl_at_dr = l.hash.unsigned_shr(((l.depth - r.depth) << 1) as u32);
match hl_at_dr.cmp(&r.hash) {
Ordering::Less => replace(&mut self.left, self.left_it.next()),
Ordering::Greater => replace(&mut self.right, self.right_it.next()),
Ordering::Equal => {
self.left = consume_overlapped_cells(&mut self.left_it, r);
replace(&mut self.right, self.right_it.next())
}
}
}
Ordering::Equal => match l.hash.cmp(&r.hash) {
Ordering::Less => replace(&mut self.left, self.left_it.next()),
Ordering::Greater => replace(&mut self.right, self.right_it.next()),
Ordering::Equal => {
self.left = self.left_it.next();
replace(&mut self.right, self.right_it.next())
}
},
},
(Some(_l), None) => replace(&mut self.left, self.left_it.next()),
(None, Some(_r)) => replace(&mut self.right, self.right_it.next()),
(None, None) => None,
}
}
}
impl<H, T1, T2> HasMaxDepth for OrMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
fn depth_max(&self) -> u8 {
self.depth_max
}
}
impl<H, T1, T2> Iterator for OrMocIter<H, T1, T2>
where
H: HpxHash,
T1: MOCIterator<H>,
T2: MOCIterator<H>,
{
type Item = HpxCell<H>;
fn next(&mut self) -> Option<Self::Item> {
let h0 = H::zero();
let h1 = H::one();
let h2 = h1 << 1;
let h3 = h2 & h1;
if self.flush_stack > 0 {
self.flush_stack -= 1;
Some(self.to_be_possibly_packed.remove(0))
} else {
let new = self.unpacked_next();
match new {
Some(curr) => {
if !self.to_be_possibly_packed.is_empty() {
let prev = self.to_be_possibly_packed.last().unwrap();
if curr.depth == prev.depth && curr.hash == prev.hash + H::one() {
let pack = curr.hash & h3 == h3;
self.to_be_possibly_packed.push(curr);
if pack {
self.pack_stack();
}
} else if curr.depth > prev.depth
&& curr.hash == (prev.hash + h1) << (((curr.depth - prev.depth) << 1) as usize)
{
debug_assert_eq!(curr.hash & h3, h0);
self.to_be_possibly_packed.push(curr);
} else {
let curr_d = curr.depth;
let curr_h = curr.hash;
self.to_be_possibly_packed.push(curr);
self.flush_stack = if curr_d > 0 && curr_h & h3 == h0 {
self.to_be_possibly_packed.len() - 1
} else {
self.to_be_possibly_packed.len()
} as u8;
}
self.next()
} else if curr.depth > 0 && curr.hash & h3 == h0 {
self.to_be_possibly_packed.push(curr);
self.next()
} else {
Some(curr)
}
}
None => {
if !self.to_be_possibly_packed.is_empty() {
self.flush_stack = self.to_be_possibly_packed.len() as u8;
self.next()
} else {
None
}
}
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size_hint_l = self.left_it.size_hint();
let size_hint_r = self.right_it.size_hint();
match (size_hint_l.1, size_hint_r.1) {
(Some(n1), Some(n2)) => (1 + min(n1, n2), Some(1 + n1 + n2)),
(Some(n1), None) => (1 + n1, Some(1 + n1)),
(None, Some(n2)) => (1 + n2, Some(1 + n2)),
(None, None) => {
if self.left.is_some() || self.right.is_some() {
(1, Some(1))
} else {
(0, Some(0))
}
}
}
}
}
fn consume_overlapped_cells<H, T2>(it: &mut T2, low_res_cell: &HpxCell<H>) -> Option<HpxCell<H>>
where
H: HpxHash,
T2: Iterator<Item = HpxCell<H>>,
{
let mut curr = it.next();
while let Some(c) = &curr {
if c.depth <= low_res_cell.depth
|| low_res_cell.hash
!= c
.hash
.unsigned_shr(((c.depth - low_res_cell.depth) << 1) as u32)
{
break;
} else {
curr = it.next();
}
}
curr
}
#[cfg(test)]
mod tests {
use super::super::LazyMOCIter;
use super::*;
#[test]
pub fn test_not_empty() {
for depth in 0..30 {
let empty_it = std::iter::empty::<HpxCell<u64>>();
let mut full_it = not_unchecked(LazyMOCIter::new(depth, empty_it));
for hash in 0..12_u64 {
assert_eq!(full_it.next(), Some(HpxCell { depth: 0, hash }));
}
assert_eq!(full_it.next(), None);
}
}
#[test]
pub fn test_not_full() {
for depth in 0..30 {
let mut empty_it = not_unchecked(LazyMOCIter::new(
depth,
(0..12_u64)
.map(|hash| HpxCell { depth: 0, hash }),
));
assert_eq!(empty_it.next(), None);
}
}
#[test]
pub fn test_and_full_full() {
for depth in 0..30 {
let full_1: Vec<HpxCell<u64>> = (0..12_u64)
.map(|hash| HpxCell { depth: 0, hash })
.collect();
let full_2: Vec<HpxCell<u64>> = (0..12_u64)
.map(|hash| HpxCell { depth: 0, hash })
.collect();
let mut full_it = and_unchecked(
LazyMOCIter::new(depth, full_1.into_iter()),
LazyMOCIter::new(depth, full_2.into_iter()),
);
for hash in 0..12_u64 {
assert_eq!(full_it.next(), Some(HpxCell { depth: 0, hash }));
}
assert_eq!(full_it.next(), None);
}
}
#[test]
pub fn test_and_empty_full() {
for depth in 0..30 {
let empty_it = std::iter::empty::<HpxCell<u64>>();
let full: Vec<HpxCell<u64>> = (0..12_u64)
.map(|hash| HpxCell { depth: 0, hash })
.collect();
let mut emtpy_res = and_unchecked(
LazyMOCIter::new(depth, empty_it),
LazyMOCIter::new(depth, full.into_iter()),
);
assert_eq!(emtpy_res.next(), None);
}
}
#[test]
pub fn test_or_full_empty() {
for depth in 0..30 {
let empty_it = std::iter::empty::<HpxCell<u64>>();
let full: Vec<HpxCell<u64>> = (0..12_u64)
.map(|hash| HpxCell { depth: 0, hash })
.collect();
let mut full_it = or_unchecked(
LazyMOCIter::new(depth, empty_it),
LazyMOCIter::new(depth, full.into_iter()),
);
for hash in 0..12_u64 {
assert_eq!(full_it.next(), Some(HpxCell { depth: 0, hash }));
}
assert_eq!(full_it.next(), None);
}
}
#[test]
pub fn test_or_empty_empty() {
for depth in 0..30 {
let empty_it_1 = std::iter::empty::<HpxCell<u64>>();
let empty_it_2 = std::iter::empty::<HpxCell<u64>>();
let mut emtpy_res = and_unchecked(
LazyMOCIter::new(depth, empty_it_1),
LazyMOCIter::new(depth, empty_it_2),
);
assert_eq!(emtpy_res.next(), None);
}
}
}