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