opendal/services/dashmap/
backend.rs1use std::fmt::Debug;
19use std::fmt::Formatter;
20
21use dashmap::DashMap;
22
23use crate::raw::adapters::typed_kv;
24use crate::raw::Access;
25use crate::services::DashmapConfig;
26use crate::*;
27
28impl Configurator for DashmapConfig {
29 type Builder = DashmapBuilder;
30 fn into_builder(self) -> Self::Builder {
31 DashmapBuilder { config: self }
32 }
33}
34
35#[doc = include_str!("docs.md")]
37#[derive(Default)]
38pub struct DashmapBuilder {
39 config: DashmapConfig,
40}
41
42impl DashmapBuilder {
43 pub fn root(mut self, path: &str) -> Self {
45 self.config.root = if path.is_empty() {
46 None
47 } else {
48 Some(path.to_string())
49 };
50
51 self
52 }
53}
54
55impl Builder for DashmapBuilder {
56 const SCHEME: Scheme = Scheme::Dashmap;
57 type Config = DashmapConfig;
58
59 fn build(self) -> Result<impl Access> {
60 let mut backend = DashmapBackend::new(Adapter {
61 inner: DashMap::default(),
62 });
63 if let Some(v) = self.config.root {
64 backend = backend.with_root(&v);
65 }
66
67 Ok(backend)
68 }
69}
70
71pub type DashmapBackend = typed_kv::Backend<Adapter>;
73
74#[derive(Clone)]
75pub struct Adapter {
76 inner: DashMap<String, typed_kv::Value>,
77}
78
79impl Debug for Adapter {
80 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
81 f.debug_struct("DashmapAdapter")
82 .field("size", &self.inner.len())
83 .finish_non_exhaustive()
84 }
85}
86
87impl typed_kv::Adapter for Adapter {
88 fn info(&self) -> typed_kv::Info {
89 typed_kv::Info::new(
90 Scheme::Dashmap,
91 "dashmap",
92 typed_kv::Capability {
93 get: true,
94 set: true,
95 scan: true,
96 delete: true,
97 shared: false,
98 },
99 )
100 }
101
102 async fn get(&self, path: &str) -> Result<Option<typed_kv::Value>> {
103 match self.inner.get(path) {
104 None => Ok(None),
105 Some(bs) => Ok(Some(bs.value().to_owned())),
106 }
107 }
108
109 async fn set(&self, path: &str, value: typed_kv::Value) -> Result<()> {
110 self.inner.insert(path.to_string(), value);
111
112 Ok(())
113 }
114
115 async fn delete(&self, path: &str) -> Result<()> {
116 self.inner.remove(path);
117
118 Ok(())
119 }
120
121 async fn scan(&self, path: &str) -> Result<Vec<String>> {
122 let keys = self.inner.iter().map(|kv| kv.key().to_string());
123 if path.is_empty() {
124 Ok(keys.collect())
125 } else {
126 Ok(keys.filter(|k| k.starts_with(path)).collect())
127 }
128 }
129}