feat: add String::ValueView (#1543)

This commit is contained in:
snek 2024-07-24 07:59:18 -07:00 committed by GitHub
parent 1e4b691905
commit 39631b31d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 130 additions and 7 deletions

View File

@ -1197,6 +1197,33 @@ bool v8__String__ContainsOnlyOneByte(const v8::String& self) {
return self.ContainsOnlyOneByte();
}
void v8__String__ValueView__CONSTRUCT(uninit_t<v8::String::ValueView>* buf,
v8::Isolate* isolate,
const v8::String& string) {
construct_in_place<v8::String::ValueView>(buf, isolate,
ptr_to_local(&string));
}
void v8__String__ValueView__DESTRUCT(v8::String::ValueView* self) {
self->~ValueView();
}
bool v8__String__ValueView__is_one_byte(const v8::String::ValueView& self) {
return self.is_one_byte();
}
const void* v8__String__ValueView__data(const v8::String::ValueView& self) {
if (self.is_one_byte()) {
return reinterpret_cast<const void*>(self.data8());
} else {
return reinterpret_cast<const void*>(self.data16());
}
}
int v8__String__ValueView__length(const v8::String::ValueView& self) {
return self.length();
}
const v8::Symbol* v8__Symbol__New(v8::Isolate* isolate,
const v8::String* description) {
return local_to_ptr(v8::Symbol::New(isolate, ptr_to_local(description)));

View File

@ -19,3 +19,5 @@ static size_t RUST_cppgc__WeakMember_SIZE = sizeof(cppgc::WeakMember<RustObj>);
static size_t RUST_v8__TracedReference_SIZE =
sizeof(v8::TracedReference<v8::Data>);
static size_t RUST_v8__String__ValueView_SIZE = sizeof(v8::String::ValueView);

View File

@ -149,6 +149,8 @@ pub use snapshot::StartupData;
pub use string::Encoding;
pub use string::NewStringType;
pub use string::OneByteConst;
pub use string::ValueView;
pub use string::ValueViewData;
pub use string::WriteOptions;
pub use support::SharedPtr;
pub use support::SharedRef;

View File

@ -1,10 +1,3 @@
use std::borrow::Cow;
use std::convert::TryInto;
use std::default::Default;
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use std::slice;
use crate::support::char;
use crate::support::int;
use crate::support::size_t;
@ -13,6 +6,14 @@ use crate::HandleScope;
use crate::Isolate;
use crate::Local;
use crate::String;
use std::borrow::Cow;
use std::convert::TryInto;
use std::default::Default;
use std::ffi::c_void;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use std::slice;
extern "C" {
fn v8__String__kMaxLength() -> size_t;
@ -116,6 +117,16 @@ extern "C" {
fn v8__ExternalOneByteStringResource__length(
this: *const ExternalOneByteStringResource,
) -> size_t;
fn v8__String__ValueView__CONSTRUCT(
buf: *mut ValueView,
isolate: *mut Isolate,
string: *const String,
);
fn v8__String__ValueView__DESTRUCT(this: *mut ValueView);
fn v8__String__ValueView__is_one_byte(this: *const ValueView) -> bool;
fn v8__String__ValueView__data(this: *const ValueView) -> *const c_void;
fn v8__String__ValueView__length(this: *const ValueView) -> int;
}
#[derive(PartialEq, Debug)]
@ -939,3 +950,53 @@ pub extern "C" fn free_rust_external_onebyte(s: *mut char, len: usize) {
drop(Box::from_raw(slice));
}
}
#[derive(Debug, PartialEq)]
pub enum ValueViewData<'s> {
OneByte(&'s [u8]),
TwoByte(&'s [u16]),
}
/// Returns a view onto a string's contents.
///
/// WARNING: This does not copy the string's contents, and will therefore be
/// invalidated if the GC can move the string while the ValueView is alive. It
/// is therefore required that no GC or allocation can happen while there is an
/// active ValueView. This requirement may be relaxed in the future.
///
/// V8 strings are either encoded as one-byte or two-bytes per character.
#[repr(C)]
pub struct ValueView<'s>(
[u8; crate::binding::RUST_v8__String__ValueView_SIZE],
PhantomData<&'s ()>,
);
impl<'s> ValueView<'s> {
#[inline(always)]
pub fn new(isolate: &mut Isolate, string: Local<'s, String>) -> Self {
let mut v = std::mem::MaybeUninit::uninit();
unsafe {
v8__String__ValueView__CONSTRUCT(v.as_mut_ptr(), isolate, &*string);
v.assume_init()
}
}
#[inline(always)]
pub fn data(&self) -> ValueViewData<'_> {
unsafe {
let data = v8__String__ValueView__data(self);
let length = v8__String__ValueView__length(self) as usize;
if v8__String__ValueView__is_one_byte(self) {
ValueViewData::OneByte(std::slice::from_raw_parts(data as _, length))
} else {
ValueViewData::TwoByte(std::slice::from_raw_parts(data as _, length))
}
}
}
}
impl<'s> Drop for ValueView<'s> {
fn drop(&mut self) {
unsafe { v8__String__ValueView__DESTRUCT(self) }
}
}

View File

@ -11779,3 +11779,34 @@ fn clear_slots_annex_uninitialized() {
// initialized.
context.clear_all_slots(&mut scope);
}
#[test]
fn string_valueview() {
let _setup_guard = setup::parallel_test();
let mut isolate = v8::Isolate::new(Default::default());
let mut scope = v8::HandleScope::new(&mut isolate);
let context = v8::Context::new(&mut scope);
let scope = &mut v8::ContextScope::new(&mut scope, context);
{
let one_byte = v8::String::new_from_one_byte(
scope,
&[1, 2, 3],
v8::NewStringType::Normal,
)
.unwrap();
let view = v8::ValueView::new(scope, one_byte);
assert_eq!(view.data(), v8::ValueViewData::OneByte(&[1, 2, 3]));
}
{
let two_byte = v8::String::new_from_two_byte(
scope,
&[1, 0x1FF, 3],
v8::NewStringType::Normal,
)
.unwrap();
let view = v8::ValueView::new(scope, two_byte);
assert_eq!(view.data(), v8::ValueViewData::TwoByte(&[1, 0x1FF, 3]));
}
}