mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-01-11 08:34:01 -05:00
WIP
This commit is contained in:
parent
5b9b9bcea1
commit
edebd3b10d
17 changed files with 454 additions and 79 deletions
|
@ -6,4 +6,3 @@ edition = "2018"
|
|||
|
||||
[build-dependencies]
|
||||
cc = "1.0.45"
|
||||
|
||||
|
|
8
build.rs
8
build.rs
|
@ -5,10 +5,10 @@ fn main() {
|
|||
.cpp(true)
|
||||
.flag("-std:c++17")
|
||||
.debug(true)
|
||||
.file("src/v8/inspector/channel.cpp")
|
||||
.file("src/v8/inspector/client.cpp")
|
||||
.file("src/v8/platform/task.cpp")
|
||||
.file("src/v8/string_buffer.cpp")
|
||||
.file("src/inspector/channel.cpp")
|
||||
.file("src/inspector/client.cpp")
|
||||
.file("src/platform/task.cpp")
|
||||
.file("src/string_buffer.cpp")
|
||||
.compile("v8-bindings");
|
||||
|
||||
println!("cargo:rustc-link-lib=static=v8_monolith");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "../../../v8/include/v8-inspector.h"
|
||||
#include "../../support.h"
|
||||
#include "../../v8/include/v8-inspector.h"
|
||||
#include "../support.h"
|
||||
|
||||
using namespace v8_inspector;
|
||||
using namespace support;
|
268
src/inspector/channel.rs
Normal file
268
src/inspector/channel.rs
Normal file
|
@ -0,0 +1,268 @@
|
|||
use crate::support::int;
|
||||
use crate::support::CxxVTable;
|
||||
use crate::support::FieldOffset;
|
||||
use crate::support::Opaque;
|
||||
use crate::support::RustVTable;
|
||||
use crate::support::UniquePtr;
|
||||
use crate::StringBuffer;
|
||||
|
||||
// class Channel {
|
||||
// public:
|
||||
// virtual ~Channel() = default;
|
||||
// virtual void sendResponse(int callId,
|
||||
// std::unique_ptr<StringBuffer> message) = 0;
|
||||
// virtual void sendNotification(std::unique_ptr<StringBuffer> message) = 0;
|
||||
// virtual void flushProtocolNotifications() = 0;
|
||||
// };
|
||||
|
||||
extern "C" {
|
||||
fn v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(
|
||||
buf: &mut std::mem::MaybeUninit<Channel>,
|
||||
) -> ();
|
||||
|
||||
fn v8_inspector__V8Inspector__Channel__sendResponse(
|
||||
this: &mut Channel,
|
||||
call_id: int,
|
||||
message: UniquePtr<StringBuffer>,
|
||||
) -> ();
|
||||
fn v8_inspector__V8Inspector__Channel__sendNotification(
|
||||
this: &mut Channel,
|
||||
message: UniquePtr<StringBuffer>,
|
||||
) -> ();
|
||||
fn v8_inspector__V8Inspector__Channel__flushProtocolNotifications(
|
||||
this: &mut Channel,
|
||||
) -> ();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn v8_inspector__V8Inspector__Channel__BASE__sendResponse(
|
||||
this: &mut Channel,
|
||||
call_id: int,
|
||||
message: UniquePtr<StringBuffer>,
|
||||
) {
|
||||
ChannelBase::dispatch_mut(this).send_response(call_id, message)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn v8_inspector__V8Inspector__Channel__BASE__sendNotification(
|
||||
this: &mut Channel,
|
||||
message: UniquePtr<StringBuffer>,
|
||||
) {
|
||||
ChannelBase::dispatch_mut(this).send_notification(message)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn v8_inspector__V8Inspector__Channel__BASE__flushProtocolNotifications(
|
||||
this: &mut Channel,
|
||||
) {
|
||||
ChannelBase::dispatch_mut(this).flush_protocol_notifications()
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Channel {
|
||||
_cxx_vtable: CxxVTable,
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
pub fn send_response(
|
||||
&mut self,
|
||||
call_id: int,
|
||||
message: UniquePtr<StringBuffer>,
|
||||
) {
|
||||
unsafe {
|
||||
v8_inspector__V8Inspector__Channel__sendResponse(self, call_id, message)
|
||||
}
|
||||
}
|
||||
pub fn send_notification(&mut self, message: UniquePtr<StringBuffer>) {
|
||||
unsafe {
|
||||
v8_inspector__V8Inspector__Channel__sendNotification(self, message)
|
||||
}
|
||||
}
|
||||
pub fn flush_protocol_notifications(&mut self) {
|
||||
unsafe {
|
||||
v8_inspector__V8Inspector__Channel__flushProtocolNotifications(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsChannel {
|
||||
fn as_channel(&self) -> &Channel;
|
||||
fn as_channel_mut(&mut self) -> &mut Channel;
|
||||
}
|
||||
|
||||
impl AsChannel for Channel {
|
||||
fn as_channel(&self) -> &Channel {
|
||||
self
|
||||
}
|
||||
fn as_channel_mut(&mut self) -> &mut Channel {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsChannel for T
|
||||
where
|
||||
T: ChannelImpl,
|
||||
{
|
||||
fn as_channel(&self) -> &Channel {
|
||||
&self.base().cxx_base
|
||||
}
|
||||
fn as_channel_mut(&mut self) -> &mut Channel {
|
||||
&mut self.base_mut().cxx_base
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ChannelImpl: AsChannel {
|
||||
fn base(&self) -> &ChannelBase;
|
||||
fn base_mut(&mut self) -> &mut ChannelBase;
|
||||
|
||||
fn send_response(
|
||||
&mut self,
|
||||
call_id: int,
|
||||
message: UniquePtr<StringBuffer>,
|
||||
) -> ();
|
||||
fn send_notification(&mut self, message: UniquePtr<StringBuffer>) -> ();
|
||||
fn flush_protocol_notifications(&mut self) -> ();
|
||||
}
|
||||
|
||||
pub struct ChannelBase {
|
||||
cxx_base: Channel,
|
||||
offset_within_embedder: FieldOffset<Self>,
|
||||
rust_vtable: RustVTable<&'static dyn ChannelImpl>,
|
||||
}
|
||||
|
||||
impl ChannelBase {
|
||||
fn construct_cxx_base() -> Channel {
|
||||
unsafe {
|
||||
let mut buf = std::mem::MaybeUninit::<Channel>::uninit();
|
||||
v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(&mut buf);
|
||||
buf.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cxx_base_offset() -> FieldOffset<Channel> {
|
||||
let buf = std::mem::MaybeUninit::<Self>::uninit();
|
||||
FieldOffset::from_ptrs(buf.as_ptr(), unsafe { &(*buf.as_ptr()).cxx_base })
|
||||
}
|
||||
|
||||
fn get_offset_within_embedder<T>() -> FieldOffset<Self>
|
||||
where
|
||||
T: ChannelImpl,
|
||||
{
|
||||
let buf = std::mem::MaybeUninit::<T>::uninit();
|
||||
let embedder_ptr: *const T = buf.as_ptr();
|
||||
let self_ptr: *const Self = unsafe { (*embedder_ptr).base() };
|
||||
FieldOffset::from_ptrs(embedder_ptr, self_ptr)
|
||||
}
|
||||
|
||||
fn get_rust_vtable<T>() -> RustVTable<&'static dyn ChannelImpl>
|
||||
where
|
||||
T: ChannelImpl,
|
||||
{
|
||||
let buf = std::mem::MaybeUninit::<T>::uninit();
|
||||
let embedder_ptr = buf.as_ptr();
|
||||
let trait_object: *const dyn ChannelImpl = embedder_ptr;
|
||||
let (data_ptr, vtable): (*const T, RustVTable<_>) =
|
||||
unsafe { std::mem::transmute(trait_object) };
|
||||
assert_eq!(data_ptr, embedder_ptr);
|
||||
vtable
|
||||
}
|
||||
|
||||
pub fn new<T>() -> Self
|
||||
where
|
||||
T: ChannelImpl,
|
||||
{
|
||||
Self {
|
||||
cxx_base: Self::construct_cxx_base(),
|
||||
offset_within_embedder: Self::get_offset_within_embedder::<T>(),
|
||||
rust_vtable: Self::get_rust_vtable::<T>(),
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dispatch(channel: &Channel) -> &dyn ChannelImpl {
|
||||
let this = Self::get_cxx_base_offset().to_embedder::<Self>(channel);
|
||||
let embedder = this.offset_within_embedder.to_embedder::<Opaque>(this);
|
||||
std::mem::transmute((embedder, this.rust_vtable))
|
||||
}
|
||||
|
||||
pub unsafe fn dispatch_mut(channel: &mut Channel) -> &mut dyn ChannelImpl {
|
||||
let this = Self::get_cxx_base_offset().to_embedder_mut::<Self>(channel);
|
||||
let vtable = this.rust_vtable;
|
||||
let embedder = this.offset_within_embedder.to_embedder_mut::<Opaque>(this);
|
||||
std::mem::transmute((embedder, vtable))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::support::UniquePtr;
|
||||
use crate::StringView;
|
||||
use crate::*;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
static MESSAGE: &[u8] = b"Hello Pluto!";
|
||||
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
// Using repr(C) to preserve field ordering and test that everything works
|
||||
// when the ChannelBase field is not the first element of the struct.
|
||||
#[repr(C)]
|
||||
pub struct TestChannel {
|
||||
field1: i32,
|
||||
base: ChannelBase,
|
||||
field2: u64,
|
||||
}
|
||||
|
||||
impl ChannelImpl for TestChannel {
|
||||
fn base(&self) -> &ChannelBase {
|
||||
&self.base
|
||||
}
|
||||
fn base_mut(&mut self) -> &mut ChannelBase {
|
||||
&mut self.base
|
||||
}
|
||||
fn send_response(
|
||||
&mut self,
|
||||
call_id: i32,
|
||||
mut message: UniquePtr<StringBuffer>,
|
||||
) {
|
||||
assert_eq!(call_id, 999);
|
||||
assert_eq!(message.as_mut().unwrap().string().len(), MESSAGE.len());
|
||||
self.log_call();
|
||||
}
|
||||
fn send_notification(&mut self, mut message: UniquePtr<StringBuffer>) {
|
||||
assert_eq!(message.as_mut().unwrap().string().len(), MESSAGE.len());
|
||||
self.log_call();
|
||||
}
|
||||
fn flush_protocol_notifications(&mut self) {
|
||||
self.log_call()
|
||||
}
|
||||
}
|
||||
|
||||
impl TestChannel {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base: ChannelBase::new::<Self>(),
|
||||
field1: -42,
|
||||
field2: 420,
|
||||
}
|
||||
}
|
||||
|
||||
fn log_call(&self) {
|
||||
assert_eq!(self.field1, -42);
|
||||
assert_eq!(self.field2, 420);
|
||||
CALL_COUNT.fetch_add(1, SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_channel() {
|
||||
let mut channel = TestChannel::new();
|
||||
let msg_view = StringView::from(MESSAGE);
|
||||
channel.send_response(999, StringBuffer::create(&msg_view));
|
||||
assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
|
||||
channel.send_notification(StringBuffer::create(&msg_view));
|
||||
assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
|
||||
channel.flush_protocol_notifications();
|
||||
assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#include "../../../v8/include/v8-inspector.h"
|
||||
#include "../../support.h"
|
||||
#include "../../v8/include/v8-inspector.h"
|
||||
#include "../support.h"
|
||||
|
||||
using namespace v8_inspector;
|
||||
using namespace support;
|
|
@ -1,7 +1,11 @@
|
|||
#![warn(clippy::all)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub mod inspector;
|
||||
pub mod platform;
|
||||
pub mod string_buffer;
|
||||
pub mod string_view;
|
||||
pub mod support;
|
||||
|
||||
pub use string_buffer::StringBuffer;
|
||||
pub use string_view::StringView;
|
64
src/main.rs
64
src/main.rs
|
@ -1,64 +0,0 @@
|
|||
#![warn(clippy::all)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod support;
|
||||
mod v8;
|
||||
|
||||
mod example {
|
||||
use crate::support::UniquePtr;
|
||||
use crate::v8::inspector::channel::*;
|
||||
use crate::v8::*;
|
||||
|
||||
// Using repr(C) to preserve field ordering and test that everything works
|
||||
// when the ChannelBase field is not the first element of the struct.
|
||||
#[repr(C)]
|
||||
pub struct TestChannel {
|
||||
field1: i32,
|
||||
base: ChannelBase,
|
||||
field2: f64,
|
||||
}
|
||||
|
||||
impl ChannelImpl for TestChannel {
|
||||
fn base(&self) -> &ChannelBase {
|
||||
&self.base
|
||||
}
|
||||
fn base_mut(&mut self) -> &mut ChannelBase {
|
||||
&mut self.base
|
||||
}
|
||||
fn send_response(
|
||||
&mut self,
|
||||
call_id: i32,
|
||||
mut message: UniquePtr<StringBuffer>,
|
||||
) {
|
||||
println!(
|
||||
"call_id: {:?}, message: '{:?}'",
|
||||
call_id,
|
||||
message.as_mut().unwrap().string().characters16().unwrap()
|
||||
);
|
||||
}
|
||||
fn send_notification(&mut self, _message: UniquePtr<StringBuffer>) {}
|
||||
fn flush_protocol_notifications(&mut self) {}
|
||||
}
|
||||
|
||||
impl TestChannel {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base: ChannelBase::new::<Self>(),
|
||||
field1: -42,
|
||||
field2: 4.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use crate::v8::inspector::channel::*;
|
||||
use crate::v8::*;
|
||||
use example::*;
|
||||
let mut ex = TestChannel::new();
|
||||
let chan = ex.as_channel_mut();
|
||||
let message: &[u8] = b"hello";
|
||||
let message = StringView::from(message);
|
||||
let message = StringBuffer::create(&message);
|
||||
chan.send_response(3, message);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#include "../../../v8/include/v8-platform.h"
|
||||
#include "../../support.h"
|
||||
#include "../../v8/include/v8-platform.h"
|
||||
#include "../support.h"
|
||||
|
||||
#include <iostream>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#include "../../v8/include/v8-inspector.h"
|
||||
#include "../support.h"
|
||||
#include "../v8/include/v8-inspector.h"
|
||||
#include "support.h"
|
||||
|
||||
using namespace v8_inspector;
|
||||
|
76
src/string_buffer.rs
Normal file
76
src/string_buffer.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use crate::support::CxxVTable;
|
||||
use crate::support::Delete;
|
||||
use crate::support::UniquePtr;
|
||||
use crate::StringView;
|
||||
|
||||
// class StringBuffer {
|
||||
// public:
|
||||
// virtual ~StringBuffer() = default;
|
||||
// virtual const StringView& string() = 0;
|
||||
// // This method copies contents.
|
||||
// static std::unique_ptr<StringBuffer> create(const StringView&);
|
||||
// };
|
||||
|
||||
// TODO: in C++, this class is intended to be user-extensible, just like
|
||||
// like `Task`, `Client`, `Channel`. In Rust this would ideally also be the
|
||||
// case, but currently to obtain a `UniquePtr<StringBuffer>` is by making a
|
||||
// copy using `StringBuffer::create()`.
|
||||
|
||||
extern "C" {
|
||||
fn v8_inspector__StringBuffer__DELETE(this: &'static mut StringBuffer) -> ();
|
||||
fn v8_inspector__StringBuffer__string(this: &mut StringBuffer)
|
||||
-> &StringView;
|
||||
fn v8_inspector__StringBuffer__create(
|
||||
source: &StringView,
|
||||
) -> UniquePtr<StringBuffer>;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct StringBuffer {
|
||||
_cxx_vtable: CxxVTable,
|
||||
}
|
||||
|
||||
// TODO: make it possible to obtain a `UniquePtr<StringBuffer>` directly from
|
||||
// an owned `Vec<u8>` or `Vec<u16>`,
|
||||
impl StringBuffer {
|
||||
// The C++ class definition does not declare `string()` to be a const method,
|
||||
// therefore we declare self as mutable here.
|
||||
// TODO: figure out whether it'd be safe to assume a const receiver here.
|
||||
// That would make it possible to implement `Deref<Target = StringBuffer>`.
|
||||
pub fn string(&mut self) -> &StringView {
|
||||
unsafe { v8_inspector__StringBuffer__string(self) }
|
||||
}
|
||||
|
||||
/// This method copies contents.
|
||||
pub fn create(source: &StringView) -> UniquePtr<StringBuffer> {
|
||||
unsafe { v8_inspector__StringBuffer__create(source) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Delete for StringBuffer {
|
||||
fn delete(&'static mut self) {
|
||||
unsafe { v8_inspector__StringBuffer__DELETE(self) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_string_buffer() {
|
||||
let chars = b"Hello Venus!";
|
||||
let mut buf = {
|
||||
let src_view = StringView::from(&chars[..]);
|
||||
StringBuffer::create(&src_view)
|
||||
};
|
||||
let view = buf.as_mut().unwrap().string();
|
||||
|
||||
assert_eq!(chars.len(), view.into_iter().len());
|
||||
assert_eq!(chars.len(), view.len());
|
||||
for (c1, c2) in chars.iter().copied().map(u16::from).zip(view) {
|
||||
assert_eq!(c1, c2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -71,6 +71,10 @@ impl<'a> StringView<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
Self::U16(v) => v.len(),
|
||||
|
@ -139,6 +143,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T> Send for CharacterArray<'a, T> where T: Copy {}
|
||||
unsafe impl<'a, T> Sync for CharacterArray<'a, T> where T: Sync {}
|
||||
|
||||
impl<'a, T> From<&'a [T]> for CharacterArray<'a, T> {
|
||||
fn from(v: &'a [T]) -> Self {
|
||||
Self {
|
|
@ -4,7 +4,7 @@ use crate::support::FieldOffset;
|
|||
use crate::support::Opaque;
|
||||
use crate::support::RustVTable;
|
||||
use crate::support::UniquePtr;
|
||||
use crate::v8::StringBuffer;
|
||||
use crate::StringBuffer;
|
||||
|
||||
// class Channel {
|
||||
// public:
|
||||
|
@ -191,3 +191,78 @@ impl ChannelBase {
|
|||
std::mem::transmute((embedder, vtable))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::support::UniquePtr;
|
||||
use crate::StringView;
|
||||
use crate::*;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
static MESSAGE: &[u8] = b"Hello Pluto!";
|
||||
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
// Using repr(C) to preserve field ordering and test that everything works
|
||||
// when the ChannelBase field is not the first element of the struct.
|
||||
#[repr(C)]
|
||||
pub struct TestChannel {
|
||||
field1: i32,
|
||||
base: ChannelBase,
|
||||
field2: u64,
|
||||
}
|
||||
|
||||
impl ChannelImpl for TestChannel {
|
||||
fn base(&self) -> &ChannelBase {
|
||||
&self.base
|
||||
}
|
||||
fn base_mut(&mut self) -> &mut ChannelBase {
|
||||
&mut self.base
|
||||
}
|
||||
fn send_response(
|
||||
&mut self,
|
||||
call_id: i32,
|
||||
mut message: UniquePtr<StringBuffer>,
|
||||
) {
|
||||
assert_eq!(call_id, 999);
|
||||
assert_eq!(message.as_mut().unwrap().string().len(), MESSAGE.len());
|
||||
self.log_call();
|
||||
}
|
||||
fn send_notification(&mut self, mut message: UniquePtr<StringBuffer>) {
|
||||
assert_eq!(message.as_mut().unwrap().string().len(), MESSAGE.len());
|
||||
self.log_call();
|
||||
}
|
||||
fn flush_protocol_notifications(&mut self) {
|
||||
self.log_call()
|
||||
}
|
||||
}
|
||||
|
||||
impl TestChannel {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base: ChannelBase::new::<Self>(),
|
||||
field1: -42,
|
||||
field2: 420,
|
||||
}
|
||||
}
|
||||
|
||||
fn log_call(&self) {
|
||||
assert_eq!(self.field1, -42);
|
||||
assert_eq!(self.field2, 420);
|
||||
CALL_COUNT.fetch_add(1, SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_channel() {
|
||||
let mut channel = TestChannel::new();
|
||||
let msg_view = StringView::from(MESSAGE);
|
||||
channel.send_response(999, StringBuffer::create(&msg_view));
|
||||
assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
|
||||
channel.send_notification(StringBuffer::create(&msg_view));
|
||||
assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
|
||||
channel.flush_protocol_notifications();
|
||||
assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::support::CxxVTable;
|
||||
use crate::support::Delete;
|
||||
use crate::support::UniquePtr;
|
||||
use crate::v8::StringView;
|
||||
use crate::StringView;
|
||||
|
||||
// class StringBuffer {
|
||||
// public:
|
||||
|
@ -11,6 +11,11 @@ use crate::v8::StringView;
|
|||
// static std::unique_ptr<StringBuffer> create(const StringView&);
|
||||
// };
|
||||
|
||||
// TODO: in C++, this class is intended to be user-extensible, just like
|
||||
// like `Task`, `Client`, `Channel`. In Rust this would ideally also be the
|
||||
// case, but currently to obtain a `UniquePtr<StringBuffer>` is by making a
|
||||
// copy using `StringBuffer::create()`.
|
||||
|
||||
extern "C" {
|
||||
fn v8_inspector__StringBuffer__DELETE(this: &'static mut StringBuffer) -> ();
|
||||
fn v8_inspector__StringBuffer__string(this: &mut StringBuffer)
|
||||
|
@ -26,13 +31,18 @@ pub struct StringBuffer {
|
|||
_cxx_vtable: CxxVTable,
|
||||
}
|
||||
|
||||
// TODO: make it possible to obtain a `UniquePtr<StringBuffer>` directly from
|
||||
// an owned `Vec<u8>` or `Vec<u16>`,
|
||||
impl StringBuffer {
|
||||
// The C++ class definition does not declare `string()` to be a const method,
|
||||
// therefore we declare self as mutable here.
|
||||
// TODO: figure out whether it'd be safe to assume a const receiver here.
|
||||
// That would make it possible to implement `Deref<Target = StringBuffer>`.
|
||||
pub fn string(&mut self) -> &StringView {
|
||||
unsafe { v8_inspector__StringBuffer__string(self) }
|
||||
}
|
||||
|
||||
/// This method copies contents.
|
||||
pub fn create(source: &StringView) -> UniquePtr<StringBuffer> {
|
||||
unsafe { v8_inspector__StringBuffer__create(source) }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue