wasmer_cache_near/
filesystem.rs1use crate::cache::Cache;
2use crate::hash::Hash;
3use std::fs::{create_dir_all, File};
4use std::io::{self, Write};
5use std::path::PathBuf;
6use wasmer::{DeserializeError, Module, SerializeError, Store};
7
8pub struct FileSystemCache {
34 path: PathBuf,
35 ext: Option<String>,
36}
37
38impl FileSystemCache {
39 pub fn new<P: Into<PathBuf>>(path: P) -> io::Result<Self> {
41 let path: PathBuf = path.into();
42 if path.exists() {
43 let metadata = path.metadata()?;
44 if metadata.is_dir() {
45 if !metadata.permissions().readonly() {
46 Ok(Self { path, ext: None })
47 } else {
48 Err(io::Error::new(
50 io::ErrorKind::PermissionDenied,
51 format!("the supplied path is readonly: {}", path.display()),
52 ))
53 }
54 } else {
55 Err(io::Error::new(
57 io::ErrorKind::PermissionDenied,
58 format!(
59 "the supplied path already points to a file: {}",
60 path.display()
61 ),
62 ))
63 }
64 } else {
65 create_dir_all(&path)?;
67 Ok(Self { path, ext: None })
68 }
69 }
70
71 pub fn set_cache_extension(&mut self, ext: Option<impl ToString>) {
76 self.ext = ext.map(|ext| ext.to_string());
77 }
78}
79
80impl Cache for FileSystemCache {
81 type DeserializeError = DeserializeError;
82 type SerializeError = SerializeError;
83
84 unsafe fn load(&self, store: &Store, key: Hash) -> Result<Module, Self::DeserializeError> {
85 let filename = if let Some(ref ext) = self.ext {
86 format!("{}.{}", key.to_string(), ext)
87 } else {
88 key.to_string()
89 };
90 let path = self.path.join(filename);
91 Module::deserialize_from_file(&store, path)
92 }
93
94 fn store(&mut self, key: Hash, module: &Module) -> Result<(), Self::SerializeError> {
95 let filename = if let Some(ref ext) = self.ext {
96 format!("{}.{}", key.to_string(), ext)
97 } else {
98 key.to_string()
99 };
100 let path = self.path.join(filename);
101 let mut file = File::create(path)?;
102
103 let buffer = module.serialize()?;
104 file.write_all(&buffer)?;
105
106 Ok(())
107 }
108}