diff --git a/src/content/read.rs b/src/content/read.rs index 9b1209c..70fab12 100644 --- a/src/content/read.rs +++ b/src/content/read.rs @@ -1,11 +1,37 @@ -use std::fs; +use std::fs::{self, File}; use std::path::Path; -use ssri::Integrity; +use ssri::{Algorithm, Integrity, IntegrityChecker}; use crate::content::path; use crate::errors::Error; +pub struct Reader { + fd: File, + checker: IntegrityChecker, +} + +impl std::io::Read for Reader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let amt = self.fd.read(buf)?; + self.checker.input(&buf); + Ok(amt) + } +} + +impl Reader { + pub fn check(self) -> Result { + self.checker.result().ok_or(Error::IntegrityError) + } +} + +pub fn open<'a>(cache: &Path, sri: Integrity) -> Result { + Ok(Reader { + fd: File::open(cache)?, + checker: IntegrityChecker::new(sri), + }) +} + pub fn read(cache: &Path, sri: &Integrity) -> Result, Error> { let cpath = path::content_path(&cache, &sri); let ret = fs::read(&cpath)?; diff --git a/src/get.rs b/src/get.rs index 28e3afe..f392192 100644 --- a/src/get.rs +++ b/src/get.rs @@ -1,12 +1,50 @@ //! Functions for reading from cache. use std::path::Path; -use ssri::Integrity; +use ssri::{Algorithm, Integrity}; -use crate::content::read; +use crate::content::read::{self, Reader}; use crate::errors::Error; use crate::index::{self, Entry}; +pub struct Get { + reader: Reader, +} + +impl std::io::Read for Get { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.reader.read(buf) + } +} + +impl Get { + pub fn check(self) -> Result { + self.reader.check() + } +} + +pub fn open(cache: P, key: K) -> Result +where + P: AsRef, + K: AsRef, +{ + if let Some(entry) = index::find(cache.as_ref(), key.as_ref())? { + let reader = read::open(cache.as_ref(), entry.integrity)?; + Ok(Get { reader }) + } else { + Err(Error::NotFound) + } +} + +pub fn open_hash

(cache: P, sri: Integrity) -> Result +where + P: AsRef +{ + Ok(Get { + reader: read::open(cache.as_ref(), sri)?, + }) +} + pub fn read, K: AsRef>(cache: P, key: K) -> Result, Error> { if let Some(entry) = index::find(cache.as_ref(), key.as_ref())? { read_hash(cache, &entry.integrity)