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 Service> {
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: ServiceInfo,
63 capability: Capability,
64}
65
66impl MemoryBackend {
67 fn new(core: MemoryCore) -> Self {
68 let capability = Capability {
69 read: true,
70 read_with_suffix: true,
71 write: true,
72 write_can_empty: true,
73 write_with_cache_control: true,
74 write_with_content_type: true,
75 write_with_content_disposition: true,
76 write_with_content_encoding: true,
77 write_with_if_not_exists: true,
78 delete: true,
79 stat: true,
80 list: true,
81 list_with_recursive: true,
82 shared: false,
83 ..Default::default()
84 };
85
86 Self {
87 info: ServiceInfo::new(MEMORY_SCHEME, "/", format!("{:p}", Arc::as_ptr(&core.data))),
88 core: Arc::new(core),
89 root: "/".to_string(),
90 capability,
91 }
92 }
93
94 fn with_normalized_root(mut self, root: String) -> Self {
95 self.info = ServiceInfo::new(MEMORY_SCHEME, root.clone(), self.info.name());
96 self.root = root;
97 self
98 }
99}
100
101impl Service for MemoryBackend {
102 type Reader = oio::StreamReader<MemoryReader>;
103 type Writer = MemoryWriter;
104 type Lister = oio::HierarchyLister<MemoryLister>;
105 type Deleter = oio::OneShotDeleter<MemoryDeleter>;
106 type Copier = ();
107
108 fn info(&self) -> ServiceInfo {
109 self.info.clone()
110 }
111
112 fn capability(&self) -> Capability {
113 self.capability
114 }
115
116 async fn create_dir(
117 &self,
118 _: &OperationContext,
119 _: &str,
120 _: OpCreateDir,
121 ) -> Result<RpCreateDir> {
122 Err(Error::new(
123 ErrorKind::Unsupported,
124 "operation is not supported",
125 ))
126 }
127
128 async fn stat(&self, _: &OperationContext, path: &str, _: OpStat) -> Result<RpStat> {
129 let p = build_abs_path(&self.root, path);
130
131 if p == build_abs_path(&self.root, "") {
132 Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
133 } else {
134 match self.core.get(&p)? {
135 Some(value) => Ok(RpStat::new(value.metadata)),
136 None => Err(Error::new(
137 ErrorKind::NotFound,
138 "memory doesn't have this path",
139 )),
140 }
141 }
142 }
143
144 fn read(&self, _ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
145 Ok(oio::StreamReader::new(MemoryReader::new(
146 self.clone(),
147 path,
148 args,
149 )))
150 }
151
152 fn write(&self, _ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
153 let p = build_abs_path(&self.root, path);
154 Ok(MemoryWriter::new(self.core.clone(), p, args))
155 }
156
157 fn delete(&self, _ctx: &OperationContext) -> Result<Self::Deleter> {
158 Ok(oio::OneShotDeleter::new(MemoryDeleter::new(
159 self.core.clone(),
160 self.root.clone(),
161 )))
162 }
163
164 fn list(&self, _ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
165 let p = build_abs_path(&self.root, path);
166 let keys = self.core.scan(&p)?;
167 let lister = MemoryLister::new(&self.root, keys);
168 let lister = oio::HierarchyLister::new(lister, path, args.recursive());
169
170 Ok(lister)
171 }
172
173 fn copy(
174 &self,
175 _: &OperationContext,
176 _: &str,
177 _: &str,
178 _: OpCopy,
179 _: OpCopier,
180 ) -> Result<Self::Copier> {
181 Err(Error::new(
182 ErrorKind::Unsupported,
183 "operation is not supported",
184 ))
185 }
186
187 async fn rename(
188 &self,
189 _: &OperationContext,
190 _: &str,
191 _: &str,
192 _: OpRename,
193 ) -> Result<RpRename> {
194 Err(Error::new(
195 ErrorKind::Unsupported,
196 "operation is not supported",
197 ))
198 }
199
200 async fn presign(&self, _: &OperationContext, _: &str, _: OpPresign) -> Result<RpPresign> {
201 Err(Error::new(
202 ErrorKind::Unsupported,
203 "operation is not supported",
204 ))
205 }
206}
207
208pub struct MemoryReader {
210 backend: MemoryBackend,
211 path: String,
212}
213
214impl MemoryReader {
215 fn new(backend: MemoryBackend, path: &str, _: OpRead) -> Self {
216 Self {
217 backend,
218 path: path.to_string(),
219 }
220 }
221}
222
223impl oio::StreamRead for MemoryReader {
224 async fn open(&self, range: BytesRange) -> Result<(RpRead, Box<dyn oio::ReadStreamDyn>)> {
225 let backend = &self.backend;
226 let path = self.path.as_str();
227 let p = build_abs_path(&backend.root, path);
228
229 let value = match backend.core.get(&p)? {
230 Some(value) => value,
231 None => {
232 return Err(Error::new(
233 ErrorKind::NotFound,
234 "memory doesn't have this path",
235 ));
236 }
237 };
238
239 let total_size = value.content.len() as u64;
240 let content = value
241 .content
242 .slice(range.to_content_range(value.content.len())?);
243 let metadata = Metadata::new(EntryMode::FILE).with_content_length(total_size);
244 Ok((
245 RpRead::new(metadata),
246 Box::new(content) as Box<dyn oio::ReadStreamDyn>,
247 ))
248 }
249}