opendal/raw/adapters/typed_kv/api.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::fmt::Debug;
19use std::future::ready;
20use std::future::Future;
21use std::mem::size_of;
22
23use chrono::Utc;
24
25use crate::raw::MaybeSend;
26use crate::Buffer;
27use crate::EntryMode;
28use crate::Error;
29use crate::ErrorKind;
30use crate::Metadata;
31use crate::Result;
32use crate::Scheme;
33
34/// Adapter is the typed adapter to underlying kv services.
35///
36/// By implement this trait, any kv service can work as an OpenDAL Service.
37///
38/// # Notes
39///
40/// `typed_kv::Adapter` is the typed version of `kv::Adapter`. It's more
41/// efficient if the underlying kv service can store data with its type. For
42/// example, we can store `Bytes` along with its metadata so that we don't
43/// need to serialize/deserialize it when we get it from the service.
44///
45/// Ideally, we should use `typed_kv::Adapter` instead of `kv::Adapter` for
46/// in-memory rust libs like moka and dashmap.
47pub trait Adapter: Send + Sync + Debug + Unpin + 'static {
48 /// Return the info of this key value accessor.
49 fn info(&self) -> Info;
50
51 /// Get a value from adapter.
52 fn get(&self, path: &str) -> impl Future<Output = Result<Option<Value>>> + MaybeSend;
53
54 /// Get a value from adapter.
55 fn blocking_get(&self, path: &str) -> Result<Option<Value>>;
56
57 /// Set a value into adapter.
58 fn set(&self, path: &str, value: Value) -> impl Future<Output = Result<()>> + MaybeSend;
59
60 /// Set a value into adapter.
61 fn blocking_set(&self, path: &str, value: Value) -> Result<()>;
62
63 /// Delete a value from adapter.
64 fn delete(&self, path: &str) -> impl Future<Output = Result<()>> + MaybeSend;
65
66 /// Delete a value from adapter.
67 fn blocking_delete(&self, path: &str) -> Result<()>;
68
69 /// Scan a key prefix to get all keys that start with this key.
70 fn scan(&self, path: &str) -> impl Future<Output = Result<Vec<String>>> + MaybeSend {
71 let _ = path;
72
73 ready(Err(Error::new(
74 ErrorKind::Unsupported,
75 "typed_kv adapter doesn't support this operation",
76 )
77 .with_operation("typed_kv::Adapter::scan")))
78 }
79
80 /// Scan a key prefix to get all keys that start with this key
81 /// in blocking way.
82 fn blocking_scan(&self, path: &str) -> Result<Vec<String>> {
83 let _ = path;
84
85 Err(Error::new(
86 ErrorKind::Unsupported,
87 "typed_kv adapter doesn't support this operation",
88 )
89 .with_operation("typed_kv::Adapter::blocking_scan"))
90 }
91}
92
93/// Value is the typed value stored in adapter.
94///
95/// It's cheap to clone so that users can read data without extra copy.
96#[derive(Debug, Clone)]
97pub struct Value {
98 /// Metadata of this value.
99 pub metadata: Metadata,
100 /// The corresponding content of this value.
101 pub value: Buffer,
102}
103
104impl Value {
105 /// Create a new dir of value.
106 pub fn new_dir() -> Self {
107 Self {
108 metadata: Metadata::new(EntryMode::DIR)
109 .with_content_length(0)
110 .with_last_modified(Utc::now()),
111 value: Buffer::new(),
112 }
113 }
114
115 /// Size returns the in-memory size of Value.
116 pub fn size(&self) -> usize {
117 size_of::<Metadata>() + self.value.len()
118 }
119}
120
121/// Capability is used to describe what operations are supported
122/// by Typed KV Operator.
123#[derive(Copy, Clone, Default)]
124pub struct Capability {
125 /// If typed_kv operator supports get natively.
126 pub get: bool,
127 /// If typed_kv operator supports set natively.
128 pub set: bool,
129 /// If typed_kv operator supports delete natively.
130 pub delete: bool,
131 /// If typed_kv operator supports scan natively.
132 pub scan: bool,
133 /// If typed_kv operator supports shared access.
134 pub shared: bool,
135}
136
137impl Debug for Capability {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 let mut s = vec![];
140
141 if self.get {
142 s.push("Get")
143 }
144 if self.set {
145 s.push("Set");
146 }
147 if self.delete {
148 s.push("Delete");
149 }
150 if self.scan {
151 s.push("Scan");
152 }
153 if self.shared {
154 s.push("Shared");
155 }
156
157 write!(f, "{{ {} }}", s.join(" | "))
158 }
159}
160
161/// Info for this key value accessor.
162pub struct Info {
163 scheme: Scheme,
164 name: String,
165 capabilities: Capability,
166}
167
168impl Info {
169 /// Create a new KeyValueAccessorInfo.
170 pub fn new(scheme: Scheme, name: &str, capabilities: Capability) -> Self {
171 Self {
172 scheme,
173 name: name.to_string(),
174 capabilities,
175 }
176 }
177
178 /// Get the scheme.
179 pub fn scheme(&self) -> Scheme {
180 self.scheme
181 }
182
183 /// Get the name.
184 pub fn name(&self) -> &str {
185 &self.name
186 }
187
188 /// Get the capabilities.
189 pub fn capabilities(&self) -> Capability {
190 self.capabilities
191 }
192}