-
Notifications
You must be signed in to change notification settings - Fork 14
feat: Read and seek #119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Read and seek #119
Changes from all commits
4bfa953
6925dd6
2d388a2
b2b0216
b2658b6
709b14e
5fc308e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,8 +29,11 @@ use n0_future::{future, stream, Stream, StreamExt}; | |
use quinn::SendStream; | ||
use range_collections::{range_set::RangeSetRange, RangeSet2}; | ||
use ref_cast::RefCast; | ||
use serde::{Deserialize, Serialize}; | ||
use tokio::io::AsyncWriteExt; | ||
use tracing::trace; | ||
mod reader; | ||
pub use reader::BlobReader; | ||
|
||
// Public reexports from the proto module. | ||
// | ||
|
@@ -102,6 +105,38 @@ impl Blobs { | |
}) | ||
} | ||
|
||
/// Create a reader for the given hash. The reader implements [`tokio::io::AsyncRead`] and [`tokio::io::AsyncSeek`] | ||
/// and therefore can be used to read the blob's content. | ||
/// | ||
/// Any access to parts of the blob that are not present will result in an error. | ||
/// | ||
/// Example: | ||
/// ```rust | ||
/// use iroh_blobs::{store::mem::MemStore, api::blobs::Blobs}; | ||
/// use tokio::io::AsyncReadExt; | ||
/// | ||
/// # async fn example() -> anyhow::Result<()> { | ||
/// let store = MemStore::new(); | ||
/// let tag = store.add_slice(b"Hello, world!").await?; | ||
/// let mut reader = store.reader(tag.hash); | ||
/// let mut buf = String::new(); | ||
/// reader.read_to_string(&mut buf).await?; | ||
/// assert_eq!(buf, "Hello, world!"); | ||
/// # Ok(()) | ||
/// } | ||
/// ``` | ||
pub fn reader(&self, hash: impl Into<Hash>) -> BlobReader { | ||
self.reader_with_opts(ReaderOptions { hash: hash.into() }) | ||
} | ||
|
||
/// Create a reader for the given options. The reader implements [`tokio::io::AsyncRead`] and [`tokio::io::AsyncSeek`] | ||
/// and therefore can be used to read the blob's content. | ||
/// | ||
/// Any access to parts of the blob that are not present will result in an error. | ||
pub fn reader_with_opts(&self, options: ReaderOptions) -> BlobReader { | ||
BlobReader::new(self.clone(), options) | ||
} | ||
|
||
/// Delete a blob. | ||
/// | ||
/// This function is not public, because it does not work as expected when called manually, | ||
|
@@ -647,6 +682,12 @@ impl<'a> AddProgress<'a> { | |
} | ||
} | ||
|
||
/// Options for an async reader for blobs that supports AsyncRead and AsyncSeek. | ||
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub struct ReaderOptions { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might think that this options object is a bit much, but who knows, maybe we want to add more options in the future. One option would be the "magic wait until download" option, e.g. you seek to somewhere where the blob isn't downloaded yet, it waits instead of failing. Or even, you seek to somewhere where the blob isn't downloaded yet, it triggers a download and waits instead of failing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe mark it as non_exhaustive in this case? |
||
pub hash: Hash, | ||
} | ||
|
||
/// An observe result. Awaiting this will return the current state. | ||
/// | ||
/// Calling [`ObserveProgress::stream`] will return a stream of updates, where | ||
|
@@ -856,7 +897,7 @@ impl ExportRangesProgress { | |
/// range of 0..100, you will get the entire first chunk, 0..1024. | ||
/// | ||
/// It is up to the caller to clip the ranges to the requested ranges. | ||
pub async fn stream(self) -> impl Stream<Item = ExportRangesItem> { | ||
pub fn stream(self) -> impl Stream<Item = ExportRangesItem> { | ||
Gen::new(|co| async move { | ||
let mut rx = match self.inner.await { | ||
Ok(rx) => rx, | ||
|
Uh oh!
There was an error while loading. Please reload this page.