opendal_core/services/memory/
backend.rs1use std::fmt::Debug;
19use std::sync::Arc;
20
21use super::MEMORY_SCHEME;
22use super::config::MemoryConfig;
23use super::core::*;
24use super::deleter::MemoryDeleter;
25use super::lister::MemoryLister;
26use super::writer::MemoryWriter;
27use crate::raw::oio;
28use crate::raw::*;
29use crate::*;
30
31#[doc = include_str!("docs.md")]
33#[derive(Debug, Default)]
34pub struct MemoryBuilder {
35 pub(super) config: MemoryConfig,
36}
37
38impl MemoryBuilder {
39 pub fn root(mut self, path: &str) -> Self {
41 self.config.root = Some(path.into());
42 self
43 }
44}
45
46impl Builder for MemoryBuilder {
47 type Config = MemoryConfig;
48
49 fn build(self) -> Result<impl Access> {
50 let root = normalize_root(self.config.root.as_deref().unwrap_or("/"));
51
52 let core = MemoryCore::new();
53 Ok(MemoryBackend::new(core).with_normalized_root(root))
54 }
55}
56
57#[derive(Debug, Clone)]
59pub struct MemoryBackend {
60 core: Arc<MemoryCore>,
61 root: String,
62 info: Arc<AccessorInfo>,
63}
64
65impl MemoryBackend {
66 fn new(core: MemoryCore) -> Self {
67 let info = AccessorInfo::default();
68 info.set_scheme(MEMORY_SCHEME);
69 info.set_name(&format!("{:p}", Arc::as_ptr(&core.data)));
70 info.set_root("/");
71 info.set_native_capability(Capability {
72 read: true,
73 write: true,
74 write_can_empty: true,
75 write_with_cache_control: true,
76 write_with_content_type: true,
77 write_with_content_disposition: true,
78 write_with_content_encoding: true,
79 write_with_if_not_exists: true,
80 delete: true,
81 stat: true,
82 list: true,
83 list_with_recursive: true,
84 shared: false,
85 ..Default::default()
86 });
87
88 Self {
89 core: Arc::new(core),
90 root: "/".to_string(),
91 info: Arc::new(info),
92 }
93 }
94
95 fn with_normalized_root(mut self, root: String) -> Self {
96 self.info.set_root(&root);
97 self.root = root;
98 self
99 }
100}
101
102impl Access for MemoryBackend {
103 type Reader = Buffer;
104 type Writer = MemoryWriter;
105 type Lister = oio::HierarchyLister<MemoryLister>;
106 type Deleter = oio::OneShotDeleter<MemoryDeleter>;
107 type Copier = ();
108
109 fn info(&self) -> Arc<AccessorInfo> {
110 self.info.clone()
111 }
112
113 async fn stat(&self, path: &str, _: OpStat) -> Result<RpStat> {
114 let p = build_abs_path(&self.root, path);
115
116 if p == build_abs_path(&self.root, "") {
117 Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
118 } else {
119 match self.core.get(&p)? {
120 Some(value) => Ok(RpStat::new(value.metadata)),
121 None => Err(Error::new(
122 ErrorKind::NotFound,
123 "memory doesn't have this path",
124 )),
125 }
126 }
127 }
128
129 async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
130 let p = build_abs_path(&self.root, path);
131
132 let value = match self.core.get(&p)? {
133 Some(value) => value,
134 None => {
135 return Err(Error::new(
136 ErrorKind::NotFound,
137 "memory doesn't have this path",
138 ));
139 }
140 };
141
142 let total_size = value.content.len() as u64;
143 let range = args.range();
144 let start = range.offset().min(total_size) as usize;
145 let end = match range.size() {
146 Some(size) => range.offset().saturating_add(size).min(total_size),
147 None => total_size,
148 } as usize;
149 let content = value.content.slice(start..end);
150 let metadata = Metadata::new(EntryMode::FILE).with_content_length(total_size);
151
152 Ok((RpRead::new(metadata), content))
153 }
154
155 async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::Writer)> {
156 let p = build_abs_path(&self.root, path);
157 Ok((
158 RpWrite::new(),
159 MemoryWriter::new(self.core.clone(), p, args),
160 ))
161 }
162
163 async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
164 Ok((
165 RpDelete::default(),
166 oio::OneShotDeleter::new(MemoryDeleter::new(self.core.clone(), self.root.clone())),
167 ))
168 }
169
170 async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> {
171 let p = build_abs_path(&self.root, path);
172 let keys = self.core.scan(&p)?;
173 let lister = MemoryLister::new(&self.root, keys);
174 let lister = oio::HierarchyLister::new(lister, path, args.recursive());
175
176 Ok((RpList::default(), lister))
177 }
178}