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 /// Set a value into adapter.
55 fn set(&self, path: &str, value: Value) -> impl Future<Output = Result<()>> + MaybeSend;
56
57 /// Delete a value from adapter.
58 fn delete(&self, path: &str) -> impl Future<Output = Result<()>> + MaybeSend;
59
60 /// Scan a key prefix to get all keys that start with this key.
61 fn scan(&self, path: &str) -> impl Future<Output = Result<Vec<String>>> + MaybeSend {
62 let _ = path;
63
64 ready(Err(Error::new(
65 ErrorKind::Unsupported,
66 "typed_kv adapter doesn't support this operation",
67 )
68 .with_operation("typed_kv::Adapter::scan")))
69 }
70}
71
72/// Value is the typed value stored in adapter.
73///
74/// It's cheap to clone so that users can read data without extra copy.
75#[derive(Debug, Clone)]
76pub struct Value {
77 /// Metadata of this value.
78 pub metadata: Metadata,
79 /// The corresponding content of this value.
80 pub value: Buffer,
81}
82
83impl Value {
84 /// Create a new dir of value.
85 pub fn new_dir() -> Self {
86 Self {
87 metadata: Metadata::new(EntryMode::DIR)
88 .with_content_length(0)
89 .with_last_modified(Utc::now()),
90 value: Buffer::new(),
91 }
92 }
93
94 /// Size returns the in-memory size of Value.
95 pub fn size(&self) -> usize {
96 size_of::<Metadata>() + self.value.len()
97 }
98}
99
100/// Capability is used to describe what operations are supported
101/// by Typed KV Operator.
102#[derive(Copy, Clone, Default)]
103pub struct Capability {
104 /// If typed_kv operator supports get natively.
105 pub get: bool,
106 /// If typed_kv operator supports set natively.
107 pub set: bool,
108 /// If typed_kv operator supports delete natively.
109 pub delete: bool,
110 /// If typed_kv operator supports scan natively.
111 pub scan: bool,
112 /// If typed_kv operator supports shared access.
113 pub shared: bool,
114}
115
116impl Debug for Capability {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 let mut s = vec![];
119
120 if self.get {
121 s.push("Get")
122 }
123 if self.set {
124 s.push("Set");
125 }
126 if self.delete {
127 s.push("Delete");
128 }
129 if self.scan {
130 s.push("Scan");
131 }
132 if self.shared {
133 s.push("Shared");
134 }
135
136 write!(f, "{{ {} }}", s.join(" | "))
137 }
138}
139
140/// Info for this key value accessor.
141pub struct Info {
142 scheme: Scheme,
143 name: String,
144 capabilities: Capability,
145}
146
147impl Info {
148 /// Create a new KeyValueAccessorInfo.
149 pub fn new(scheme: Scheme, name: &str, capabilities: Capability) -> Self {
150 Self {
151 scheme,
152 name: name.to_string(),
153 capabilities,
154 }
155 }
156
157 /// Get the scheme.
158 pub fn scheme(&self) -> Scheme {
159 self.scheme
160 }
161
162 /// Get the name.
163 pub fn name(&self) -> &str {
164 &self.name
165 }
166
167 /// Get the capabilities.
168 pub fn capabilities(&self) -> Capability {
169 self.capabilities
170 }
171}