surrealdb_core/key/change/
mod.rs

1/// Stores change feeds
2use derive::Key;
3use serde::{Deserialize, Serialize};
4
5use crate::vs;
6
7use crate::key::error::KeyCategory;
8use crate::key::key_req::KeyRequirements;
9use std::str;
10
11// Cf stands for change feeds
12#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Key)]
13#[non_exhaustive]
14pub struct Cf<'a> {
15	__: u8,
16	_a: u8,
17	pub ns: &'a str,
18	_b: u8,
19	pub db: &'a str,
20	_d: u8,
21	// vs is the versionstamp of the change feed entry that is encoded in big-endian.
22	// Use the to_u64_be function to convert it to a u128.
23	pub vs: [u8; 10],
24	_c: u8,
25	pub tb: &'a str,
26}
27
28#[allow(unused)]
29pub fn new<'a>(ns: &'a str, db: &'a str, ts: u64, tb: &'a str) -> Cf<'a> {
30	Cf::new(ns, db, vs::u64_to_versionstamp(ts), tb)
31}
32
33#[allow(unused)]
34pub fn versionstamped_key_prefix(ns: &str, db: &str) -> Vec<u8> {
35	let mut k = crate::key::database::all::new(ns, db).encode().unwrap();
36	k.extend_from_slice(&[b'#']);
37	k
38}
39
40#[allow(unused)]
41pub fn versionstamped_key_suffix(tb: &str) -> Vec<u8> {
42	let mut k: Vec<u8> = vec![];
43	k.extend_from_slice(&[b'*']);
44	k.extend_from_slice(tb.as_bytes());
45	// Without this, decoding fails with UnexpectedEOF errors
46	k.extend_from_slice(&[0x00]);
47	k
48}
49
50/// Returns the prefix for the whole database change feeds since the
51/// specified versionstamp.
52#[allow(unused)]
53pub fn prefix_ts(ns: &str, db: &str, vs: vs::Versionstamp) -> Vec<u8> {
54	let mut k = crate::key::database::all::new(ns, db).encode().unwrap();
55	k.extend_from_slice(&[b'#']);
56	k.extend_from_slice(&vs);
57	k
58}
59
60/// Returns the prefix for the whole database change feeds
61#[allow(unused)]
62pub fn prefix(ns: &str, db: &str) -> Vec<u8> {
63	let mut k = crate::key::database::all::new(ns, db).encode().unwrap();
64	k.extend_from_slice(&[b'#']);
65	k
66}
67
68/// Returns the suffix for the whole database change feeds
69#[allow(unused)]
70pub fn suffix(ns: &str, db: &str) -> Vec<u8> {
71	let mut k = crate::key::database::all::new(ns, db).encode().unwrap();
72	k.extend_from_slice(&[b'#', 0xff]);
73	k
74}
75
76impl KeyRequirements for Cf<'_> {
77	fn key_category(&self) -> KeyCategory {
78		KeyCategory::ChangeFeed
79	}
80}
81
82impl<'a> Cf<'a> {
83	pub fn new(ns: &'a str, db: &'a str, vs: [u8; 10], tb: &'a str) -> Self {
84		Cf {
85			__: b'/',
86			_a: b'*',
87			ns,
88			_b: b'*',
89			db,
90			_d: b'#',
91			vs,
92			_c: b'*',
93			tb,
94		}
95	}
96}
97
98#[cfg(test)]
99mod tests {
100	use crate::vs::*;
101	use std::ascii::escape_default;
102
103	#[test]
104	fn key() {
105		use super::*;
106		#[rustfmt::skip]
107		let val = Cf::new(
108			"test",
109			"test",
110			try_u128_to_versionstamp(12345).unwrap(),
111			"test",
112		);
113		let enc = Cf::encode(&val).unwrap();
114		println!("enc={}", show(&enc));
115		let dec = Cf::decode(&enc).unwrap();
116		assert_eq!(val, dec);
117	}
118
119	#[test]
120	fn versionstamp_conversions() {
121		let a = u64_to_versionstamp(12345);
122		let b = try_to_u64_be(a).unwrap();
123		assert_eq!(12345, b);
124
125		let a = try_u128_to_versionstamp(12345).unwrap();
126		let b = to_u128_be(a);
127		assert_eq!(12345, b);
128	}
129
130	fn show(bs: &[u8]) -> String {
131		let mut visible = String::new();
132		for &b in bs {
133			let part: Vec<u8> = escape_default(b).collect();
134			visible.push_str(std::str::from_utf8(&part).unwrap());
135		}
136		visible
137	}
138}