feat: allow to read key without checking integrity

This commit is contained in:
Jakub Koralewski 2025-11-20 17:13:09 +00:00
parent 82e29a541c
commit 89457c054a
5 changed files with 81 additions and 17 deletions

View File

@ -118,8 +118,7 @@ pub fn read(cache: &Path, sri: &Integrity) -> Result<Vec<u8>> {
} }
#[cfg(any(feature = "async-std", feature = "tokio"))] #[cfg(any(feature = "async-std", feature = "tokio"))]
pub async fn read_async<'c, 's>(cache: &'c Path, sri: Integrity) -> Result<Vec<u8>> { pub async fn read_async<'c, 's>(cache: &'c Path, sri: Integrity, verify_integrity: bool) -> Result<Vec<u8>> {
// let cache = cache.to_path_buf();
let cpath = path::content_path(&cache, &sri); let cpath = path::content_path(&cache, &sri);
let ret = crate::async_lib::read(&cpath).await.with_context(|| { let ret = crate::async_lib::read(&cpath).await.with_context(|| {
format!( format!(
@ -127,14 +126,20 @@ pub async fn read_async<'c, 's>(cache: &'c Path, sri: Integrity) -> Result<Vec<u
path::content_path(&cache, &sri).display() path::content_path(&cache, &sri).display()
) )
})?; })?;
let integrity_check = move || { let ret = if verify_integrity {
sri.check(&ret)?; let integrity_check = move || {
Ok::<_, ssri::Error>(ret) sri.check(&ret)?;
Ok::<_, ssri::Error>(ret)
};
#[cfg(feature = "tokio")]
let ret = tokio::task::spawn_blocking(integrity_check).await??;
#[cfg(feature = "async-std")]
let ret = async_std::task::spawn_blocking(integrity_check).await?;
ret
} else {
ret
}; };
#[cfg(feature = "tokio")]
let ret = tokio::task::spawn_blocking(integrity_check).await??;
#[cfg(feature = "async-std")]
let ret = async_std::task::spawn_blocking(integrity_check).await?;
Ok(ret) Ok(ret)
} }

View File

@ -167,6 +167,39 @@ where
inner(cache.as_ref(), key.as_ref()).await inner(cache.as_ref(), key.as_ref()).await
} }
/// Reads the entire contents of a cache file into a bytes vector, looking the
/// data up by key. Skips integrity checking. Use this for loading large files.
///
/// ## Example
/// ```no_run
/// use async_std::prelude::*;
/// use async_attributes;
///
/// #[async_attributes::main]
/// async fn main() -> cacache::Result<()> {
/// let data: Vec<u8> = cacache::read_no_integrity("./my-cache", "my-key").await?;
/// Ok(())
/// }
/// ```
///
/// If you have no integrity this function is for you.
#[doc(hidden)]
#[cfg(any(feature = "async-std", feature = "tokio"))]
pub async fn read_no_integrity<P, K>(cache: P, key: K) -> Result<Vec<u8>>
where
P: AsRef<Path>,
K: AsRef<str>,
{
async fn inner(cache: &Path, key: &str) -> Result<Vec<u8>> {
if let Some(entry) = index::find_async(cache, key).await? {
read_hash_no_integrity(cache, entry.integrity).await
} else {
Err(Error::EntryNotFound(cache.to_path_buf(), key.into()))
}
}
inner(cache.as_ref(), key.as_ref()).await
}
/// Reads the entire contents of a cache file into a bytes vector, looking the /// Reads the entire contents of a cache file into a bytes vector, looking the
/// data up by its content address. /// data up by its content address.
/// ///
@ -178,7 +211,7 @@ where
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> cacache::Result<()> { /// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?;
/// let data: Vec<u8> = cacache::read_hash("./my-cache", &sri).await?; /// let data: Vec<u8> = cacache::read_hash("./my-cache", sri).await?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
@ -187,7 +220,33 @@ pub async fn read_hash<P>(cache: P, sri: Integrity) -> Result<Vec<u8>>
where where
P: AsRef<Path>, P: AsRef<Path>,
{ {
read::read_async(cache.as_ref(), sri).await read::read_async(cache.as_ref(), sri, true).await
}
/// Reads the entire contents of a cache file into a bytes vector, looking the
/// data up by its content address. Skips integrity checking. Use this for large files.
///
/// ## Example
/// ```no_run
/// use async_std::prelude::*;
/// use async_attributes;
///
/// #[async_attributes::main]
/// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "my-key", b"hello").await?;
/// let data: Vec<u8> = cacache::read_hash_no_integrity("./my-cache", sri).await?;
/// Ok(())
/// }
/// ```
///
/// If you have no integrity this function is for you.
#[doc(hidden)]
#[cfg(any(feature = "async-std", feature = "tokio"))]
pub async fn read_hash_no_integrity<P>(cache: P, sri: Integrity) -> Result<Vec<u8>>
where
P: AsRef<Path>,
{
read::read_async(cache.as_ref(), sri, false).await
} }
/// Copies cache data to a specified location. Returns the number of bytes /// Copies cache data to a specified location. Returns the number of bytes
@ -995,7 +1054,7 @@ mod tests {
let dir = tmp.path().to_owned(); let dir = tmp.path().to_owned();
let sri = crate::write(&dir, "my-key", b"hello world").await.unwrap(); let sri = crate::write(&dir, "my-key", b"hello world").await.unwrap();
let data = crate::read_hash(&dir, &sri).await.unwrap(); let data = crate::read_hash(&dir, sri).await.unwrap();
assert_eq!(data, b"hello world"); assert_eq!(data, b"hello world");
} }

