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