use crate::error::Result;
pub trait AsyncDataset: Send + Sync + 'static {
type Item: Send + 'static;
fn get(&self, index: usize) -> impl Future<Output = Result<Self::Item>> + Send;
fn get_batch(&self, indices: &[usize]) -> impl Future<Output = Result<Vec<Self::Item>>> + Send {
async move {
let mut items = Vec::with_capacity(indices.len());
for &index in indices {
items.push(self.get(index).await?);
}
Ok(items)
}
}
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[cfg(test)]
mod tests {
use super::AsyncDataset;
use crate::error::Result;
struct Numbers(usize);
impl AsyncDataset for Numbers {
type Item = u64;
async fn get(&self, index: usize) -> Result<u64> {
tokio::task::yield_now().await;
if index < self.0 {
Ok(index as u64)
} else {
Err(format!("index {index} out of range").into())
}
}
fn len(&self) -> usize {
self.0
}
}
fn block_on<F: Future>(future: F) -> F::Output {
tokio::runtime::Builder::new_current_thread()
.build()
.unwrap()
.block_on(future)
}
#[test]
fn default_get_batch_awaits_get_in_order() {
assert_eq!(block_on(Numbers(4).get_batch(&[3, 0])).unwrap(), vec![3, 0]);
assert!(block_on(Numbers(4).get_batch(&[1, 7])).is_err());
}
}