opendal_service_surrealdb/
config.rs1use std::fmt::Debug;
19
20use serde::Deserialize;
21use serde::Serialize;
22
23use super::backend::SurrealdbBuilder;
24
25#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
27#[serde(default)]
28#[non_exhaustive]
29pub struct SurrealdbConfig {
30 pub connection_string: Option<String>,
32 pub username: Option<String>,
34 pub password: Option<String>,
36 pub namespace: Option<String>,
38 pub database: Option<String>,
40 pub table: Option<String>,
42 pub key_field: Option<String>,
44 pub value_field: Option<String>,
46 pub root: Option<String>,
48}
49
50impl Debug for SurrealdbConfig {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 f.debug_struct("SurrealdbConfig")
53 .field("username", &self.username)
54 .field("namespace", &self.namespace)
55 .field("database", &self.database)
56 .field("table", &self.table)
57 .field("key_field", &self.key_field)
58 .field("value_field", &self.value_field)
59 .field("root", &self.root)
60 .finish_non_exhaustive()
61 }
62}
63
64impl opendal_core::Configurator for SurrealdbConfig {
65 type Builder = SurrealdbBuilder;
66
67 fn from_uri(uri: &opendal_core::OperatorUri) -> opendal_core::Result<Self> {
68 let mut map = uri.options().clone();
69
70 if let Some(authority) = uri.authority() {
71 map.entry("connection_string".to_string())
72 .or_insert_with(|| format!("ws://{authority}"));
73 }
74
75 if let Some(path) = uri.root()
76 && !path.is_empty()
77 {
78 let mut segments = path.splitn(4, '/');
79 if let Some(namespace) = segments.next()
80 && !namespace.is_empty()
81 {
82 map.entry("namespace".to_string())
83 .or_insert_with(|| namespace.to_string());
84 }
85 if let Some(database) = segments.next()
86 && !database.is_empty()
87 {
88 map.entry("database".to_string())
89 .or_insert_with(|| database.to_string());
90 }
91 if let Some(table) = segments.next()
92 && !table.is_empty()
93 {
94 map.entry("table".to_string())
95 .or_insert_with(|| table.to_string());
96 }
97 if let Some(rest) = segments.next()
98 && !rest.is_empty()
99 {
100 map.insert("root".to_string(), rest.to_string());
101 }
102 }
103
104 Self::from_iter(map)
105 }
106
107 fn into_builder(self) -> Self::Builder {
108 SurrealdbBuilder { config: self }
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use opendal_core::Configurator;
116 use opendal_core::OperatorUri;
117
118 #[test]
119 fn from_uri_sets_connection_namespace_database_table_and_root() {
120 let uri = OperatorUri::new(
121 "surrealdb://db.example.com:8000/project/app/cache/static",
122 Vec::<(String, String)>::new(),
123 )
124 .unwrap();
125
126 let cfg = SurrealdbConfig::from_uri(&uri).unwrap();
127 assert_eq!(
128 cfg.connection_string.as_deref(),
129 Some("ws://db.example.com:8000")
130 );
131 assert_eq!(cfg.namespace.as_deref(), Some("project"));
132 assert_eq!(cfg.database.as_deref(), Some("app"));
133 assert_eq!(cfg.table.as_deref(), Some("cache"));
134 assert_eq!(cfg.root.as_deref(), Some("static"));
135 }
136}