Skip to main content

vector_core/
files.rs

1//! Files an account keeps beside its database, on either target: the
2//! filesystem natively, OPFS on the web. Async because OPFS only answers
3//! through promises; natively the calls are the same std::fs ones as before.
4
5use std::path::{Path, PathBuf};
6
7pub async fn read(path: &Path) -> Result<Vec<u8>, String> {
8    #[cfg(target_arch = "wasm32")]
9    return crate::webfiles::read(path).await;
10    #[cfg(not(target_arch = "wasm32"))]
11    std::fs::read(path).map_err(|e| format!("Failed to read {}: {e}", path.display()))
12}
13
14/// Replace `path` whole: a reader never sees a partial file.
15pub async fn write(path: &Path, bytes: &[u8]) -> Result<(), String> {
16    #[cfg(target_arch = "wasm32")]
17    return crate::webfiles::write(path, bytes).await;
18    #[cfg(not(target_arch = "wasm32"))]
19    {
20        if let Some(dir) = path.parent() {
21            std::fs::create_dir_all(dir).map_err(|e| format!("Failed to create {}: {e}", dir.display()))?;
22        }
23        let name = path.file_name().map(|n| n.to_string_lossy().into_owned()).unwrap_or_default();
24        let tmp = path.with_file_name(format!("{name}.tmp"));
25        std::fs::write(&tmp, bytes).map_err(|e| format!("Failed to write {}: {e}", path.display()))?;
26        std::fs::rename(&tmp, path).map_err(|e| format!("Failed to commit {}: {e}", path.display()))
27    }
28}
29
30pub async fn rename(from: &Path, to: &Path) -> Result<(), String> {
31    #[cfg(target_arch = "wasm32")]
32    {
33        let bytes = crate::webfiles::read(from).await?;
34        crate::webfiles::write(to, &bytes).await?;
35        crate::webfiles::remove(from).await;
36        Ok(())
37    }
38    #[cfg(not(target_arch = "wasm32"))]
39    std::fs::rename(from, to).map_err(|e| format!("Failed to move {}: {e}", from.display()))
40}
41
42pub async fn remove(path: &Path) {
43    #[cfg(target_arch = "wasm32")]
44    crate::webfiles::remove(path).await;
45    #[cfg(not(target_arch = "wasm32"))]
46    let _ = std::fs::remove_file(path);
47}
48
49/// The files directly inside `dir`; empty when it doesn't exist.
50pub async fn list(dir: &Path) -> Vec<PathBuf> {
51    #[cfg(target_arch = "wasm32")]
52    return crate::webfiles::list(dir).await.into_iter().map(|n| dir.join(n)).collect();
53    #[cfg(not(target_arch = "wasm32"))]
54    std::fs::read_dir(dir)
55        .map(|entries| entries.flatten().map(|e| e.path()).filter(|p| p.is_file()).collect())
56        .unwrap_or_default()
57}