From 4bbe780a34a63ffbcfc850e7191f800bac8ec161 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Thu, 5 Jun 2025 13:10:44 -0300 Subject: [PATCH] add optional serde serialization and deserialization to limbo Value --- Cargo.lock | 1 + core/Cargo.toml | 3 +++ core/types.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index b3047aad8..1f81e1a76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1841,6 +1841,7 @@ dependencies = [ "rusqlite", "rustix 1.0.7", "ryu", + "serde", "sorted-vec", "strum", "strum_macros", diff --git a/core/Cargo.toml b/core/Cargo.toml index 898eb337d..9673497a7 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -31,6 +31,8 @@ static = ["limbo_ext/static"] fuzz = [] csv = ["limbo_csv/static"] omit_autovacuum = [] +simulator = ["fuzz", "serde"] +serde = ["dep:serde"] [target.'cfg(target_os = "linux")'.dependencies] io-uring = { version = "0.7.5", optional = true } @@ -80,6 +82,7 @@ ryu = "1.0.19" uncased = "0.9.10" strum_macros = { workspace = true } bitflags = "2.9.0" +serde = { workspace = true , optional = true, features = ["derive"] } [build-dependencies] chrono = { version = "0.4.38", default-features = false } diff --git a/core/types.rs b/core/types.rs index 544af0523..68363d5dd 100644 --- a/core/types.rs +++ b/core/types.rs @@ -1,5 +1,7 @@ use limbo_ext::{AggCtx, FinalizeFunction, StepFunction}; use limbo_sqlite3_parser::ast::SortOrder; +#[cfg(feature = "serde")] +use serde::Deserialize; use crate::error::LimboError; use crate::ext::{ExtValue, ExtValueType}; @@ -42,6 +44,7 @@ impl Display for ValueType { } #[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TextSubtype { Text, #[cfg(feature = "json")] @@ -49,6 +52,7 @@ pub enum TextSubtype { } #[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Text { pub value: Vec, pub subtype: TextSubtype, @@ -108,10 +112,36 @@ impl TextRef { } } +#[cfg(feature = "serde")] +fn float_to_string(float: &f64, serializer: S) -> Result +where + S: serde::Serializer, +{ + serializer.serialize_str(&format!("{}", float)) +} + +#[cfg(feature = "serde")] +fn string_to_float<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + s.parse().map_err(serde::de::Error::custom) +} + #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Value { Null, Integer(i64), + // we use custom serialization to preserve float precision + #[cfg_attr( + feature = "serde", + serde( + serialize_with = "float_to_string", + deserialize_with = "string_to_float" + ) + )] Float(f64), Text(Text), Blob(Vec),