surrealdb/api/opt/mod.rs
1//! The different options and types for use in API functions
2
3use std::borrow::Cow;
4
5use serde::Serialize;
6
7pub mod auth;
8pub mod capabilities;
9
10mod config;
11pub(crate) mod endpoint;
12mod export;
13pub(crate) mod query;
14mod resource;
15mod tls;
16
17pub use config::*;
18pub use endpoint::*;
19pub use export::*;
20pub use query::*;
21pub use resource::*;
22use serde_content::{Serializer, Value as Content};
23#[cfg(any(feature = "native-tls", feature = "rustls"))]
24pub use tls::*;
25
26type UnitOp<'a> = InnerOp<'a, ()>;
27
28#[derive(Debug, Serialize)]
29#[serde(tag = "op", rename_all = "lowercase")]
30enum InnerOp<'a, T> {
31 Add {
32 path: &'a str,
33 value: T,
34 },
35 Remove {
36 path: &'a str,
37 },
38 Replace {
39 path: &'a str,
40 value: T,
41 },
42 Change {
43 path: &'a str,
44 value: String,
45 },
46}
47
48/// A [JSON Patch] operation
49///
50/// From the official website:
51///
52/// > JSON Patch is a format for describing changes to a JSON document.
53/// > It can be used to avoid sending a whole document when only a part has
54/// > changed.
55///
56/// [JSON Patch]: https://jsonpatch.com/
57#[derive(Debug)]
58#[must_use]
59pub struct PatchOp(pub(crate) serde_content::Result<Content<'static>>);
60
61impl PatchOp {
62 /// Adds a value to an object or inserts it into an array.
63 ///
64 /// In the case of an array, the value is inserted before the given index.
65 /// The `-` character can be used instead of an index to insert at the end
66 /// of an array.
67 ///
68 /// # Examples
69 ///
70 /// ```
71 /// # use serde_json::json;
72 /// # use surrealdb::opt::PatchOp;
73 /// PatchOp::add("/biscuits/1", json!({ "name": "Ginger Nut" }))
74 /// # ;
75 /// ```
76 pub fn add<T>(path: &str, value: T) -> Self
77 where
78 T: Serialize,
79 {
80 Self(Serializer::new().serialize(InnerOp::Add {
81 path,
82 value,
83 }))
84 }
85
86 /// Removes a value from an object or array.
87 ///
88 /// # Examples
89 ///
90 /// ```
91 /// # use surrealdb::opt::PatchOp;
92 /// PatchOp::remove("/biscuits")
93 /// # ;
94 /// ```
95 ///
96 /// Remove the first element of the array at `biscuits`
97 /// (or just removes the “0” key if `biscuits` is an object)
98 ///
99 /// ```
100 /// # use surrealdb::opt::PatchOp;
101 /// PatchOp::remove("/biscuits/0")
102 /// # ;
103 /// ```
104 pub fn remove(path: &str) -> Self {
105 Self(Serializer::new().serialize(UnitOp::Remove {
106 path,
107 }))
108 }
109
110 /// Replaces a value.
111 ///
112 /// Equivalent to a “remove” followed by an “add”.
113 ///
114 /// # Examples
115 ///
116 /// ```
117 /// # use surrealdb::opt::PatchOp;
118 /// PatchOp::replace("/biscuits/0/name", "Chocolate Digestive")
119 /// # ;
120 /// ```
121 pub fn replace<T>(path: &str, value: T) -> Self
122 where
123 T: Serialize,
124 {
125 Self(Serializer::new().serialize(InnerOp::Replace {
126 path,
127 value,
128 }))
129 }
130
131 /// Changes a value
132 pub fn change(path: &str, diff: String) -> Self {
133 Self(Serializer::new().serialize(UnitOp::Change {
134 path,
135 value: diff,
136 }))
137 }
138}
139
140/// Multiple patch operations
141#[derive(Debug, Default)]
142#[must_use]
143pub struct PatchOps(Vec<PatchOp>);
144
145impl From<PatchOps> for PatchOp {
146 fn from(ops: PatchOps) -> Self {
147 let mut merged = PatchOp(Ok(Content::Seq(Vec::with_capacity(ops.0.len()))));
148 for PatchOp(result) in ops.0 {
149 if let Ok(Content::Seq(value)) = &mut merged.0 {
150 match result {
151 Ok(op) => value.push(op),
152 Err(error) => {
153 merged.0 = Err(error);
154 // This operation produced an error, no need to continue
155 break;
156 }
157 }
158 }
159 }
160 merged
161 }
162}
163
164impl PatchOps {
165 /// Prepare for multiple patch operations
166 pub const fn new() -> Self {
167 Self(Vec::new())
168 }
169
170 /// Adds a value to an object or inserts it into an array.
171 ///
172 /// In the case of an array, the value is inserted before the given index.
173 /// The `-` character can be used instead of an index to insert at the end
174 /// of an array.
175 ///
176 /// # Examples
177 ///
178 /// ```
179 /// # use serde_json::json;
180 /// # use surrealdb::opt::PatchOps;
181 /// PatchOps::new().add("/biscuits/1", json!({ "name": "Ginger Nut" }))
182 /// # ;
183 /// ```
184 pub fn add<T>(mut self, path: &str, value: T) -> Self
185 where
186 T: Serialize,
187 {
188 self.0.push(PatchOp::add(path, value));
189 self
190 }
191
192 /// Removes a value from an object or array.
193 ///
194 /// # Examples
195 ///
196 /// ```
197 /// # use surrealdb::opt::PatchOps;
198 /// PatchOps::new().remove("/biscuits")
199 /// # ;
200 /// ```
201 ///
202 /// Remove the first element of the array at `biscuits`
203 /// (or just removes the “0” key if `biscuits` is an object)
204 ///
205 /// ```
206 /// # use surrealdb::opt::PatchOps;
207 /// PatchOps::new().remove("/biscuits/0")
208 /// # ;
209 /// ```
210 pub fn remove(mut self, path: &str) -> Self {
211 self.0.push(PatchOp::remove(path));
212 self
213 }
214
215 /// Replaces a value.
216 ///
217 /// Equivalent to a “remove” followed by an “add”.
218 ///
219 /// # Examples
220 ///
221 /// ```
222 /// # use surrealdb::opt::PatchOps;
223 /// PatchOps::new().replace("/biscuits/0/name", "Chocolate Digestive")
224 /// # ;
225 /// ```
226 pub fn replace<T>(mut self, path: &str, value: T) -> Self
227 where
228 T: Serialize,
229 {
230 self.0.push(PatchOp::replace(path, value));
231 self
232 }
233
234 /// Changes a value
235 pub fn change(mut self, path: &str, diff: String) -> Self {
236 self.0.push(PatchOp::change(path, diff));
237 self
238 }
239}
240
241/// Makes the client wait for a certain event or call to happen before
242/// continuing
243#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
244#[non_exhaustive]
245pub enum WaitFor {
246 /// Waits for the connection to succeed
247 Connection,
248 /// Waits for the desired database to be selected
249 Database,
250}
251
252/// Forwards a raw query without trying to parse for live select statements
253#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
254#[doc(hidden)]
255pub struct Raw(pub(crate) Cow<'static, str>);
256
257impl From<&'static str> for Raw {
258 fn from(query: &'static str) -> Self {
259 Self(Cow::Borrowed(query))
260 }
261}
262
263impl From<String> for Raw {
264 fn from(query: String) -> Self {
265 Self(Cow::Owned(query))
266 }
267}