opendal/services/cacache/
backend.rs1use std::fmt::Debug;
19use std::fmt::Formatter;
20use std::str;
21
22use cacache;
23
24use crate::raw::adapters::kv;
25use crate::raw::Access;
26use crate::services::CacacheConfig;
27use crate::Builder;
28use crate::Error;
29use crate::ErrorKind;
30use crate::Scheme;
31use crate::*;
32
33impl Configurator for CacacheConfig {
34 type Builder = CacacheBuilder;
35 fn into_builder(self) -> Self::Builder {
36 CacacheBuilder { config: self }
37 }
38}
39
40#[doc = include_str!("docs.md")]
42#[derive(Default)]
43pub struct CacacheBuilder {
44 config: CacacheConfig,
45}
46
47impl CacacheBuilder {
48 pub fn datadir(mut self, path: &str) -> Self {
50 self.config.datadir = Some(path.into());
51 self
52 }
53}
54
55impl Builder for CacacheBuilder {
56 const SCHEME: Scheme = Scheme::Cacache;
57 type Config = CacacheConfig;
58
59 fn build(self) -> Result<impl Access> {
60 let datadir_path = self.config.datadir.ok_or_else(|| {
61 Error::new(ErrorKind::ConfigInvalid, "datadir is required but not set")
62 .with_context("service", Scheme::Cacache)
63 })?;
64
65 Ok(CacacheBackend::new(Adapter {
66 datadir: datadir_path,
67 }))
68 }
69}
70
71pub type CacacheBackend = kv::Backend<Adapter>;
73
74#[derive(Clone)]
75pub struct Adapter {
76 datadir: String,
77}
78
79impl Debug for Adapter {
80 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
81 let mut ds = f.debug_struct("Adapter");
82 ds.field("path", &self.datadir);
83 ds.finish()
84 }
85}
86
87impl kv::Adapter for Adapter {
88 type Scanner = ();
89
90 fn info(&self) -> kv::Info {
91 kv::Info::new(
92 Scheme::Cacache,
93 &self.datadir,
94 Capability {
95 read: true,
96 write: true,
97 delete: true,
98 shared: false,
99 ..Default::default()
100 },
101 )
102 }
103
104 async fn get(&self, path: &str) -> Result<Option<Buffer>> {
105 let result = cacache::read(&self.datadir, path)
106 .await
107 .map_err(parse_error)?;
108 Ok(Some(Buffer::from(result)))
109 }
110
111 async fn set(&self, path: &str, value: Buffer) -> Result<()> {
112 cacache::write(&self.datadir, path, value.to_vec())
113 .await
114 .map_err(parse_error)?;
115 Ok(())
116 }
117
118 async fn delete(&self, path: &str) -> Result<()> {
119 cacache::remove(&self.datadir, path)
120 .await
121 .map_err(parse_error)?;
122
123 Ok(())
124 }
125}
126
127fn parse_error(err: cacache::Error) -> Error {
128 let kind = match err {
129 cacache::Error::EntryNotFound(_, _) => ErrorKind::NotFound,
130 _ => ErrorKind::Unexpected,
131 };
132
133 Error::new(kind, "error from cacache").set_source(err)
134}