Skip to main content

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}