0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2025-01-12 09:04:02 -05:00
denoland-rusty-v8/src/string.rs

150 lines
3.6 KiB
Rust
Raw Normal View History

2019-12-04 02:03:17 -05:00
use std::convert::TryInto;
use std::default::Default;
use std::mem::forget;
2019-12-08 18:19:22 -05:00
use std::ops::Deref;
2019-12-04 02:03:17 -05:00
use std::slice;
use crate::isolate::Isolate;
2019-12-04 02:03:17 -05:00
use crate::support::char;
use crate::support::int;
use crate::support::Opaque;
use crate::Local;
2019-12-08 18:19:22 -05:00
use crate::Value;
2019-12-04 02:03:17 -05:00
extern "C" {
fn v8__String__NewFromUtf8(
2019-12-19 20:11:22 -05:00
isolate: &Isolate,
2019-12-04 02:03:17 -05:00
data: *const char,
new_type: NewStringType,
length: int,
2019-12-04 08:12:27 -05:00
) -> *mut String;
2019-12-04 02:03:17 -05:00
2019-12-05 12:28:20 -05:00
fn v8__String__Length(this: &String) -> int;
2019-12-19 20:11:22 -05:00
fn v8__String__Utf8Length(this: &String, isolate: &Isolate) -> int;
2019-12-04 02:03:17 -05:00
fn v8__String__WriteUtf8(
this: &String,
2019-12-19 20:11:22 -05:00
isolate: &Isolate,
2019-12-04 02:03:17 -05:00
buffer: *mut char,
length: int,
nchars_ref: *mut int,
options: WriteOptions,
) -> int;
}
#[repr(C)]
pub enum NewStringType {
Normal,
Internalized,
}
impl Default for NewStringType {
fn default() -> Self {
NewStringType::Normal
}
}
bitflags! {
#[derive(Default)]
#[repr(transparent)]
pub struct WriteOptions: int {
const NO_OPTIONS = 0;
const HINT_MANY_WRITES_EXPECTED = 1;
const NO_NULL_TERMINATION = 2;
const PRESERVE_ONE_BYTE_NULL = 4;
// Used by WriteUtf8 to replace orphan surrogate code units with the
// unicode replacement character. Needs to be set to guarantee valid UTF-8
// output.
const REPLACE_INVALID_UTF8 = 8;
}
}
2019-12-19 08:14:19 -05:00
/// A JavaScript string value (ECMA-262, 4.3.17).
2019-12-04 02:03:17 -05:00
#[repr(C)]
pub struct String(Opaque);
impl String {
pub fn new_from_utf8(
2019-12-19 20:11:22 -05:00
isolate: &Isolate,
2019-12-04 02:03:17 -05:00
buffer: &[u8],
new_type: NewStringType,
) -> Option<Local<String>> {
2019-12-04 02:03:17 -05:00
unsafe {
let ptr = v8__String__NewFromUtf8(
2019-12-19 20:11:22 -05:00
isolate,
2019-12-04 02:03:17 -05:00
buffer.as_ptr() as *const char,
new_type,
buffer.len().try_into().ok()?,
);
Local::from_raw(ptr)
}
}
2019-12-05 12:28:20 -05:00
/// Returns the number of characters (UTF-16 code units) in this string.
pub fn length(&self) -> usize {
unsafe { v8__String__Length(self) as usize }
}
/// Returns the number of bytes in the UTF-8 encoded representation of this
/// string.
2019-12-19 20:11:22 -05:00
pub fn utf8_length(&self, isolate: &Isolate) -> usize {
unsafe { v8__String__Utf8Length(self, isolate) as usize }
2019-12-04 02:03:17 -05:00
}
pub fn write_utf8(
&self,
2019-12-19 20:11:22 -05:00
isolate: &Isolate,
2019-12-04 02:03:17 -05:00
buffer: &mut [u8],
nchars_ref: Option<&mut usize>,
options: WriteOptions,
) -> usize {
let mut nchars_ref_int: int = 0;
let bytes = unsafe {
v8__String__WriteUtf8(
self,
2019-12-19 20:11:22 -05:00
isolate,
2019-12-04 02:03:17 -05:00
buffer.as_mut_ptr() as *mut char,
buffer.len().try_into().unwrap_or(int::max_value()),
&mut nchars_ref_int,
options,
)
};
if let Some(r) = nchars_ref {
*r = nchars_ref_int as usize;
}
bytes as usize
}
// Convenience function not present in the original V8 API.
pub fn new(
2019-12-19 20:11:22 -05:00
isolate: &Isolate,
2019-12-04 02:03:17 -05:00
value: &str,
new_type: NewStringType,
) -> Option<Local<String>> {
2019-12-19 20:11:22 -05:00
Self::new_from_utf8(isolate, value.as_ref(), new_type)
2019-12-04 02:03:17 -05:00
}
// Convenience function not present in the original V8 API.
2019-12-19 20:11:22 -05:00
pub fn to_rust_string_lossy(&self, isolate: &Isolate) -> std::string::String {
2019-12-04 02:03:17 -05:00
let capacity = self.utf8_length(isolate);
let mut string = std::string::String::with_capacity(capacity);
let data = string.as_mut_ptr();
forget(string);
let length = self.write_utf8(
isolate,
unsafe { slice::from_raw_parts_mut(data, capacity) },
None,
WriteOptions::NO_NULL_TERMINATION | WriteOptions::REPLACE_INVALID_UTF8,
);
unsafe { std::string::String::from_raw_parts(data, length, capacity) }
}
}
2019-12-08 18:19:22 -05:00
impl Deref for String {
type Target = Value;
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const _ as *const Value) }
}
}