From f9d7d56195a487331cd1ae6ad76f2ea3ac0ac8f6 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 21 Feb 2019 14:00:33 -0800 Subject: [PATCH] Add documentation and make load safe --- lib/runtime-core/src/cache.rs | 23 ++++++++++++++++++- lib/runtime/src/cache.rs | 42 ++++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/lib/runtime-core/src/cache.rs b/lib/runtime-core/src/cache.rs index 34c09c3aa..2e9b29250 100644 --- a/lib/runtime-core/src/cache.rs +++ b/lib/runtime-core/src/cache.rs @@ -29,16 +29,34 @@ pub enum Error { InvalidatedCache, } +impl From for Error { + fn from(io_err: io::Error) -> Self { + Error::IoError(io_err) + } +} + +/// The hash of a wasm module. +/// +/// Used as a key when loading and storing modules in a [`Cache`]. +/// +/// [`Cache`]: trait.Cache.html #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct WasmHash([u8; 32]); impl WasmHash { + /// Hash a wasm module. + /// + /// # Note: + /// This does no verification that the supplied data + /// is, in fact, a wasm module. pub fn generate(wasm: &[u8]) -> Self { let mut array = [0u8; 32]; array.copy_from_slice(Sha256::digest(wasm).as_slice()); WasmHash(array) } + /// Create the hexadecimal representation of the + /// stored hash. pub fn encode(self) -> String { hex::encode(self.0) } @@ -183,10 +201,13 @@ impl SerializedCache { } } +/// A generic cache for storing and loading compiled wasm modules. +/// +/// The `wasmer-runtime` supplies a naive `FileSystemCache` api. pub trait Cache { type LoadError; type StoreError; - unsafe fn load(&self, key: WasmHash) -> Result; + fn load(&self, key: WasmHash) -> Result; fn store(&mut self, module: Module) -> Result; } diff --git a/lib/runtime/src/cache.rs b/lib/runtime/src/cache.rs index 2fbf7f47b..e6664d046 100644 --- a/lib/runtime/src/cache.rs +++ b/lib/runtime/src/cache.rs @@ -91,12 +91,42 @@ use wasmer_runtime_core::cache::{Error as CacheError, SerializedCache}; // } // } -pub struct FSCache { +/// Representation of a directory that contains compiled wasm artifacts. +/// +/// The `FileSystemCache` type implements the [`Cache`] trait, which allows it to be used +/// generically when some sort of cache is required. +/// +/// [`Cache`]: trait.Cache.html +/// +/// # Usage: +/// +/// ```rust +/// use wasmer_runtime::cache::{Cache, FileSystemCache}; +/// +/// # use wasmer_runtime::{Module, error::CacheError}; +/// fn store_and_load_module(module: Module) -> Result { +/// // Create a new file system cache. +/// // This is unsafe because we can't ensure that the artifact wasn't +/// // corrupted or tampered with. +/// let mut fs_cache = unsafe { FileSystemCache::new("some/directory/goes/here")? }; +/// // Store a module into the cache. +/// // The returned `key` is equivalent to `module.info().wasm_hash`. +/// let key = fs_cache.store(module)?; +/// // Load the module back from the cache with the `key`. +/// fs_cache.load(key) +/// } +/// ``` +pub struct FileSystemCache { path: PathBuf, } -impl FSCache { - pub fn open>(path: P) -> io::Result { +impl FileSystemCache { + /// Construct a new `FileSystemCache` around the specified directory. + /// + /// # Note: + /// This method is unsafe because there's no way to ensure the artifacts + /// stored in this cache haven't been corrupted or tampered with. + pub unsafe fn new>(path: P) -> io::Result { let path: PathBuf = path.into(); if path.exists() { @@ -129,17 +159,17 @@ impl FSCache { } } -impl Cache for FSCache { +impl Cache for FileSystemCache { type LoadError = CacheError; type StoreError = CacheError; - unsafe fn load(&self, key: WasmHash) -> Result { + fn load(&self, key: WasmHash) -> Result { let filename = key.encode(); let mut new_path_buf = self.path.clone(); new_path_buf.push(filename); let serialized_cache = SerializedCache::open(new_path_buf)?; - wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) + unsafe { wasmer_runtime_core::load_cache_with(serialized_cache, super::default_compiler()) } } fn store(&mut self, module: Module) -> Result {