Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
mmastrac committed Mar 1, 2024
1 parent 3c6a5c1 commit 4e9ba6b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 18 deletions.
53 changes: 37 additions & 16 deletions src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,27 @@ pub struct OneByteConst {
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
// of the included functions are thread-safe, the cached_data pointer
// is never changed and points to a static ASCII string, and the
Expand Down Expand Up @@ -201,19 +222,6 @@ const ONE_BYTE_CONST_VTABLE: OneByteConstVtable = OneByteConstVtable {
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)]
#[derive(Debug, Default)]
pub enum NewStringType {
Expand Down Expand Up @@ -456,15 +464,28 @@ impl String {
Self::new_from_utf8(scope, value.as_ref(), NewStringType::Normal)
}

// Compile-time function to create an external string resource.
// The buffer is checked to contain only ASCII characters.
/// Compile-time function to create an external string resource.
/// The buffer is checked to contain only ASCII characters.
#[inline(always)]
pub const fn create_external_onebyte_const(
buffer: &'static [u8],
) -> OneByteConst {
// Assert that the buffer contains only ASCII, and that the
// 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 {
vtable: &ONE_BYTE_CONST_VTABLE.delete1,
cached_data: buffer.as_ptr() as *const char,
Expand Down
6 changes: 4 additions & 2 deletions tests/test_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4211,7 +4211,7 @@ fn promise_hook() {
) {
// Check that PromiseHookType implements Clone and PartialEq.
_ = type_.clone() == v8::PromiseHookType::Init;

let scope = &mut unsafe { v8::CallbackScope::new(promise) };
let context = promise.get_creation_context(scope).unwrap();
let scope = &mut v8::ContextScope::new(scope, context);
Expand Down Expand Up @@ -5468,7 +5468,8 @@ fn snapshot_creator_multiple_contexts() {
fn external_references() {
let _setup_guard = setup::sequential_test();
// Allocate externals for the test.
let external_ptr = Box::into_raw(vec![0_u8, 1, 2, 3, 4].into_boxed_slice()) as *mut c_void;
let external_ptr =
Box::into_raw(vec![0_u8, 1, 2, 3, 4].into_boxed_slice()) as *mut c_void;
// Push them to the external reference table.
let refs = [
v8::ExternalReference {
Expand Down Expand Up @@ -8999,6 +9000,7 @@ fn external_strings() {
assert!(latin1.contains_only_onebyte());

// one-byte "const" test
assert_eq!(EXAMPLE_STRING.as_bytes(), b"const static");
let const_ref_string =
v8::String::new_from_onebyte_const(scope, &EXAMPLE_STRING).unwrap();
assert!(const_ref_string.is_external());
Expand Down

0 comments on commit 4e9ba6b

Please sign in to comment.