Add safety comments and clean up extension types

This commit is contained in:
PThorpe92 2025-01-12 15:48:26 -05:00
parent 98eff6cf7a
commit 6e05258d36
No known key found for this signature in database
GPG key ID: 66DB3FBACBDD05CC
3 changed files with 28 additions and 24 deletions

View file

@ -123,14 +123,10 @@ impl OwnedValue {
OwnedValue::Float(float)
}
ExtValueType::Text => {
if v.value.is_null() {
OwnedValue::Null
} else {
let Some(text) = ExtTextValue::from_value(v) else {
return OwnedValue::Null;
};
OwnedValue::build_text(std::rc::Rc::new(unsafe { text.as_str().to_string() }))
}
let Some(text) = (unsafe { ExtTextValue::from_value(v) }) else {
return OwnedValue::Null;
};
OwnedValue::build_text(std::rc::Rc::new(unsafe { text.as_str().to_string() }))
}
ExtValueType::Blob => {
let blob_ptr = v.value as *mut ExtBlob;

View file

@ -73,7 +73,9 @@ declare_scalar_functions! {
Value::from_integer(unix as i64)
}
ValueType::Text => {
let text = TextValue::from_value(&args[0]).unwrap();
let Some(text) = (unsafe {TextValue::from_value(&args[0])}) else {
return Value::null();
};
let uuid = uuid::Uuid::parse_str(unsafe {text.as_str()}).unwrap();
let unix = uuid_to_unix(uuid.as_bytes());
Value::from_integer(unix as i64)
@ -106,16 +108,15 @@ declare_scalar_functions! {
log::debug!("uuid_blob was passed a non-text arg");
return Value::null();
}
if let Some(text) = TextValue::from_value(&args[0]) {
let Some(text) = (unsafe { TextValue::from_value(&args[0])}) else {
return Value::null();
};
match uuid::Uuid::parse_str(unsafe {text.as_str()}) {
Ok(uuid) => {
Value::from_blob(uuid.as_bytes().to_vec())
}
Err(_) => Value::null()
}
} else {
Value::null()
}
}
}

View file

@ -137,8 +137,8 @@ impl std::fmt::Debug for Value {
#[repr(C)]
pub struct TextValue {
pub text: *const u8,
pub len: u32,
text: *const u8,
len: u32,
}
impl std::fmt::Debug for TextValue {
@ -168,22 +168,27 @@ impl TextValue {
}
}
pub fn from_value(value: &Value) -> Option<&Self> {
/// # Safety
/// Safe to call if the pointer is null, returns None
/// if the value is not a text type or if the value is null
pub unsafe fn from_value(value: &Value) -> Option<&Self> {
if value.value_type != ValueType::Text {
return None;
}
unsafe { Some(&*(value.value as *const TextValue)) }
if value.value.is_null() {
return None;
}
Some(&*(value.value as *const TextValue))
}
/// # Safety
/// The caller must ensure that the text is a valid UTF-8 string
/// If self.text is null we safely return an empty string but
/// the caller must ensure that the underlying value is valid utf8
pub unsafe fn as_str(&self) -> &str {
if self.text.is_null() {
return "";
}
unsafe {
std::str::from_utf8_unchecked(std::slice::from_raw_parts(self.text, self.len as usize))
}
std::str::from_utf8_unchecked(std::slice::from_raw_parts(self.text, self.len as usize))
}
}
@ -258,7 +263,11 @@ impl Value {
}
}
pub unsafe fn free(&mut self) {
/// # Safety
/// consumes the value while freeing the underlying memory with null check.
/// however this does assume that the type was properly constructed with
/// the appropriate value_type and value.
pub unsafe fn free(self) {
if self.value.is_null() {
return;
}
@ -277,7 +286,5 @@ impl Value {
}
ValueType::Null => {}
}
self.value = std::ptr::null_mut();
}
}