use super::super::{ColdStamps, HotNbr, Nbr, Timestamp, VertexId};
use super::ImmutableCsr;
impl ImmutableCsr {
pub fn iter(&self, ts: Timestamp) -> ImmutableCsrIterator<'_> {
ImmutableCsrIterator::new(self, ts)
}
pub fn iter_edges_of(&self, src_vid: u32, ts: Timestamp) -> FrozenRowIter<'_> {
let (start, end) = self.row_window(src_vid).unwrap_or((0, 0));
FrozenRowIter {
hot: &self.hot_entries[start..end],
cold: &self.cold_entries[start..end],
ts,
idx: 0,
}
}
pub fn iter_all(&self) -> ImmutableCsrIterator<'_> {
ImmutableCsrIterator::new_all(self)
}
}
pub struct FrozenRowIter<'a> {
hot: &'a [HotNbr],
cold: &'a [ColdStamps],
ts: Timestamp,
idx: usize,
}
impl<'a> Iterator for FrozenRowIter<'a> {
type Item = Nbr;
fn next(&mut self) -> Option<Self::Item> {
while self.idx < self.hot.len() {
let nbr = Nbr::from_parts(self.hot[self.idx], self.cold[self.idx]);
self.idx += 1;
if nbr.is_alive_at(self.ts) {
return Some(nbr);
}
}
None
}
}
pub struct ImmutableCsrIterator<'a> {
csr: &'a ImmutableCsr,
ts: Timestamp,
include_deleted: bool,
row: usize,
idx: usize,
}
impl<'a> ImmutableCsrIterator<'a> {
fn new(csr: &'a ImmutableCsr, ts: Timestamp) -> Self {
Self {
csr,
ts,
include_deleted: false,
row: 0,
idx: 0,
}
}
fn new_all(csr: &'a ImmutableCsr) -> Self {
Self {
csr,
ts: 0,
include_deleted: true,
row: 0,
idx: 0,
}
}
}
impl<'a> Iterator for ImmutableCsrIterator<'a> {
type Item = (VertexId, Nbr);
fn next(&mut self) -> Option<Self::Item> {
while self.row < self.csr.degrees.len() {
let end = self.csr.offsets[self.row] as usize + self.csr.degrees[self.row] as usize;
while self.idx < end {
let nbr = self.csr.slot_at(self.idx).unwrap();
self.idx += 1;
if self.include_deleted || nbr.is_alive_at(self.ts) {
return Some((VertexId::from_u32(u32::try_from(self.row).ok()?), nbr));
}
}
self.row += 1;
if self.row < self.csr.offsets.len() {
self.idx = self.csr.offsets[self.row] as usize;
}
}
None
}
}