round_pipers 0.2.0

A way to pipe ndarrays using circular buffers
Documentation
use crate::error::Result;
use crate::iterator_common::ChunkGuard;
use crate::pipe_common::PipeState;
use ndarray::{ArrayView, ArrayView1, ArrayViewMut, Dim, Dimension, StrideShape};
use uuid::Uuid;

pub trait Readable<A, D: SizedDimension + Dimension, M: Clone> {
    fn read<R>(
        &self,
        n_to_read: usize,
        n_to_consume: usize,
        f: impl FnOnce(ArrayView<A, D::Larger>, PipeState) -> R,
    ) -> Result<R>
    where
        D::LargerSize: Into<StrideShape<D::Larger>> + Clone,
        D::CurrentSize: Clone;

    fn get_metadata(&self) -> Option<M>;
}

pub trait Writable<A, D: SizedDimension + Dimension, M: Clone> {
    fn write<R>(
        &self,
        n_to_write: usize,
        f: impl FnOnce(ArrayViewMut<A, D::Larger>, PipeState) -> R,
    ) -> Result<R>
    where
        D::LargerSize: Into<StrideShape<D::Larger>> + Clone,
        D::CurrentSize: Clone;

    fn set_metadata(&self, metadata: &M);
}

/// Trait for types that can provide chunks of data for iteration
/// This allows both circular buffer pipes and read-only pipes to work with the same iterator API
pub trait ChunkSource<A, D: SizedDimension + Dimension, M: Clone> {
    /// Read a chunk of data for iteration, returning a ChunkGuard that manages consumption
    fn read_chunk_for_iterator<'a>(
        &'a self,
        reader_id: Uuid,
        n_to_read: usize,
        n_to_consume: usize,
    ) -> Result<ChunkGuard<'a, A, D, M>>
    where
        D::LargerSize: Into<StrideShape<D::Larger>> + Clone,
        D::CurrentSize: Clone;

    /// Get the current read pointer for a reader
    fn get_reader_ptr(&self, reader_id: Uuid) -> Option<usize>;

    /// Advance the read pointer for a reader
    fn advance_reader_ptr(&self, reader_id: Uuid, n_to_consume: usize);

    /// Get metadata
    fn get_metadata(&self) -> Option<M>;
}

pub trait SizedDimension {
    type LargerSize;
    type CurrentSize;
    fn get_larger_array_size(nel: usize, size: Self::CurrentSize) -> Self::LargerSize;
    fn from_array_view(view: ArrayView1<usize>) -> Self::CurrentSize;
}

//Boy I should macro-ify these, and think about support for dynamic arrays.
impl SizedDimension for Dim<[usize; 0]> {
    type CurrentSize = ();
    type LargerSize = usize;
    fn get_larger_array_size(nel: usize, _size: Self::CurrentSize) -> Self::LargerSize {
        nel
    }
    fn from_array_view(_view: ArrayView1<usize>) -> Self::CurrentSize {}
}

impl SizedDimension for Dim<[usize; 1]> {
    type CurrentSize = usize;
    type LargerSize = (usize, usize);
    fn get_larger_array_size(nel: usize, size: Self::CurrentSize) -> Self::LargerSize {
        (nel, size)
    }
    fn from_array_view(view: ArrayView1<usize>) -> Self::CurrentSize {
        view[0]
    }
}
impl SizedDimension for Dim<[usize; 2]> {
    type CurrentSize = (usize, usize);
    type LargerSize = (usize, usize, usize);
    fn get_larger_array_size(nel: usize, size: Self::CurrentSize) -> Self::LargerSize {
        (nel, size.1, size.0)
    }
    fn from_array_view(view: ArrayView1<usize>) -> Self::CurrentSize {
        (view[1], view[0])
    }
}
impl SizedDimension for Dim<[usize; 3]> {
    type CurrentSize = (usize, usize, usize);
    type LargerSize = (usize, usize, usize, usize);
    fn get_larger_array_size(nel: usize, size: Self::CurrentSize) -> Self::LargerSize {
        (nel, size.2, size.1, size.0)
    }
    fn from_array_view(view: ArrayView1<usize>) -> Self::CurrentSize {
        (view[2], view[1], view[0])
    }
}
impl SizedDimension for Dim<[usize; 4]> {
    type CurrentSize = (usize, usize, usize, usize);
    type LargerSize = (usize, usize, usize, usize, usize);
    fn get_larger_array_size(nel: usize, size: Self::CurrentSize) -> Self::LargerSize {
        (nel, size.3, size.2, size.1, size.0)
    }
    fn from_array_view(view: ArrayView1<usize>) -> Self::CurrentSize {
        (view[3], view[2], view[1], view[0])
    }
}
impl SizedDimension for Dim<[usize; 5]> {
    type CurrentSize = (usize, usize, usize, usize, usize);
    type LargerSize = (usize, usize, usize, usize, usize, usize);
    fn get_larger_array_size(nel: usize, size: Self::CurrentSize) -> Self::LargerSize {
        (nel, size.4, size.3, size.2, size.1, size.0)
    }
    fn from_array_view(view: ArrayView1<usize>) -> Self::CurrentSize {
        (view[4], view[3], view[2], view[1], view[0])
    }
}