Define some helper traits to reduce duplication

This commit is contained in:
Jussi Saurio
2025-07-24 10:37:27 +03:00
parent 7eb52c65d3
commit 12d8b266a1
2 changed files with 76 additions and 31 deletions

View File

@@ -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<T> {
fn maybe_extend(&mut self, other: &T) -> bool;
}
impl<T: AnyText> Extendable<T> 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<T: AnyBlob> Extendable<T> for Vec<u8> {
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<str> {
fn subtype(&self) -> TextSubtype;
}
impl AsRef<str> 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<u8> {
fn as_slice(&self) -> &[u8] {
self.as_slice()
}
}
impl AsRef<str> for Text {
fn as_ref(&self) -> &str {
self.as_str()

View File

@@ -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()));
}
}
_ => {