#[derive(Debug, Clone)]
pub struct RaggedArray<T> {
offsets: Vec<usize>,
values: Vec<T>,
}
impl<T> Default for RaggedArray<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> RaggedArray<T> {
pub fn new() -> Self {
Self {
offsets: vec![0],
values: Vec::new(),
}
}
pub fn push(&mut self, values: impl IntoIterator<Item = T>) {
self.values.extend(values);
self.offsets.push(self.values.len());
}
pub fn clear(&mut self) {
self.offsets.truncate(1);
self.values.clear();
}
pub fn len(&self) -> usize {
self.offsets.len() - 1
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn shrink_to_fit(&mut self) {
self.offsets.shrink_to_fit();
self.values.shrink_to_fit();
}
pub fn shrink_values_to(&mut self, min_capacity: usize) {
self.values.shrink_to(min_capacity);
}
pub fn values_capacity(&self) -> usize {
self.values.capacity()
}
pub fn num_values(&self) -> usize {
self.values.len()
}
}
impl<T> core::ops::Index<usize> for RaggedArray<T> {
type Output = [T];
fn index(&self, row: usize) -> &Self::Output {
let start = self.offsets[row];
let end = self.offsets[row + 1];
&self.values[start..end]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_array_is_empty() {
let matrix: RaggedArray<i32> = RaggedArray::new();
assert_eq!(matrix.len(), 0);
}
#[test]
fn test_push_rows_and_indexing() {
let mut matrix = RaggedArray::new();
matrix.push(vec![1, 2, 3]);
matrix.push(vec![4, 5]);
assert_eq!(matrix.len(), 2);
assert_eq!(&matrix[0], &[1, 2, 3]);
assert_eq!(&matrix[1], &[4, 5]);
}
#[test]
fn test_ragged_rows_and_empty_rows() {
let mut matrix = RaggedArray::new();
matrix.push(vec![1]);
matrix.push(vec![]);
matrix.push(vec![2, 3, 4]);
assert_eq!(matrix.len(), 3);
assert_eq!(&matrix[0], &[1]);
assert_eq!(&matrix[1], &[]);
assert_eq!(&matrix[2], &[2, 3, 4]);
}
#[test]
fn test_clear_and_reuse() {
let mut matrix = RaggedArray::new();
matrix.push(vec![1, 2]);
matrix.push(vec![3]);
assert_eq!(matrix.len(), 2);
matrix.clear();
assert_eq!(matrix.len(), 0);
matrix.push(vec![10, 20]);
matrix.push(vec![]);
matrix.push(vec![30]);
assert_eq!(matrix.len(), 3);
assert_eq!(&matrix[0], &[10, 20]);
assert_eq!(&matrix[1], &[]);
assert_eq!(&matrix[2], &[30]);
}
#[test]
#[should_panic]
fn test_index_out_of_bounds() {
let mut matrix = RaggedArray::new();
matrix.push(vec![1]);
let _ = &matrix[1];
}
}