Skip to content

Commit 65d503d

Browse files
impl TextData
1 parent f3133ac commit 65d503d

File tree

1 file changed

+52
-36
lines changed

1 file changed

+52
-36
lines changed

pgrx/src/text.rs

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use crate::{pg_sys, varlena};
88
use alloc::borrow::Cow;
99
use alloc::string::String;
1010
use core::borrow::Borrow;
11-
use core::{ptr, slice, str};
11+
use core::ops::{Deref, DerefMut};
12+
use core::{ptr, str};
1213

1314
use bstr::{BStr, ByteSlice};
1415

@@ -24,44 +25,33 @@ pub use core::str::{Utf8Chunks, Utf8Error};
2425
#[repr(transparent)]
2526
pub struct Text([u8]);
2627

27-
// API decision: we could deref to TextData and move some fn to TextData so it can be returned from
28-
// `split_at`, `trim`, etc., and thus preserve conveniences that [u8] doesn't have?
28+
/// Data field of a TEXT varlena
29+
#[repr(transparent)]
30+
pub struct TextData([u8]);
31+
32+
impl TextData {
33+
/// Reborrow `&Text as `&BStr`
34+
///
35+
/// We do not implement Deref to BStr or [u8] because we'd like to expose a more selective API.
36+
/// Several fn that [u8] implements are implemented very differently on str, and we would like
37+
/// the API of Text to "feel like" that of str in most cases.
38+
fn as_bstr(&self) -> &BStr {
39+
self.as_bytes().borrow()
40+
}
2941

30-
impl Text {
3142
/// Obtain a reference to the Text's data as bytes
3243
pub fn as_bytes(&self) -> &[u8] {
33-
let self_ptr = self as *const Text as *const pg_sys::varlena;
34-
unsafe {
35-
let len = varlena::varsize_any_exhdr(self_ptr);
36-
let data = varlena::vardata_any(self_ptr);
37-
38-
slice::from_raw_parts(data.cast::<u8>(), len)
39-
}
44+
&self.0
4045
}
4146

42-
/// Obtain a mutable reference the Text's data as bytes
47+
/// Obtain a mutable reference to the Text's data as bytes
4348
///
4449
/// # Safety
4550
/// Like [`str::as_bytes_mut`], this can cause problems if you change Text in a way that
4651
/// your database is not specified to support, so the caller must assure that it remains in
4752
/// a valid encoding for the database.
4853
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
49-
let self_ptr = self as *mut Text as *mut pg_sys::varlena;
50-
unsafe {
51-
let len = varlena::varsize_any_exhdr(self_ptr);
52-
let data = varlena::vardata_any(self_ptr);
53-
54-
slice::from_raw_parts_mut(data.cast::<u8>().cast_mut(), len)
55-
}
56-
}
57-
58-
/// Reborrow `&Text as `&BStr`
59-
///
60-
/// We do not implement Deref to BStr or [u8] because we'd like to expose a more selective API.
61-
/// Several fn that [u8] implements are implemented very differently on str, and we would like
62-
/// the API of Text to "feel like" that of str in most cases.
63-
fn as_bstr(&self) -> &BStr {
64-
self.as_bytes().borrow()
54+
&mut self.0
6555
}
6656

6757
/// Iterate over the UTF-8 characters of this Text
@@ -81,22 +71,17 @@ impl Text {
8171
self.as_bytes().is_ascii()
8272
}
8373

84-
/// Is the varlena larger than its header?
74+
/// Is this slice nonzero len?
8575
pub fn is_empty(&self) -> bool {
8676
self.as_bytes().is_empty()
8777
}
8878

8979
/// Length of the data in bytes
90-
pub fn len_data(&self) -> usize {
80+
pub fn len(&self) -> usize {
9181
self.as_bytes().len()
9282
}
9383

94-
/// Length of the entire varlena in bytes
95-
pub fn len_full(&self) -> usize {
96-
self.0.len()
97-
}
98-
99-
/// Obtain a reference to the varlena data if it is a UTF-8 str
84+
/// Obtain a reference to the data if it is a UTF-8 str
10085
pub fn to_str(&self) -> Result<&str, Utf8Error> {
10186
str::from_utf8(self.as_bytes())
10287
}
@@ -114,6 +99,37 @@ impl Text {
11499
}
115100
}
116101

102+
impl Text {
103+
/// Length of the entire varlena in bytes
104+
pub fn va_len(&self) -> usize {
105+
self.0.len()
106+
}
107+
}
108+
109+
impl Deref for Text {
110+
type Target = TextData;
111+
fn deref(&self) -> &Self::Target {
112+
let self_ptr = self as *const Text as *const pg_sys::varlena;
113+
unsafe { &*varlena_to_text_data(self_ptr.cast_mut()) }
114+
}
115+
}
116+
117+
impl DerefMut for Text {
118+
fn deref_mut(&mut self) -> &mut Self::Target {
119+
let self_ptr = self as *mut Text as *mut pg_sys::varlena;
120+
unsafe { &mut *varlena_to_text_data(self_ptr) }
121+
}
122+
}
123+
124+
unsafe fn varlena_to_text_data(vptr: *mut pg_sys::varlena) -> *mut TextData {
125+
unsafe {
126+
let len = varlena::varsize_any_exhdr(vptr);
127+
let data = varlena::vardata_any(vptr).cast_mut();
128+
129+
ptr::slice_from_raw_parts_mut(data.cast::<u8>(), len) as *mut TextData
130+
}
131+
}
132+
117133
unsafe impl BorrowDatum for Text {
118134
const PASS: PassBy = PassBy::Ref;
119135
unsafe fn point_from(ptr: ptr::NonNull<u8>) -> ptr::NonNull<Self> {

0 commit comments

Comments
 (0)