#[derive(Clone, Debug, Default)]
pub(crate) struct CsrU32 {
data: Vec<u32>,
offsets: Vec<u32>,
}
impl CsrU32 {
pub(crate) fn from_pairs(
row_count: usize,
pairs: impl IntoIterator<Item = (usize, usize)>,
) -> Self {
assert!(
row_count <= u32::MAX as usize,
"CSR row count exceeds the u32 offset representation"
);
let mut pairs = pairs
.into_iter()
.map(|(row, value)| {
assert!(row < row_count, "CSR pair row {row} exceeds {row_count}");
assert!(
value <= u32::MAX as usize,
"CSR value exceeds the u32 representation"
);
(row, value as u32)
})
.collect::<Vec<_>>();
pairs.sort_by_key(|(row, _)| *row);
let mut data = Vec::with_capacity(pairs.len());
let mut offsets = Vec::with_capacity(row_count + 1);
offsets.push(0);
let mut cursor = 0;
for row in 0..row_count {
while cursor < pairs.len() && pairs[cursor].0 == row {
data.push(pairs[cursor].1);
cursor += 1;
}
offsets.push(data.len() as u32);
}
debug_assert_eq!(cursor, pairs.len());
Self { data, offsets }
}
#[inline]
pub(crate) fn get(&self, i: usize) -> Option<&[u32]> {
let start = *self.offsets.get(i)? as usize;
let end = *self.offsets.get(i + 1)? as usize;
Some(&self.data[start..end])
}
#[inline]
pub(crate) fn len(&self) -> usize {
self.offsets.len().saturating_sub(1)
}
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.len() == 0
}
pub(crate) fn iter(&self) -> impl ExactSizeIterator<Item = &[u32]> {
(0..self.len()).map(|index| &self[index])
}
pub(crate) fn storage_lengths(&self) -> (usize, usize) {
(self.data.len(), self.offsets.len())
}
}
impl std::ops::Index<usize> for CsrU32 {
type Output = [u32];
#[inline]
fn index(&self, i: usize) -> &[u32] {
let start = self.offsets[i] as usize;
let end = self.offsets[i + 1] as usize;
&self.data[start..end]
}
}