mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-21 15:04:33 -05:00
feat: Fix is_onebyte and add an uninit write for onebyte (#1255)
Some fixes around one-byte strings: - `is_onebyte` was calling the wrong v8 API. - We didn't have a way to write one-byte strings with uninitialized buffers - (bonus) The test_string method was quite slow making testing a bit of a pain
This commit is contained in:
parent
b97dd1b1d8
commit
672254e113
2 changed files with 62 additions and 23 deletions
|
@ -258,6 +258,28 @@ impl String {
|
|||
}
|
||||
}
|
||||
|
||||
/// Writes the contents of the string to an external [`MaybeUninit`] buffer, as one-byte
|
||||
/// (Latin-1) characters.
|
||||
#[inline(always)]
|
||||
pub fn write_one_byte_uninit(
|
||||
&self,
|
||||
scope: &mut Isolate,
|
||||
buffer: &mut [MaybeUninit<u8>],
|
||||
start: usize,
|
||||
options: WriteOptions,
|
||||
) -> usize {
|
||||
unsafe {
|
||||
v8__String__WriteOneByte(
|
||||
self,
|
||||
scope,
|
||||
buffer.as_mut_ptr() as *mut u8,
|
||||
start.try_into().unwrap_or(int::max_value()),
|
||||
buffer.len().try_into().unwrap_or(int::max_value()),
|
||||
options,
|
||||
) as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the contents of the string to an external buffer, as UTF-8.
|
||||
#[inline(always)]
|
||||
pub fn write_utf8(
|
||||
|
@ -281,7 +303,7 @@ impl String {
|
|||
}
|
||||
}
|
||||
|
||||
/// Writes the contents of the string to an external buffer, as UTF-8.
|
||||
/// Writes the contents of the string to an external [`MaybeUninit`] buffer, as UTF-8.
|
||||
pub fn write_utf8_uninit(
|
||||
&self,
|
||||
scope: &mut Isolate,
|
||||
|
@ -378,16 +400,17 @@ impl String {
|
|||
unsafe { v8__String__IsExternalTwoByte(self) }
|
||||
}
|
||||
|
||||
/// True if string is known to contain only one-byte data.
|
||||
/// Doesn't read the string so can return false positives.
|
||||
/// Will return true if and only if string is known for certain to contain only one-byte data,
|
||||
/// ie: Latin-1, a.k.a. ISO-8859-1 code points. Doesn't read the string so can return false
|
||||
/// negatives, and a return value of false does not mean this string is not one-byte data.
|
||||
///
|
||||
/// For a method that will not return false positives at the cost of
|
||||
/// For a method that will not return false negatives at the cost of
|
||||
/// potentially reading the entire string, use [`contains_only_onebyte()`].
|
||||
///
|
||||
/// [`contains_only_onebyte()`]: String::contains_only_onebyte
|
||||
#[inline(always)]
|
||||
pub fn is_onebyte(&self) -> bool {
|
||||
unsafe { v8__String__IsExternalOneByte(self) }
|
||||
unsafe { v8__String__IsOneByte(self) }
|
||||
}
|
||||
|
||||
/// True if the string contains only one-byte data.
|
||||
|
|
|
@ -305,27 +305,35 @@ fn test_string() {
|
|||
}
|
||||
{
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
let buffer = (0..v8::String::max_length() / 4)
|
||||
.map(|_| '\u{10348}') // UTF8: 0xF0 0x90 0x8D 0x88
|
||||
.collect::<String>();
|
||||
let local = v8::String::new_from_utf8(
|
||||
scope,
|
||||
buffer.as_bytes(),
|
||||
v8::NewStringType::Normal,
|
||||
)
|
||||
.unwrap();
|
||||
let mut buffer = Vec::with_capacity(v8::String::max_length());
|
||||
for _ in 0..buffer.capacity() / 4 {
|
||||
// U+10348 in UTF-8
|
||||
buffer.push(0xF0_u8);
|
||||
buffer.push(0x90_u8);
|
||||
buffer.push(0x8D_u8);
|
||||
buffer.push(0x88_u8);
|
||||
}
|
||||
let local =
|
||||
v8::String::new_from_utf8(scope, &buffer, v8::NewStringType::Normal)
|
||||
.unwrap();
|
||||
// U+10348 is 2 UTF-16 code units, which is the unit of v8::String.length().
|
||||
assert_eq!(v8::String::max_length() / 2, local.length());
|
||||
assert_eq!(buffer, local.to_rust_string_lossy(scope));
|
||||
|
||||
let too_long = (0..(v8::String::max_length() / 4) + 1)
|
||||
.map(|_| '\u{10348}') // UTF8: 0xF0 0x90 0x8D 0x88
|
||||
.collect::<String>();
|
||||
let none = v8::String::new_from_utf8(
|
||||
scope,
|
||||
too_long.as_bytes(),
|
||||
v8::NewStringType::Normal,
|
||||
assert_eq!(
|
||||
buffer.as_slice(),
|
||||
local.to_rust_string_lossy(scope).as_bytes()
|
||||
);
|
||||
|
||||
let mut too_long = Vec::with_capacity(v8::String::max_length() + 4);
|
||||
for _ in 0..too_long.capacity() / 4 {
|
||||
// U+10348 in UTF-8
|
||||
too_long.push(0xF0_u8);
|
||||
too_long.push(0x90_u8);
|
||||
too_long.push(0x8D_u8);
|
||||
too_long.push(0x88_u8);
|
||||
}
|
||||
|
||||
let none =
|
||||
v8::String::new_from_utf8(scope, &too_long, v8::NewStringType::Normal);
|
||||
assert!(none.is_none());
|
||||
}
|
||||
{
|
||||
|
@ -8316,6 +8324,14 @@ fn external_strings() {
|
|||
assert!(!gradients.is_external_twobyte());
|
||||
assert!(!gradients.is_onebyte());
|
||||
assert!(!gradients.contains_only_onebyte());
|
||||
|
||||
// one-byte "internal" test
|
||||
let latin1 = v8::String::new(scope, "latin-1").unwrap();
|
||||
assert!(!latin1.is_external());
|
||||
assert!(!latin1.is_external_onebyte());
|
||||
assert!(!latin1.is_external_twobyte());
|
||||
assert!(latin1.is_onebyte());
|
||||
assert!(latin1.contains_only_onebyte());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue