From f26e3bc645f5237b49550fbd24f53ddb669b41d0 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Thu, 16 Jul 2026 14:37:06 +0200 Subject: [PATCH 1/3] perf(spanner): add ToValue for &[u8] ToValue was implemented for Vec but not for byte slices, so a caller holding a &[u8] had to allocate an owned Vec (via .to_vec()) purely to encode it, adding a copy per binary cell on potentially hot binding paths. Add impl ToValue for &[u8] holding the BYTES/base64 encoding, and have the Vec impl delegate to it via self.as_slice(). This keeps a single source of truth for the encoding (no risk of the two drifting) while both produce an identical Value. Signed-off-by: Fredrik Fornwall --- src/spanner/src/to_value.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/spanner/src/to_value.rs b/src/spanner/src/to_value.rs index 8dd4645e0c..e5e4e765e0 100644 --- a/src/spanner/src/to_value.rs +++ b/src/spanner/src/to_value.rs @@ -170,6 +170,12 @@ impl ToValue for f32 { } impl ToValue for Vec { + fn to_value(&self) -> Value { + self.as_slice().to_value() + } +} + +impl ToValue for &[u8] { fn to_value(&self) -> Value { Value(ProtoValue { kind: Some(prost_types::value::Kind::StringValue( @@ -252,6 +258,16 @@ mod tests { assert_eq!(v.as_string(), "AQID"); // Base64 encoded } + #[test] + fn test_to_value_bytes_slice() { + let bytes: Vec = vec![1, 2, 3]; + let slice: &[u8] = &bytes; + let v = slice.to_value(); + assert_eq!(v.kind(), Kind::String); + assert_eq!(v.as_string(), "AQID"); // Base64 encoded + assert_eq!(v, bytes.to_value()); + } + #[test] fn test_to_value_decimal() { let d = Decimal::from_str("123.456").unwrap(); From b287bd4a8e601fc01b62557086e081cdc332a9d3 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Fri, 17 Jul 2026 13:01:47 +0200 Subject: [PATCH 2/3] Apply suggestion from @olavloite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Knut Olav Løite --- src/spanner/src/to_value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spanner/src/to_value.rs b/src/spanner/src/to_value.rs index e5e4e765e0..16c271ed50 100644 --- a/src/spanner/src/to_value.rs +++ b/src/spanner/src/to_value.rs @@ -175,7 +175,7 @@ impl ToValue for Vec { } } -impl ToValue for &[u8] { +impl ToValue for [u8] { fn to_value(&self) -> Value { Value(ProtoValue { kind: Some(prost_types::value::Kind::StringValue( From afddb84777687ebe6ef94aef5aca66bb1e3d2aaf Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Fri, 17 Jul 2026 13:02:21 +0200 Subject: [PATCH 3/3] Add test_to_value_slice_trait_bound() as suggested by @olavloite --- src/spanner/src/to_value.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/spanner/src/to_value.rs b/src/spanner/src/to_value.rs index 16c271ed50..b7c9e5df8c 100644 --- a/src/spanner/src/to_value.rs +++ b/src/spanner/src/to_value.rs @@ -268,6 +268,18 @@ mod tests { assert_eq!(v, bytes.to_value()); } + #[test] + fn test_to_value_slice_trait_bound() { + fn bind_param(val: &T) -> Value { + val.to_value() + } + + let slice: &[u8] = &[1, 2, 3]; + let v = bind_param(slice); + assert_eq!(v.kind(), Kind::String); + assert_eq!(v.as_string(), "AQID"); + } + #[test] fn test_to_value_decimal() { let d = Decimal::from_str("123.456").unwrap();