Skip to main content

tuwunel_database/
ser.rs

1//! Serialization for the database's compact record codec.
2//!
3//! Tuples place [`SEP`] between every pair of adjacent elements, while
4//! sequences follow each element's separator state. Supported integer scalars
5//! use big-endian bytes, and [`Json`] and [`Cbor`] delegate their payloads to
6//! the corresponding self-describing format.
7
8use std::{io::Write, mem::replace};
9
10use serde::{Deserialize, Serialize, ser};
11use tuwunel_core::{Error, Result, debug::type_name, err, result::DebugInspect, unhandled};
12
13/// Serializes a value into an owned byte vector.
14///
15/// The database record codec determines the representation. Use [`Json`] or
16/// [`Cbor`] to delegate the wrapped payload to one of those formats.
17///
18/// # Panics
19///
20/// Panics if `T` requests a Serde data-model operation unsupported by this
21/// codec. Debug builds also panic when record-layout invariants are violated or
22/// when a directly wrapped `Json<Box<serde_json::value::RawValue>>` is
23/// serialized.
24#[inline]
25pub fn serialize_to_vec<T: Serialize>(val: T) -> Result<Vec<u8>> {
26	serialize_to::<Vec<u8>, T>(val)
27}
28
29/// Serializes a value into a default-constructed output buffer.
30///
31/// The buffer must support byte writes and expose its completed contents as a
32/// slice. The returned buffer retains any inline-storage behavior chosen by
33/// `B`.
34///
35/// # Panics
36///
37/// Panics if `T` requests a Serde data-model operation unsupported by this
38/// codec. Debug builds also panic when record-layout invariants are violated or
39/// when a directly wrapped `Json<Box<serde_json::value::RawValue>>` is
40/// serialized.
41#[inline]
42pub fn serialize_to<B, T>(val: T) -> Result<B>
43where
44	B: Default + Write + AsRef<[u8]>,
45	T: Serialize,
46{
47	let mut buf = B::default();
48	serialize(&mut buf, val)?;
49
50	Ok(buf)
51}
52
53/// Serializes a value into a caller-provided output buffer.
54///
55/// Encoding is written through the writer without resetting it, and the
56/// returned slice covers the full buffer exposed through `AsRef<[u8]>`. The
57/// compact codec supports its database-oriented subset of the Serde data model.
58///
59/// # Panics
60///
61/// Panics if `T` requests a Serde data-model operation unsupported by this
62/// codec. Debug builds also panic when record-layout invariants are violated or
63/// when a directly wrapped `Json<Box<serde_json::value::RawValue>>` is
64/// serialized.
65#[inline]
66#[cfg_attr(unabridged, tracing::instrument(level = "trace", skip_all))]
67pub fn serialize<'a, W, T>(out: &'a mut W, val: T) -> Result<&'a [u8]>
68where
69	W: Write + AsRef<[u8]> + 'a,
70	T: Serialize,
71{
72	let mut serializer = Serializer { out, depth: 0, sep: false, fin: false };
73
74	val.serialize(&mut serializer)
75		.map_err(|error| err!(SerdeSer("{error}")))
76		.debug_inspect(|()| {
77			debug_assert_eq!(
78				serializer.depth, 0,
79				"Serialization completed at non-zero recursion level"
80			);
81		})?;
82
83	Ok((*out).as_ref())
84}
85
86/// Stateful writer for the compact database record format.
87///
88/// Separator state controls record boundaries in the compact encoding. Debug
89/// builds track container depth and explicit prefix finalization to validate
90/// the layout.
91pub(crate) struct Serializer<'a, W: Write> {
92	out: &'a mut W,
93	depth: u32,
94	sep: bool,
95	fin: bool,
96}
97
98/// Wraps a value for JSON encoding within the database codec.
99///
100/// Encoding and decoding delegate the wrapped value to `serde_json` instead of
101/// the compact record rules. The wrapper changes the representation selected
102/// for its inner value.
103#[derive(Debug, Deserialize, Serialize)]
104pub struct Json<T>(
105	/// Wrapped value encoded as JSON.
106	///
107	/// The field remains public for direct construction and extraction.
108	pub T,
109);
110
111/// Wraps a value for CBOR encoding within the database codec.
112///
113/// Encoding and decoding delegate the wrapped value to `minicbor_serde` instead
114/// of the compact record rules. The wrapper changes the representation selected
115/// for its inner value. Values containing Ruma `Raw<T>` fields do not
116/// round-trip through this format; use [`Json`] for those values.
117#[derive(Debug, Deserialize, Serialize)]
118pub struct Cbor<T>(
119	/// Wrapped value encoded as CBOR.
120	///
121	/// The field remains public for direct construction and extraction.
122	pub T,
123);
124
125/// Finalizes a tuple prefix immediately after its trailing separator.
126///
127/// Place this zero-width marker as the final tuple element to encode a raw
128/// prefix ending in [`SEP`]. It emits no payload of its own, and debug builds
129/// reject serialization after it.
130#[derive(Clone, Copy, Debug, Serialize)]
131pub struct Interfix;
132
133/// Emits one record separator explicitly.
134///
135/// Use this zero-width marker where a format requires [`SEP`] independently of
136/// automatic container boundaries. Unlike [`Interfix`], it does not finalize
137/// the surrounding value.
138#[derive(Clone, Copy, Debug, Serialize)]
139pub struct Separator;
140
141/// Byte separating records in the compact database format.
142///
143/// The value is intentionally invalid UTF-8, so it cannot occur inside a valid
144/// encoded string. Container state emits it at automatic record boundaries,
145/// while [`Separator`] emits it explicitly.
146pub const SEP: u8 = b'\xFF';
147
148impl<W: Write> Serializer<'_, W> {
149	const SEP: &'static [u8] = &[SEP];
150
151	fn tuple_start(&mut self) {
152		debug_assert!(!self.sep, "Tuple start with separator set");
153		self.sequence_start();
154	}
155
156	fn tuple_end(&mut self) -> Result {
157		self.sequence_end()?;
158		Ok(())
159	}
160
161	fn sequence_start(&mut self) {
162		debug_assert!(!self.is_finalized(), "Sequence start with finalization set");
163		cfg!(debug_assertions).then(|| self.depth = self.depth.saturating_add(1));
164		self.sep = false;
165	}
166
167	fn sequence_end(&mut self) -> Result {
168		cfg!(debug_assertions).then(|| self.depth = self.depth.saturating_sub(1));
169		self.sep = false;
170		Ok(())
171	}
172
173	fn record_start(&mut self) -> Result {
174		debug_assert!(!self.is_finalized(), "Starting a record after serialization finalized");
175		replace(&mut self.sep, true)
176			.then(|| self.separator())
177			.unwrap_or(Ok(()))
178	}
179
180	fn separator(&mut self) -> Result {
181		debug_assert!(!self.is_finalized(), "Writing a separator after serialization finalized");
182		self.out.write_all(Self::SEP).map_err(Into::into)
183	}
184
185	fn write(&mut self, buf: &[u8]) -> Result { self.out.write_all(buf).map_err(Into::into) }
186
187	fn set_finalized(&mut self) {
188		debug_assert!(!self.is_finalized(), "Finalization already set");
189		cfg!(debug_assertions).then(|| self.fin = true);
190	}
191
192	fn is_finalized(&self) -> bool { self.fin }
193}
194
195impl<W: Write> ser::Serializer for &mut Serializer<'_, W> {
196	type Error = Error;
197	type Ok = ();
198	type SerializeMap = Self;
199	type SerializeSeq = Self;
200	type SerializeStruct = Self;
201	type SerializeStructVariant = Self;
202	type SerializeTuple = Self;
203	type SerializeTupleStruct = Self;
204	type SerializeTupleVariant = Self;
205
206	fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
207		self.sequence_start();
208		Ok(self)
209	}
210
211	fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
212		self.tuple_start();
213		Ok(self)
214	}
215
216	fn serialize_tuple_struct(
217		self,
218		_name: &'static str,
219		_len: usize,
220	) -> Result<Self::SerializeTupleStruct> {
221		self.tuple_start();
222		Ok(self)
223	}
224
225	fn serialize_tuple_variant(
226		self,
227		_name: &'static str,
228		_idx: u32,
229		_var: &'static str,
230		_len: usize,
231	) -> Result<Self::SerializeTupleVariant> {
232		unhandled!("serialize Tuple Variant not implemented")
233	}
234
235	fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
236		unhandled!(
237			"serialize Map not implemented; did you mean to use database::Json() around your \
238			 serde_json::Value?"
239		)
240	}
241
242	fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
243		unhandled!(
244			"serialize Struct not implemented at this time; did you mean to use \
245			 database::Json() around your struct?"
246		)
247	}
248
249	fn serialize_struct_variant(
250		self,
251		_name: &'static str,
252		_idx: u32,
253		_var: &'static str,
254		_len: usize,
255	) -> Result<Self::SerializeStructVariant> {
256		unhandled!("serialize Struct Variant not implemented")
257	}
258
259	fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<Self::Ok>
260	where
261		T: Serialize + ?Sized,
262	{
263		debug_assert!(
264			name != "Json" || type_name::<T>() != "alloc::boxed::Box<serde_json::raw::RawValue>",
265			"serializing a Json(RawValue); you can skip serialization instead"
266		);
267
268		match name {
269			| "Json" => serde_json::to_writer(&mut *self.out, value).map_err(Into::into),
270			| "Cbor" => {
271				use minicbor::encode::write::Writer;
272				use minicbor_serde::Serializer;
273
274				value
275					.serialize(&mut Serializer::new(&mut Writer::new(&mut *self.out)))
276					.map_err(|e| Self::Error::SerdeSer(e.to_string().into()))
277			},
278			| _ => unhandled!("Unrecognized serialization Newtype {name:?}"),
279		}
280	}
281
282	fn serialize_newtype_variant<T: Serialize + ?Sized>(
283		self,
284		_name: &'static str,
285		_idx: u32,
286		_var: &'static str,
287		_value: &T,
288	) -> Result<Self::Ok> {
289		unhandled!("serialize Newtype Variant not implemented")
290	}
291
292	fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
293		match name {
294			| "Interfix" => {
295				self.set_finalized();
296			},
297			| "Separator" => {
298				self.separator()?;
299			},
300			| _ => unhandled!("Unrecognized serialization directive: {name:?}"),
301		}
302
303		Ok(())
304	}
305
306	fn serialize_unit_variant(
307		self,
308		_name: &'static str,
309		_idx: u32,
310		_var: &'static str,
311	) -> Result<Self::Ok> {
312		unhandled!("serialize Unit Variant not implemented")
313	}
314
315	fn serialize_some<T: Serialize + ?Sized>(self, val: &T) -> Result<Self::Ok> {
316		val.serialize(self)
317	}
318
319	fn serialize_none(self) -> Result<Self::Ok> { Ok(()) }
320
321	fn serialize_char(self, v: char) -> Result<Self::Ok> {
322		let mut buf: [u8; 4] = [0; 4];
323		self.serialize_str(v.encode_utf8(&mut buf))
324	}
325
326	fn serialize_str(self, v: &str) -> Result<Self::Ok> {
327		debug_assert!(
328			self.depth > 0,
329			"serializing string at the top-level; you can skip serialization instead"
330		);
331
332		self.serialize_bytes(v.as_bytes())
333	}
334
335	fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
336		debug_assert!(
337			self.depth > 0,
338			"serializing byte array at the top-level; you can skip serialization instead"
339		);
340
341		self.write(v).inspect(|()| self.sep = true)
342	}
343
344	fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
345		unhandled!("serialize f64 not implemented")
346	}
347
348	fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
349		unhandled!("serialize f32 not implemented")
350	}
351
352	fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
353		self.write(&v.to_be_bytes())
354			.inspect(|()| self.sep = false)
355	}
356
357	fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
358		self.write(&v.to_be_bytes())
359			.inspect(|()| self.sep = false)
360	}
361
362	fn serialize_i16(self, _v: i16) -> Result<Self::Ok> {
363		unhandled!("serialize i16 not implemented")
364	}
365
366	fn serialize_i8(self, _v: i8) -> Result<Self::Ok> {
367		unhandled!("serialize i8 not implemented")
368	}
369
370	fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
371		self.write(&v.to_be_bytes())
372			.inspect(|()| self.sep = false)
373	}
374
375	fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
376		self.write(&v.to_be_bytes())
377			.inspect(|()| self.sep = false)
378	}
379
380	fn serialize_u16(self, _v: u16) -> Result<Self::Ok> {
381		unhandled!("serialize u16 not implemented")
382	}
383
384	fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
385		self.write(&[v]).inspect(|()| self.sep = false)
386	}
387
388	fn serialize_bool(self, _v: bool) -> Result<Self::Ok> {
389		unhandled!("serialize bool not implemented")
390	}
391
392	fn serialize_unit(self) -> Result<Self::Ok> { unhandled!("serialize unit not implemented") }
393}
394
395impl<W: Write> ser::SerializeSeq for &mut Serializer<'_, W> {
396	type Error = Error;
397	type Ok = ();
398
399	fn serialize_element<T: Serialize + ?Sized>(&mut self, val: &T) -> Result<Self::Ok> {
400		self.record_start()?;
401		val.serialize(&mut **self)
402	}
403
404	fn end(self) -> Result<Self::Ok> { self.sequence_end() }
405}
406
407impl<W: Write> ser::SerializeTuple for &mut Serializer<'_, W> {
408	type Error = Error;
409	type Ok = ();
410
411	fn serialize_element<T: Serialize + ?Sized>(&mut self, val: &T) -> Result<Self::Ok> {
412		self.record_start()?;
413		val.serialize(&mut **self)
414			.inspect(|()| self.sep = true)
415	}
416
417	fn end(self) -> Result<Self::Ok> { self.tuple_end() }
418}
419
420impl<W: Write> ser::SerializeTupleStruct for &mut Serializer<'_, W> {
421	type Error = Error;
422	type Ok = ();
423
424	fn serialize_field<T: Serialize + ?Sized>(&mut self, val: &T) -> Result<Self::Ok> {
425		self.record_start()?;
426		val.serialize(&mut **self)
427			.inspect(|()| self.sep = true)
428	}
429
430	fn end(self) -> Result<Self::Ok> { self.tuple_end() }
431}
432
433impl<W: Write> ser::SerializeTupleVariant for &mut Serializer<'_, W> {
434	type Error = Error;
435	type Ok = ();
436
437	fn serialize_field<T: Serialize + ?Sized>(&mut self, val: &T) -> Result<Self::Ok> {
438		self.record_start()?;
439		val.serialize(&mut **self)
440			.inspect(|()| self.sep = true)
441	}
442
443	fn end(self) -> Result<Self::Ok> { self.tuple_end() }
444}
445
446impl<W: Write> ser::SerializeMap for &mut Serializer<'_, W> {
447	type Error = Error;
448	type Ok = ();
449
450	fn serialize_key<T: Serialize + ?Sized>(&mut self, _key: &T) -> Result<Self::Ok> {
451		unhandled!("serialize Map Key not implemented")
452	}
453
454	fn serialize_value<T: Serialize + ?Sized>(&mut self, _val: &T) -> Result<Self::Ok> {
455		unhandled!("serialize Map Val not implemented")
456	}
457
458	fn end(self) -> Result<Self::Ok> { unhandled!("serialize Map End not implemented") }
459}
460
461impl<W: Write> ser::SerializeStruct for &mut Serializer<'_, W> {
462	type Error = Error;
463	type Ok = ();
464
465	fn serialize_field<T: Serialize + ?Sized>(
466		&mut self,
467		_key: &'static str,
468		_val: &T,
469	) -> Result<Self::Ok> {
470		unhandled!("serialize Struct Field not implemented")
471	}
472
473	fn end(self) -> Result<Self::Ok> { unhandled!("serialize Struct End not implemented") }
474}
475
476impl<W: Write> ser::SerializeStructVariant for &mut Serializer<'_, W> {
477	type Error = Error;
478	type Ok = ();
479
480	fn serialize_field<T: Serialize + ?Sized>(
481		&mut self,
482		_key: &'static str,
483		_val: &T,
484	) -> Result<Self::Ok> {
485		unhandled!("serialize Struct Variant Field not implemented")
486	}
487
488	fn end(self) -> Result<Self::Ok> {
489		unhandled!("serialize Struct Variant End not implemented")
490	}
491}