diff --git a/Cargo.lock b/Cargo.lock index 8de3abf4..d9758e6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -761,6 +761,8 @@ dependencies = [ "const-str", "futures", "log", + "minicbor", + "minicbor-serde", "rust-rocksdb-uwu", "serde", "serde_json", @@ -2329,6 +2331,36 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minicbor" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0452a60c1863c1f50b5f77cd295e8d2786849f35883f0b9e18e7e6e1b5691b0" +dependencies = [ + "minicbor-derive", +] + +[[package]] +name = "minicbor-derive" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd2209fff77f705b00c737016a48e73733d7fbccb8b007194db148f03561fb70" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "minicbor-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "becf18ac384ecf6f53b2db3b1549eebff664c67ecf259ae99be5912193291686" +dependencies = [ + "minicbor", + "serde", +] + [[package]] name = "minimad" version = "0.13.1" diff --git a/Cargo.toml b/Cargo.toml index f9e3b6db..042587fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -506,6 +506,14 @@ version = "0.2" [workspace.dependencies.num-traits] version = "0.2" +[workspace.dependencies.minicbor] +version = "0.25.1" +features = ["std"] + +[workspace.dependencies.minicbor-serde] +version = "0.3.2" +features = ["std"] + # # Patches # diff --git a/src/database/Cargo.toml b/src/database/Cargo.toml index 09eedaf4..557c9a3e 100644 --- a/src/database/Cargo.toml +++ b/src/database/Cargo.toml @@ -40,6 +40,8 @@ conduwuit-core.workspace = true const-str.workspace = true futures.workspace = true log.workspace = true +minicbor.workspace = true +minicbor-serde.workspace = true rust-rocksdb.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/src/database/de.rs b/src/database/de.rs index 48bc9f64..4fdc2251 100644 --- a/src/database/de.rs +++ b/src/database/de.rs @@ -248,6 +248,10 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { { match name { | "$serde_json::private::RawValue" => visitor.visit_map(self), + | "Cbor" => visitor + .visit_newtype_struct(&mut minicbor_serde::Deserializer::new(self.record_trail())) + .map_err(|e| Self::Error::SerdeDe(e.to_string().into())), + | _ => visitor.visit_newtype_struct(self), } } diff --git a/src/database/mod.rs b/src/database/mod.rs index 8ae8dcf5..42b7f5e3 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -31,7 +31,7 @@ pub use self::{ handle::Handle, keyval::{serialize_key, serialize_val, KeyVal, Slice}, map::{compact, Map}, - ser::{serialize, serialize_to, serialize_to_vec, Interfix, Json, Separator, SEP}, + ser::{serialize, serialize_to, serialize_to_vec, Cbor, Interfix, Json, Separator, SEP}, }; pub(crate) use self::{ engine::{context::Context, Engine}, diff --git a/src/database/ser.rs b/src/database/ser.rs index e6de5f7f..372b7522 100644 --- a/src/database/ser.rs +++ b/src/database/ser.rs @@ -1,7 +1,7 @@ use std::io::Write; use conduwuit::{debug::type_name, err, result::DebugInspect, utils::exchange, Error, Result}; -use serde::{ser, Serialize}; +use serde::{ser, Deserialize, Serialize}; use crate::util::unhandled; @@ -55,6 +55,10 @@ pub(crate) struct Serializer<'a, W: Write> { #[derive(Debug, Serialize)] pub struct Json(pub T); +/// Newtype for CBOR serialization. +#[derive(Debug, Deserialize, Serialize)] +pub struct Cbor(pub T); + /// Directive to force separator serialization specifically for prefix keying /// use. This is a quirk of the database schema and prefix iterations. #[derive(Debug, Serialize)] @@ -189,6 +193,14 @@ impl ser::Serializer for &mut Serializer<'_, W> { match name { | "Json" => serde_json::to_writer(&mut self.out, value).map_err(Into::into), + | "Cbor" => { + use minicbor::encode::write::Writer; + use minicbor_serde::Serializer; + + value + .serialize(&mut Serializer::new(&mut Writer::new(&mut self.out))) + .map_err(|e| Self::Error::SerdeSer(e.to_string().into())) + }, | _ => unhandled!("Unrecognized serialization Newtype {name:?}"), } }