diff --git a/Cargo.lock b/Cargo.lock index c031a417ca..bafcc7a5aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,7 +252,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -274,7 +274,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -295,7 +295,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -856,7 +856,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.87", + "syn 2.0.114", "which", ] @@ -1257,7 +1257,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -1690,6 +1690,41 @@ dependencies = [ "memchr", ] +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.114", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.114", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -1732,7 +1767,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -1744,7 +1779,7 @@ dependencies = [ "console", "shell-words", "tempfile", - "thiserror", + "thiserror 1.0.61", "zeroize", ] @@ -1901,7 +1936,7 @@ checksum = "3bf679796c0322556351f287a51b49e48f7c4986e727b5dd78c972d30e2e16cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -2124,7 +2159,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -2606,6 +2641,12 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -2905,7 +2946,6 @@ dependencies = [ "async-stream", "async-trait", "base64 0.21.7", - "bincode", "bitflags 2.6.0", "bytes", "chrono", @@ -2926,7 +2966,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-test", @@ -2938,6 +2978,7 @@ dependencies = [ "tracing", "tracing-subscriber", "uuid", + "wincode", "worker", "zerocopy", ] @@ -3021,7 +3062,6 @@ dependencies = [ "axum", "axum-extra", "base64 0.21.7", - "bincode", "bottomless", "bytes", "bytesize", @@ -3086,7 +3126,7 @@ dependencies = [ "sha256", "tar", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-tungstenite", @@ -3102,6 +3142,7 @@ dependencies = [ "url", "uuid", "vergen", + "wincode", "zerocopy", ] @@ -3161,7 +3202,6 @@ dependencies = [ "arbitrary", "async-stream", "async-trait", - "bincode", "bytes", "cbc", "libsql-rusqlite", @@ -3171,7 +3211,7 @@ dependencies = [ "prost-build", "serde", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-util", @@ -3179,6 +3219,7 @@ dependencies = [ "tonic-build", "tracing", "uuid", + "wincode", "zerocopy", ] @@ -3340,7 +3381,7 @@ dependencies = [ "metrics", "metrics-util", "quanta 0.11.1", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -3353,7 +3394,7 @@ checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -3435,7 +3476,7 @@ dependencies = [ "rustc_version", "smallvec", "tagptr", - "thiserror", + "thiserror 1.0.61", "triomphe", "uuid", ] @@ -3791,7 +3832,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -3882,7 +3923,7 @@ dependencies = [ "smallvec", "symbolic-demangle", "tempfile", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -3898,7 +3939,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -3913,9 +3954,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] @@ -3967,7 +4008,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.87", + "syn 2.0.114", "tempfile", ] @@ -3981,7 +4022,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -4071,9 +4112,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -4201,7 +4242,7 @@ checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -4563,7 +4604,7 @@ dependencies = [ "sha1", "sha2", "smallvec", - "thiserror", + "thiserror 1.0.61", "time", "tracing", "transform-stream", @@ -4595,7 +4636,7 @@ dependencies = [ "serde_json", "sha1", "sha2", - "thiserror", + "thiserror 1.0.61", "time", "tokio", "tokio-util", @@ -4726,7 +4767,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -4882,7 +4923,7 @@ checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ "num-bigint", "num-traits", - "thiserror", + "thiserror 1.0.61", "time", ] @@ -5027,9 +5068,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -5135,7 +5176,16 @@ version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.61", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", ] [[package]] @@ -5146,7 +5196,18 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", ] [[package]] @@ -5265,7 +5326,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -5415,7 +5476,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -5532,7 +5593,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] @@ -5619,7 +5680,7 @@ dependencies = [ "log", "rand", "sha1", - "thiserror", + "thiserror 1.0.61", "url", "utf-8", ] @@ -5854,7 +5915,7 @@ dependencies = [ "io-extras", "log", "rustix 0.37.27", - "thiserror", + "thiserror 1.0.61", "tracing", "wasmtime", "wiggle", @@ -5906,7 +5967,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", "wasm-bindgen-shared", ] @@ -6053,7 +6114,7 @@ dependencies = [ "log", "object 0.30.4", "target-lexicon", - "thiserror", + "thiserror 1.0.61", "wasmparser", "wasmtime-cranelift-shared", "wasmtime-environ", @@ -6089,7 +6150,7 @@ dependencies = [ "object 0.30.4", "serde", "target-lexicon", - "thiserror", + "thiserror 1.0.61", "wasmparser", "wasmtime-types", ] @@ -6187,7 +6248,7 @@ checksum = "19961c9a3b04d5e766875a5c467f6f5d693f508b3e81f8dc4a1444aa94f041c9" dependencies = [ "cranelift-entity", "serde", - "thiserror", + "thiserror 1.0.61", "wasmparser", ] @@ -6293,7 +6354,7 @@ dependencies = [ "anyhow", "async-trait", "bitflags 1.3.2", - "thiserror", + "thiserror 1.0.61", "tracing", "wasmtime", "wiggle-macro", @@ -6357,6 +6418,30 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "wincode" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5cec722a3274e47d1524cbe2cea762f2c19d615bd9d73ada21db9066349d57e" +dependencies = [ + "proc-macro2", + "quote", + "thiserror 2.0.17", + "wincode-derive", +] + +[[package]] +name = "wincode-derive" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8961eb04054a1b2e026b5628e24da7e001350249a787e1a85aa961f33dc5f286" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -6565,7 +6650,7 @@ checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" dependencies = [ "anyhow", "log", - "thiserror", + "thiserror 1.0.61", "wast 35.0.2", ] @@ -6608,7 +6693,7 @@ dependencies = [ "async-trait", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-macro-support", @@ -6669,7 +6754,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.114", ] [[package]] diff --git a/libsql-replication/Cargo.toml b/libsql-replication/Cargo.toml index e41c57cac5..05c46ff82d 100644 --- a/libsql-replication/Cargo.toml +++ b/libsql-replication/Cargo.toml @@ -29,7 +29,7 @@ cbc = "0.1.2" [dev-dependencies] arbitrary = { version = "1.3.0", features = ["derive_arbitrary"] } -bincode = "1.3.3" +wincode = { version = "0.2", features = ["derive"] } tempfile = "3.8.0" prost-build = "0.12" tonic-build = "0.11" diff --git a/libsql-replication/proto/proxy.proto b/libsql-replication/proto/proxy.proto index 5949cb078d..8aee59b656 100644 --- a/libsql-replication/proto/proxy.proto +++ b/libsql-replication/proto/proxy.proto @@ -71,7 +71,7 @@ message Description { } message Value { - /// bincode encoded Value + /// wincode encoded Value (binary compatible with bincode) bytes data = 1; } diff --git a/libsql-replication/src/generated/proxy.rs b/libsql-replication/src/generated/proxy.rs index a76bb9bf65..afd5ba38b5 100644 --- a/libsql-replication/src/generated/proxy.rs +++ b/libsql-replication/src/generated/proxy.rs @@ -180,7 +180,7 @@ pub struct Description { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Value { - /// / bincode encoded Value + /// / wincode encoded Value (binary compatible with bincode) #[prost(bytes = "vec", tag = "1")] pub data: ::prost::alloc::vec::Vec, } diff --git a/libsql-server/Cargo.toml b/libsql-server/Cargo.toml index 06107d0557..26fa20888d 100644 --- a/libsql-server/Cargo.toml +++ b/libsql-server/Cargo.toml @@ -18,7 +18,7 @@ async-trait = "0.1.58" axum = { version = "0.6.18", features = ["headers"] } axum-extra = { version = "0.7", features = ["json-lines", "query"] } base64 = "0.21.0" -bincode = "1.3.3" +wincode = { version = "0.2", features = ["derive"] } bottomless = { version = "0", path = "../bottomless", features = ["libsql_linked_statically"] } bytes = { version = "1.2.1", features = ["serde"] } bytesize = { version = "1.2.0", features = ["serde"] } diff --git a/libsql-server/src/error.rs b/libsql-server/src/error.rs index bfe67f47c7..b2cf9a2914 100644 --- a/libsql-server/src/error.rs +++ b/libsql-server/src/error.rs @@ -244,8 +244,14 @@ impl From for Error { } } -impl From for Error { - fn from(other: bincode::Error) -> Self { +impl From for Error { + fn from(other: wincode::WriteError) -> Self { + Self::Internal(other.to_string()) + } +} + +impl From for Error { + fn from(other: wincode::ReadError) -> Self { Self::Internal(other.to_string()) } } diff --git a/libsql-server/src/query.rs b/libsql-server/src/query.rs index 72096226cc..de68833926 100644 --- a/libsql-server/src/query.rs +++ b/libsql-server/src/query.rs @@ -4,11 +4,12 @@ use anyhow::{anyhow, ensure, Context}; use rusqlite::types::{ToSqlOutput, ValueRef}; use rusqlite::ToSql; use serde::{Deserialize, Serialize}; +use wincode::{SchemaRead, SchemaWrite}; use crate::query_analysis::Statement; /// Mirrors rusqlite::Value, but implement extra traits -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, SchemaWrite, SchemaRead)] #[cfg_attr(test, derive(arbitrary::Arbitrary))] pub enum Value { Null, diff --git a/libsql-server/src/rpc/mod.rs b/libsql-server/src/rpc/mod.rs index 2936a8742c..5cf8bdf56f 100644 --- a/libsql-server/src/rpc/mod.rs +++ b/libsql-server/src/rpc/mod.rs @@ -23,6 +23,9 @@ pub mod replica_proxy; pub mod replication; pub mod streaming_exec; +#[cfg(test)] +mod wincode_compat_test; + pub async fn run_rpc_server( proxy_service: ProxyService, acceptor: A, diff --git a/libsql-server/src/rpc/proxy.rs b/libsql-server/src/rpc/proxy.rs index 1ab5d1d19a..2107c8504a 100644 --- a/libsql-server/src/rpc/proxy.rs +++ b/libsql-server/src/rpc/proxy.rs @@ -99,7 +99,7 @@ pub mod rpc { crate::query::Params::Named(params) => { let iter = params.into_iter().map(|(k, v)| -> Result<_, SqldError> { let v = Value { - data: bincode::serialize(&v)?, + data: wincode::serialize(&v)?, }; Ok((k, v)) }); @@ -111,7 +111,7 @@ pub mod rpc { .iter() .map(|v| { Ok(Value { - data: bincode::serialize(&v)?, + data: wincode::serialize(&v)?, }) }) .collect::, SqldError>>()?; @@ -130,12 +130,12 @@ pub mod rpc { let params = pos .values .into_iter() - .map(|v| bincode::deserialize(&v.data).map_err(|e| e.into())) + .map(|v| wincode::deserialize(&v.data).map_err(|e| e.into())) .collect::, SqldError>>()?; Ok(Self::Positional(params)) } query::Params::Named(named) => { - let values = named.values.iter().map(|v| bincode::deserialize(&v.data)); + let values = named.values.iter().map(|v| wincode::deserialize(&v.data)); let params = itertools::process_results(values, |values| { named.names.into_iter().zip(values).collect() })?; @@ -455,7 +455,7 @@ impl QueryResultBuilder for ExecuteResultsBuilder { } fn add_row_value(&mut self, v: ValueRef) -> Result<(), QueryResultBuilderError> { - let data = bincode::serialize( + let data = wincode::serialize( &crate::query::Value::try_from(v).map_err(QueryResultBuilderError::from_any)?, ) .map_err(QueryResultBuilderError::from_any)?; diff --git a/libsql-server/src/rpc/wincode_compat_test.rs b/libsql-server/src/rpc/wincode_compat_test.rs new file mode 100644 index 0000000000..111ec68929 --- /dev/null +++ b/libsql-server/src/rpc/wincode_compat_test.rs @@ -0,0 +1,101 @@ +#![cfg(test)] + +//! Tests to verify wincode binary compatibility with bincode 1.3.3. +//! +//! These tests ensure that the migration from bincode to wincode maintains +//! wire protocol compatibility with existing clients (particularly the Go client). + +use crate::query::Value; + +#[test] +fn test_wincode_produces_same_bytes_as_bincode() { + // Test that wincode produces identical bytes to what bincode 1.3.3 would produce. + // This is critical for maintaining wire protocol compatibility. + + let test_cases = vec![ + ("Null", Value::Null, vec![0, 0, 0, 0]), + ( + "Integer(42)", + Value::Integer(42), + vec![1, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0], + ), + ( + "Integer(i64::MAX)", + Value::Integer(i64::MAX), + vec![1, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 127], + ), + ( + "Real(3.14159)", + Value::Real(3.14159), + vec![2, 0, 0, 0, 110, 134, 27, 240, 249, 33, 9, 64], + ), + ( + "Text(empty)", + Value::Text(String::new()), + vec![3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ), + ( + "Text(Hello)", + Value::Text("Hello".to_string()), + vec![3, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 72, 101, 108, 108, 111], + ), + ( + "Blob([1,2,3])", + Value::Blob(vec![1, 2, 3]), + vec![4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3], + ), + ]; + + for (name, value, expected_bytes) in test_cases { + let serialised = wincode::serialize(&value).expect("wincode serialisation failed"); + + assert_eq!( + serialised, expected_bytes, + "{}: wincode output differs from expected bincode output", + name + ); + + // Also verify roundtrip + let deserialised: Value = + wincode::deserialize(&serialised).expect("wincode deserialisation failed"); + + assert_eq!( + format!("{:?}", value), + format!("{:?}", deserialised), + "{}: roundtrip failed", + name + ); + } +} + +#[test] +fn test_wincode_roundtrip_all_variants() { + // Verify that all Value variants can be serialised and deserialised correctly. + let values = vec![ + Value::Null, + Value::Integer(0), + Value::Integer(i64::MIN), + Value::Integer(i64::MAX), + Value::Real(0.0), + Value::Real(std::f64::consts::PI), + Value::Real(f64::MIN), + Value::Real(f64::MAX), + Value::Text(String::new()), + Value::Text("test".to_string()), + Value::Text("unicode: 🦀🚀".to_string()), + Value::Blob(vec![]), + Value::Blob(vec![0u8, 255u8]), + Value::Blob(vec![1, 2, 3, 4, 5]), + ]; + + for value in &values { + let encoded = wincode::serialize(value).expect("encode failed"); + let decoded: Value = wincode::deserialize(&encoded).expect("decode failed"); + assert_eq!( + format!("{:?}", value), + format!("{:?}", decoded), + "roundtrip failed for {:?}", + value + ); + } +} diff --git a/libsql/Cargo.toml b/libsql/Cargo.toml index e8a7e0f909..002fc9b984 100644 --- a/libsql/Cargo.toml +++ b/libsql/Cargo.toml @@ -27,7 +27,7 @@ bitflags = { version = "2.4.0", optional = true } tower = { workspace = true, features = ["util"], optional = true } worker = { version = "0.6.7", optional = true } -bincode = { version = "1", optional = true } +wincode = { version = "0.2", optional = true, features = ["derive"] } anyhow = { version = "1.0.71", optional = true } bytes = { version = "1.4.0", features = ["serde"], optional = true } uuid = { version = "1.4.0", features = ["v4", "serde"], optional = true } @@ -83,7 +83,7 @@ replication = [ "dep:http", "dep:tokio", "dep:anyhow", - "dep:bincode", + "dep:wincode", "dep:zerocopy", "dep:bytes", "dep:uuid", diff --git a/libsql/src/errors.rs b/libsql/src/errors.rs index f612aa62f1..5d44bc3bc2 100644 --- a/libsql/src/errors.rs +++ b/libsql/src/errors.rs @@ -31,8 +31,8 @@ pub enum Error { Hrana(crate::BoxError), // Not in rusqlite #[error("Write delegation: `{0}`")] WriteDelegation(crate::BoxError), // Not in rusqlite - #[error("bincode: `{0}`")] - Bincode(crate::BoxError), + #[error("wincode: `{0}`")] + Wincode(crate::BoxError), #[error("invalid column index")] InvalidColumnIndex, #[error("invalid column type")] @@ -112,8 +112,15 @@ pub fn sqlite_errmsg_to_string(errmsg: *const std::ffi::c_char) -> String { } #[cfg(feature = "replication")] -impl From for Error { - fn from(e: bincode::Error) -> Self { - Error::Bincode(e.into()) +impl From for Error { + fn from(e: wincode::WriteError) -> Self { + Error::Wincode(e.into()) + } +} + +#[cfg(feature = "replication")] +impl From for Error { + fn from(e: wincode::ReadError) -> Self { + Error::Wincode(e.into()) } } diff --git a/libsql/src/params.rs b/libsql/src/params.rs index 6921e0145e..415663c12f 100644 --- a/libsql/src/params.rs +++ b/libsql/src/params.rs @@ -291,7 +291,7 @@ impl From for libsql_replication::rpc::proxy::query::Params { Params::Positional(values) => { let values = values .iter() - .map(|v| bincode::serialize(v).unwrap()) + .map(|v| wincode::serialize(v).unwrap()) .map(|data| proxy::Value { data }) .collect::>(); proxy::query::Params::Positional(proxy::Positional { values }) @@ -300,7 +300,7 @@ impl From for libsql_replication::rpc::proxy::query::Params { let (names, values) = values .into_iter() .map(|(name, value)| { - let data = bincode::serialize(&value).unwrap(); + let data = wincode::serialize(&value).unwrap(); let value = proxy::Value { data }; (name, value) }) diff --git a/libsql/src/value.rs b/libsql/src/value.rs index 7d50265eed..e8a1c5cf16 100644 --- a/libsql/src/value.rs +++ b/libsql/src/value.rs @@ -4,6 +4,10 @@ use crate::{Error, Result}; #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr( + feature = "replication", + derive(wincode::SchemaWrite, wincode::SchemaRead) +)] pub enum Value { Null, Integer(i64), @@ -449,24 +453,7 @@ impl TryFrom<&libsql_replication::rpc::proxy::Value> for Value { type Error = Error; fn try_from(value: &libsql_replication::rpc::proxy::Value) -> Result { - #[derive(serde::Deserialize)] - pub enum BincodeValue { - Null, - Integer(i64), - Real(f64), - Text(String), - Blob(Vec), - } - - Ok( - match bincode::deserialize::<'_, BincodeValue>(&value.data[..]).map_err(Error::from)? { - BincodeValue::Null => Value::Null, - BincodeValue::Integer(i) => Value::Integer(i), - BincodeValue::Real(x) => Value::Real(x), - BincodeValue::Text(s) => Value::Text(s), - BincodeValue::Blob(b) => Value::Blob(b), - }, - ) + wincode::deserialize(&value.data[..]).map_err(Error::from) } }