View File

@ -66,7 +66,7 @@
//! let sri = cacache::write("./my-cache", "key", b"hello").await?; //! let sri = cacache::write("./my-cache", "key", b"hello").await?;
//! //!
//! // ...data gets looked up by `sri` ("Subresource Integrity"). //! // ...data gets looked up by `sri` ("Subresource Integrity").
//! let data = cacache::read_hash("./my-cache", &sri).await?; //! let data = cacache::read_hash("./my-cache", sri).await?;
//! assert_eq!(data, b"hello"); //! assert_eq!(data, b"hello");
//! //!
//! Ok(()) //! Ok(())

View File

@ -652,7 +652,7 @@ mod tests {
let integrity = crate::write_hash(&dir, &original) let integrity = crate::write_hash(&dir, &original)
.await .await
.expect("should be able to write a hash asynchronously"); .expect("should be able to write a hash asynchronously");
let bytes = crate::read_hash(&dir, &integrity) let bytes = crate::read_hash(&dir, integrity)
.await .await
.expect("should be able to read back what we wrote"); .expect("should be able to read back what we wrote");
let result = let result =

View File

@ -26,7 +26,7 @@ use crate::index;
/// cacache::read("./my-cache", "my-key").await?; /// cacache::read("./my-cache", "my-key").await?;
/// ///
/// // But this succeeds: /// // But this succeeds:
/// cacache::read_hash("./my-cache", &sri).await?; /// cacache::read_hash("./my-cache", sri).await?;
/// ///
/// Ok(()) /// Ok(())
/// } /// }
@ -56,7 +56,7 @@ where
/// ///
/// // These fail: /// // These fail:
/// cacache::read("./my-cache", "my-key").await?; /// cacache::read("./my-cache", "my-key").await?;
/// cacache::read_hash("./my-cache", &sri).await?; /// cacache::read_hash("./my-cache", sri).await?;
/// ///
/// // But this succeeds: /// // But this succeeds:
/// cacache::metadata("./my-cache", "my-key").await?; /// cacache::metadata("./my-cache", "my-key").await?;
@ -86,7 +86,7 @@ pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()
/// // These all fail: /// // These all fail:
/// cacache::read("./my-cache", "my-key").await?; /// cacache::read("./my-cache", "my-key").await?;
/// cacache::metadata("./my-cache", "my-key").await?; /// cacache::metadata("./my-cache", "my-key").await?;
/// cacache::read_hash("./my-cache", &sri).await?; /// cacache::read_hash("./my-cache", sri).await?;
/// ///
/// Ok(()) /// Ok(())
/// } /// }