0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-25 15:29:43 -05:00

feat: Add string access methods to OneByteConst (#1409)

This commit is contained in:
Matt Mastracci 2024-03-01 10:55:02 -07:00 committed by GitHub
parent 63eea06a9a
commit be545b7d3d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 17 deletions

View file

@ -119,13 +119,34 @@ pub struct ExternalStringResource(Opaque);
pub struct ExternalOneByteStringResourceBase(Opaque); pub struct ExternalOneByteStringResourceBase(Opaque);
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Copy, Clone, Debug)]
pub struct OneByteConst { pub struct OneByteConst {
vtable: *const OneByteConstNoOp, vtable: *const OneByteConstNoOp,
cached_data: *const char, cached_data: *const char,
length: usize, length: usize,
} }
impl AsRef<str> for OneByteConst {
fn as_ref(&self) -> &str {
// SAFETY: We know this is ASCII
unsafe { std::str::from_utf8_unchecked(AsRef::<[u8]>::as_ref(self)) }
}
}
impl AsRef<[u8]> for OneByteConst {
fn as_ref(&self) -> &[u8] {
// SAFETY: Returning to the slice from which this came
unsafe { std::slice::from_raw_parts(self.cached_data as _, self.length) }
}
}
impl std::ops::Deref for OneByteConst {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
// SAFETY: The vtable for OneByteConst is an immutable static and all // SAFETY: The vtable for OneByteConst is an immutable static and all
// of the included functions are thread-safe, the cached_data pointer // of the included functions are thread-safe, the cached_data pointer
// is never changed and points to a static ASCII string, and the // is never changed and points to a static ASCII string, and the
@ -201,19 +222,6 @@ const ONE_BYTE_CONST_VTABLE: OneByteConstVtable = OneByteConstVtable {
length: one_byte_const_length, length: one_byte_const_length,
}; };
/// Compile-time function to determine if a string is ASCII. Note that UTF-8 chars
/// longer than one byte have the high-bit set and thus, are not ASCII.
const fn is_ascii(s: &'static [u8]) -> bool {
let mut i = 0;
while i < s.len() {
if !s[i].is_ascii() {
return false;
}
i += 1;
}
true
}
#[repr(C)] #[repr(C)]
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub enum NewStringType { pub enum NewStringType {
@ -456,15 +464,28 @@ impl String {
Self::new_from_utf8(scope, value.as_ref(), NewStringType::Normal) Self::new_from_utf8(scope, value.as_ref(), NewStringType::Normal)
} }
// Compile-time function to create an external string resource. /// Compile-time function to create an external string resource.
// The buffer is checked to contain only ASCII characters. /// The buffer is checked to contain only ASCII characters.
#[inline(always)] #[inline(always)]
pub const fn create_external_onebyte_const( pub const fn create_external_onebyte_const(
buffer: &'static [u8], buffer: &'static [u8],
) -> OneByteConst { ) -> OneByteConst {
// Assert that the buffer contains only ASCII, and that the // Assert that the buffer contains only ASCII, and that the
// length is less or equal to (64-bit) v8::String::kMaxLength. // length is less or equal to (64-bit) v8::String::kMaxLength.
assert!(is_ascii(buffer) && buffer.len() <= ((1 << 29) - 24)); assert!(buffer.is_ascii() && buffer.len() <= ((1 << 29) - 24));
OneByteConst {
vtable: &ONE_BYTE_CONST_VTABLE.delete1,
cached_data: buffer.as_ptr() as *const char,
length: buffer.len(),
}
}
/// Compile-time function to create an external string resource which
/// skips the ASCII and length checks.
#[inline(always)]
pub const unsafe fn create_external_onebyte_const_unchecked(
buffer: &'static [u8],
) -> OneByteConst {
OneByteConst { OneByteConst {
vtable: &ONE_BYTE_CONST_VTABLE.delete1, vtable: &ONE_BYTE_CONST_VTABLE.delete1,
cached_data: buffer.as_ptr() as *const char, cached_data: buffer.as_ptr() as *const char,

View file

@ -9000,6 +9000,7 @@ fn external_strings() {
assert!(latin1.contains_only_onebyte()); assert!(latin1.contains_only_onebyte());
// one-byte "const" test // one-byte "const" test
assert_eq!(EXAMPLE_STRING.as_bytes(), b"const static");
let const_ref_string = let const_ref_string =
v8::String::new_from_onebyte_const(scope, &EXAMPLE_STRING).unwrap(); v8::String::new_from_onebyte_const(scope, &EXAMPLE_STRING).unwrap();
assert!(const_ref_string.is_external()); assert!(const_ref_string.is_external());