From 12d8b266a11108bf5d7408b25772292b3d294167 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Thu, 24 Jul 2025 10:37:27 +0300 Subject: [PATCH] Define some helper traits to reduce duplication --- core/types.rs | 68 +++++++++++++++++++++++++++++++++++++++++++- core/vdbe/execute.rs | 39 ++++++------------------- 2 files changed, 76 insertions(+), 31 deletions(-) diff --git a/core/types.rs b/core/types.rs index b1cf976cf..acfa4ccd0 100644 --- a/core/types.rs +++ b/core/types.rs @@ -82,7 +82,6 @@ impl Text { subtype: TextSubtype::Text, } } - #[cfg(feature = "json")] pub fn json(value: String) -> Self { Self { @@ -96,6 +95,73 @@ impl Text { } } +pub trait Extendable { + fn maybe_extend(&mut self, other: &T) -> bool; +} + +impl Extendable for Text { + fn maybe_extend(&mut self, other: &T) -> bool { + if self.value.capacity() >= other.as_ref().len() { + self.value.clear(); + self.value.extend_from_slice(other.as_ref().as_bytes()); + self.subtype = other.subtype(); + true + } else { + false + } + } +} + +impl Extendable for Vec { + fn maybe_extend(&mut self, other: &T) -> bool { + if self.capacity() >= other.as_slice().len() { + self.clear(); + self.extend_from_slice(other.as_slice()); + true + } else { + false + } + } +} + +pub trait AnyText: AsRef { + fn subtype(&self) -> TextSubtype; +} + +impl AsRef for TextRef { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AnyText for Text { + fn subtype(&self) -> TextSubtype { + self.subtype + } +} + +impl AnyText for TextRef { + fn subtype(&self) -> TextSubtype { + self.subtype + } +} + +pub trait AnyBlob { + fn as_slice(&self) -> &[u8]; +} + +impl AnyBlob for RawSlice { + fn as_slice(&self) -> &[u8] { + self.to_slice() + } +} + +impl AnyBlob for Vec { + fn as_slice(&self) -> &[u8] { + self.as_slice() + } +} + impl AsRef for Text { fn as_ref(&self) -> &str { self.as_str() diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 98de72e67..2bd73263b 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -10,8 +10,8 @@ use crate::storage::wal::DummyWAL; use crate::storage::{self, header_accessor}; use crate::translate::collate::CollationSeq; use crate::types::{ - compare_immutable, compare_records_generic, ImmutableRecord, RawSlice, SeekResult, Text, - TextRef, TextSubtype, + compare_immutable, compare_records_generic, Extendable, ImmutableRecord, RawSlice, SeekResult, + Text, TextRef, TextSubtype, }; use crate::util::normalize_ident; use crate::vdbe::insn::InsertFlags; @@ -1595,23 +1595,13 @@ pub fn op_column( }; match (default, &mut state.registers[*dest]) { (Value::Text(new_text), Register::Value(Value::Text(existing_text))) => { - let new_text_str = new_text.as_str(); - if existing_text.value.capacity() >= new_text_str.len() { - existing_text.value.clear(); - existing_text - .value - .extend_from_slice(new_text_str.as_bytes()); - existing_text.subtype = new_text.subtype; - } else { + if !existing_text.maybe_extend(new_text) { state.registers[*dest] = - Register::Value(Value::Text(Text::new(new_text_str))); + Register::Value(Value::Text(Text::new(new_text.as_str()))); } } (Value::Blob(new_blob), Register::Value(Value::Blob(existing_blob))) => { - if existing_blob.capacity() >= new_blob.len() { - existing_blob.clear(); - existing_blob.extend_from_slice(new_blob); - } else { + if !existing_blob.maybe_extend(new_blob) { state.registers[*dest] = Register::Value(Value::Blob(new_blob.to_vec())); } @@ -1627,26 +1617,15 @@ pub fn op_column( // Try to reuse the registers when allocation is not needed. match (&value, &mut state.registers[*dest]) { (RefValue::Text(new_text), Register::Value(Value::Text(existing_text))) => { - let new_text_str = new_text.as_str(); - if existing_text.value.capacity() >= new_text_str.len() { - existing_text.value.clear(); - existing_text - .value - .extend_from_slice(new_text_str.as_bytes()); - existing_text.subtype = new_text.subtype; - } else { + if !existing_text.maybe_extend(new_text) { state.registers[*dest] = - Register::Value(Value::Text(Text::new(new_text_str))); + Register::Value(Value::Text(Text::new(new_text.as_str()))); } } (RefValue::Blob(new_blob), Register::Value(Value::Blob(existing_blob))) => { - let new_blob_slice = new_blob.to_slice(); - if existing_blob.capacity() >= new_blob_slice.len() { - existing_blob.clear(); - existing_blob.extend_from_slice(new_blob_slice); - } else { + if !existing_blob.maybe_extend(new_blob) { state.registers[*dest] = - Register::Value(Value::Blob(new_blob_slice.to_vec())); + Register::Value(Value::Blob(new_blob.to_slice().to_vec())); } } _ => {