noosphere_into/write/
memory.rs

1use std::{
2    collections::BTreeMap,
3    path::{Path, PathBuf},
4    sync::Arc,
5};
6
7use super::WriteTargetConditionalSend;
8use anyhow::Result;
9use async_trait::async_trait;
10use futures::Future;
11use tokio::io::AsyncRead;
12use tokio::io::AsyncReadExt;
13use tokio::sync::Mutex;
14
15use super::WriteTarget;
16
17/// An implementation of WriteTarget that is only intended to be used in tests.
18#[derive(Default, Clone)]
19pub struct MemoryWriteTarget {
20    vfs: Arc<Mutex<BTreeMap<PathBuf, Vec<u8>>>>,
21    aliases: Arc<Mutex<BTreeMap<PathBuf, PathBuf>>>,
22}
23
24impl MemoryWriteTarget {
25    pub async fn resolve_symlink(&self, path: &Path) -> Option<PathBuf> {
26        let aliases = self.aliases.lock().await;
27        aliases.get(path).cloned()
28    }
29
30    pub async fn read(&self, path: &Path) -> Option<Vec<u8>> {
31        let aliases = self.aliases.lock().await;
32
33        let path = if let Some(alias) = aliases.get(path) {
34            alias
35        } else {
36            path
37        };
38
39        self.vfs.lock().await.get(path).cloned()
40    }
41}
42
43#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
44#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
45impl WriteTarget for MemoryWriteTarget {
46    async fn exists(&self, path: &Path) -> Result<bool> {
47        Ok(self.vfs.lock().await.contains_key(path))
48    }
49
50    async fn write<R>(&self, path: &Path, mut contents: R) -> Result<()>
51    where
52        R: AsyncRead + Unpin + WriteTargetConditionalSend,
53    {
54        let mut buffer = Vec::new();
55        contents.read_to_end(&mut buffer).await?;
56        self.vfs.lock().await.insert(path.to_path_buf(), buffer);
57        Ok(())
58    }
59
60    async fn symlink(&self, src: &Path, dst: &Path) -> Result<()> {
61        let mut aliases = self.aliases.lock().await;
62        aliases.insert(dst.to_path_buf(), src.to_path_buf());
63        Ok(())
64    }
65
66    async fn spawn<F>(future: F) -> Result<()>
67    where
68        F: Future<Output = Result<()>> + WriteTargetConditionalSend + 'static,
69    {
70        future.await?;
71        Ok(())
72    }
73}