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
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
//! cacache is a Rust library for managing local key and content address
//! caches. It's really fast, really good at concurrency, and it will never
//! give you corrupted data, even if cache files get corrupted or manipulated.
//!
//! ## Examples
//!
//! Un-suffixed APIs are all async, using
//! [`async-std`](https://crates.io/crates/async-std). They let you put data
//! in and get it back out -- asynchronously!
//!
//! ```no_run
//! use async_attributes;
//!
//! #[async_attributes::main]
//! async fn main() -> Result<(), cacache::Error> {
//!   // Data goes in...
//!   cacache::put::data("./my-cache", "key", b"hello").await?;
//!
//!   // ...data comes out!
//!   let data = cacache::get::data("./my-cache", "key").await?;
//!   assert_eq!(data, b"hello");
//!
//!   Ok(())
//! }
//! ```
//!
//! ### Lookup by hash
//!
//! What makes `cacache` content addressable, though, is its ability to fetch
//! data by its "content address", which in our case is a ["subresource
//! integrity" hash](https://crates.io/crates/ssri), which `cacache::put`
//! conveniently returns for us. Fetching data by hash is significantly faster
//! than doing key lookups:
//!
//! ```no_run
//! use async_attributes;
//!
//! #[async_attributes::main]
//! async fn main() -> Result<(), cacache::Error> {
//!   // Data goes in...
//!   let sri = cacache::put::data("./my-cache", "key", b"hello").await?;
//!
//!   // ...data gets looked up by `sri` ("Subresource Integrity").
//!   let data = cacache::get::data_hash("./my-cache", &sri).await?;
//!   assert_eq!(data, b"hello");
//!
//!   Ok(())
//! }
//! ```
//!
//! ### Large file support
//!
//! `cacache` supports large file reads, in both async and sync mode, through
//! an API reminiscent of `std::fs::OpenOptions`:
//!
//! ```no_run
//! use async_attributes;
//! use async_std::prelude::*;
//!
//! #[async_attributes::main]
//! async fn main() -> Result<(), cacache::Error> {
//!   let mut fd = cacache::put::PutOpts::new().open("./my-cache", "key").await?;
//!   for _ in 0..10 {
//!     fd.write_all(b"very large data").await?;
//!   }
//!   // Data is only persisted to the cache after you do `fd.commit()`!
//!   let sri = fd.commit().await?;
//!   println!("integrity: {}", &sri);
//!
//!   let mut fd = cacache::get::open("./my-cache", "key").await?;
//!   let mut buf = String::new();
//!   fd.read_to_string(&mut buf).await?;
//!
//!   // Make sure to call `.check()` when you're done! It makes sure that what
//!   // you just read is actually valid. `cacache` always verifies the data
//!   // you get out is what it's supposed to be. The check is very cheap!
//!   fd.check()?;
//!
//!   Ok(())
//! }
//! ```
//!
//! ### Sync API
//!
//! There are also sync APIs available if you don't want to use async/await:
//!
//! ```no_run
//! fn main() -> Result<(), cacache::Error> {
//!   cacache::put::data_sync("./my-cache", "key", b"my-data").unwrap();
//!   let data = cacache::get::data_sync("./my-cache", "key").unwrap();
//!   assert_eq!(data, b"my-data");
//!   Ok(())
//! }
//! ```
#![warn(missing_docs, missing_doc_code_examples)]

pub use serde_json::Value;
pub use ssri::Algorithm;

mod content;
mod errors;
mod index;

pub mod get;
pub mod ls;
pub mod put;
pub mod rm;

pub use errors::Error;
pub use index::Entry;