#[cfg(feature = "python")]
use std::time::{Duration, Instant};
use crate::{
collator::Collator,
error::{Error, Result},
loader::source::LoaderSource,
transform::{Identity, Transform},
};
pub(super) fn forked() -> Error {
"this epoch was started before fork(); start a new one in this process (iter())".into()
}
pub trait BatchStream<B> {
fn next(&mut self) -> Option<Result<B>>;
fn len(&self) -> usize;
#[cfg(feature = "python")]
fn next_until(&mut self, deadline: Option<Instant>) -> Option<Option<Result<B>>>;
#[cfg(feature = "python")]
fn stop(&mut self, timeout: Duration) -> bool;
}
pub struct DataLoaderIter<Src, C, T = Identity>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
epoch: Src::Epoch<T, C, T::Output>,
}
impl<Src, C, T> DataLoaderIter<Src, C, T>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
pub(super) fn new(epoch: Src::Epoch<T, C, T::Output>) -> Self {
Self { epoch }
}
#[cfg(feature = "python")]
pub(crate) fn next_until(
&mut self,
deadline: Option<Instant>,
) -> Option<Option<Result<C::Batch>>> {
self.epoch.next_until(deadline)
}
#[cfg(feature = "python")]
pub(crate) fn stop(&mut self, timeout: Duration) -> bool {
self.epoch.stop(timeout)
}
}
impl<Src, C, T> Iterator for DataLoaderIter<Src, C, T>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
type Item = Result<C::Batch>;
fn next(&mut self) -> Option<Self::Item> {
self.epoch.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.epoch.len();
(n, Some(n))
}
}
impl<Src, C, T> ExactSizeIterator for DataLoaderIter<Src, C, T>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
}
pub struct IndexedIter<Src, C, T = Identity>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
indices: std::vec::IntoIter<Vec<usize>>,
batches: DataLoaderIter<Src, C, T>,
}
impl<Src, C, T> IndexedIter<Src, C, T>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
pub(super) fn new(indices: Vec<Vec<usize>>, batches: DataLoaderIter<Src, C, T>) -> Self {
Self {
indices: indices.into_iter(),
batches,
}
}
}
impl<Src, C, T> Iterator for IndexedIter<Src, C, T>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
type Item = Result<(Vec<usize>, C::Batch)>;
fn next(&mut self) -> Option<Self::Item> {
let batch = self.batches.next()?;
let indices = self.indices.next()?;
Some(batch.map(|batch| (indices, batch)))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.batches.size_hint()
}
}
impl<Src, C, T> ExactSizeIterator for IndexedIter<Src, C, T>
where
Src: LoaderSource,
T: Transform<Src::Item>,
C: Collator<T::Output>,
{
}