opendal/raw/adapters/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::ops::DerefMut;
21
22use futures::Future;
23
24use crate::raw::*;
25use crate::Capability;
26use crate::Scheme;
27use crate::*;
28
29/// Scan is the async iterator returned by `Adapter::scan`.
30pub trait Scan: Send + Sync + Unpin {
31    /// Fetch the next key in the current key prefix
32    ///
33    /// `Ok(None)` means no further key will be returned
34    fn next(&mut self) -> impl Future<Output = Result<Option<String>>> + MaybeSend;
35}
36
37/// A noop implementation of Scan
38impl Scan for () {
39    async fn next(&mut self) -> Result<Option<String>> {
40        Ok(None)
41    }
42}
43
44/// A Scan implementation for all trivial non-async iterators
45pub struct ScanStdIter<I>(I);
46
47#[cfg(any(
48    feature = "services-cloudflare-kv",
49    feature = "services-etcd",
50    feature = "services-rocksdb",
51    feature = "services-sled"
52))]
53impl<I> ScanStdIter<I>
54where
55    I: Iterator<Item = Result<String>> + Unpin + Send + Sync,
56{
57    /// Create a new ScanStdIter from an Iterator
58    pub(crate) fn new(inner: I) -> Self {
59        Self(inner)
60    }
61}
62
63impl<I> Scan for ScanStdIter<I>
64where
65    I: Iterator<Item = Result<String>> + Unpin + Send + Sync,
66{
67    async fn next(&mut self) -> Result<Option<String>> {
68        self.0.next().transpose()
69    }
70}
71
72/// A type-erased wrapper of Scan
73pub type Scanner = Box<dyn ScanDyn>;
74
75pub trait ScanDyn: Unpin + Send + Sync {
76    fn next_dyn(&mut self) -> BoxedFuture<Result<Option<String>>>;
77}
78
79impl<T: Scan + ?Sized> ScanDyn for T {
80    fn next_dyn(&mut self) -> BoxedFuture<Result<Option<String>>> {
81        Box::pin(self.next())
82    }
83}
84
85impl<T: ScanDyn + ?Sized> Scan for Box<T> {
86    async fn next(&mut self) -> Result<Option<String>> {
87        self.deref_mut().next_dyn().await
88    }
89}
90
91/// KvAdapter is the adapter to underlying kv services.
92///
93/// By implement this trait, any kv service can work as an OpenDAL Service.
94pub trait Adapter: Send + Sync + Debug + Unpin + 'static {
95    /// TODO: use default associate type `= ()` after stabilized
96    type Scanner: Scan;
97
98    /// Return the info of this key value accessor.
99    fn info(&self) -> Info;
100
101    /// Get a key from service.
102    ///
103    /// - return `Ok(None)` if this key is not exist.
104    fn get(&self, path: &str) -> impl Future<Output = Result<Option<Buffer>>> + MaybeSend;
105
106    /// Set a key into service.
107    fn set(&self, path: &str, value: Buffer) -> impl Future<Output = Result<()>> + MaybeSend;
108
109    /// Delete a key from service.
110    ///
111    /// - return `Ok(())` even if this key is not exist.
112    fn delete(&self, path: &str) -> impl Future<Output = Result<()>> + MaybeSend;
113
114    /// Scan a key prefix to get all keys that start with this key.
115    fn scan(&self, path: &str) -> impl Future<Output = Result<Self::Scanner>> + MaybeSend {
116        let _ = path;
117
118        ready(Err(Error::new(
119            ErrorKind::Unsupported,
120            "kv adapter doesn't support this operation",
121        )
122        .with_operation("kv::Adapter::scan")))
123    }
124
125    /// Append a key into service
126    fn append(&self, path: &str, value: &[u8]) -> impl Future<Output = Result<()>> + MaybeSend {
127        let _ = path;
128        let _ = value;
129
130        ready(Err(Error::new(
131            ErrorKind::Unsupported,
132            "kv adapter doesn't support this operation",
133        )
134        .with_operation("kv::Adapter::append")))
135    }
136}
137
138/// Info for this key value accessor.
139pub struct Info {
140    scheme: Scheme,
141    name: String,
142    capabilities: Capability,
143}
144
145impl Info {
146    /// Create a new KeyValueAccessorInfo.
147    pub fn new(scheme: Scheme, name: &str, capabilities: Capability) -> Self {
148        Self {
149            scheme,
150            name: name.to_string(),
151            capabilities,
152        }
153    }
154
155    /// Get the scheme.
156    pub fn scheme(&self) -> Scheme {
157        self.scheme
158    }
159
160    /// Get the name.
161    pub fn name(&self) -> &str {
162        &self.name
163    }
164
165    /// Get the capabilities.
166    pub fn capabilities(&self) -> Capability {
167        self.capabilities
168    }
169}