1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
//! traits related to collections of blobs
use crate::util::Hash;
use futures::{
future::{self, LocalBoxFuture},
FutureExt,
};
use iroh_io::AsyncSliceReader;
use std::fmt::Debug;
/// A custom collection parser that allows the user to define what a collection is.
///
/// A collection can be anything that contains an ordered sequence of blake3 hashes.
/// Some collections store links with a fixed size and therefore allow efficient
/// skipping. Others store links with a variable size and therefore only allow
/// sequential access.
///
/// This API tries to accomodate both use cases. For collections that do not allow
/// efficient random access, the [`LinkStream::skip`] method can be implemented by just repeatedly
/// calling `next`.
///
/// For collections that do allow efficient random access, the [`LinkStream::skip`] method can be
/// used to move some internal offset.
pub trait CollectionParser: Send + Debug + Clone + 'static {
/// Parse a collection with this parser
fn parse<'a, R: AsyncSliceReader + 'a>(
&'a self,
format: u64,
reader: R,
) -> LocalBoxFuture<'a, anyhow::Result<(Box<dyn LinkStream>, CollectionStats)>>;
}
/// A stream (async iterator) over the hashes of a collection.
///
/// Allows to get the next hash or skip a number of hashes. Does not
/// implement `Stream` because of the extra `skip` method.
pub trait LinkStream: Debug {
/// Get the next hash in the collection.
fn next(&mut self) -> LocalBoxFuture<'_, anyhow::Result<Option<Hash>>>;
/// Skip a number of hashes in the collection.
fn skip(&mut self, n: u64) -> LocalBoxFuture<'_, anyhow::Result<()>>;
}
/// Information about a collection.
#[derive(Debug, Clone, Copy, Default)]
pub struct CollectionStats {
/// The number of blobs in the collection. `None` for unknown.
pub num_blobs: Option<u64>,
/// The total size of all blobs in the collection. `None` for unknown.
pub total_blob_size: Option<u64>,
}
/// A collection parser that just disables collections entirely.
#[derive(Debug, Clone)]
pub struct NoCollectionParser;
/// A CustomCollection for NoCollectionParser.
///
/// This is useful for when you don't want to support collections at all.
impl CollectionParser for NoCollectionParser {
fn parse<'a, R: AsyncSliceReader + 'a>(
&'a self,
_format: u64,
_reader: R,
) -> LocalBoxFuture<'a, anyhow::Result<(Box<dyn LinkStream>, CollectionStats)>> {
future::err(anyhow::anyhow!("collections not supported")).boxed_local()
}
}