diff --git a/src/v8/inspector/channel.rs b/src/v8/inspector/channel.rs deleted file mode 100644 index 2bb55277..00000000 --- a/src/v8/inspector/channel.rs +++ /dev/null @@ -1,268 +0,0 @@ -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 message) = 0; -// virtual void sendNotification(std::unique_ptr message) = 0; -// virtual void flushProtocolNotifications() = 0; -// }; - -extern "C" { - fn v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT( - buf: &mut std::mem::MaybeUninit, - ) -> (); - - fn v8_inspector__V8Inspector__Channel__sendResponse( - this: &mut Channel, - call_id: int, - message: UniquePtr, - ) -> (); - fn v8_inspector__V8Inspector__Channel__sendNotification( - this: &mut Channel, - message: UniquePtr, - ) -> (); - 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, -) { - 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, -) { - 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, - ) { - unsafe { - v8_inspector__V8Inspector__Channel__sendResponse(self, call_id, message) - } - } - pub fn send_notification(&mut self, message: UniquePtr) { - 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 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, - ) -> (); - fn send_notification(&mut self, message: UniquePtr) -> (); - fn flush_protocol_notifications(&mut self) -> (); -} - -pub struct ChannelBase { - cxx_base: Channel, - offset_within_embedder: FieldOffset, - rust_vtable: RustVTable<&'static dyn ChannelImpl>, -} - -impl ChannelBase { - fn construct_cxx_base() -> Channel { - unsafe { - let mut buf = std::mem::MaybeUninit::::uninit(); - v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(&mut buf); - buf.assume_init() - } - } - - fn get_cxx_base_offset() -> FieldOffset { - let buf = std::mem::MaybeUninit::::uninit(); - FieldOffset::from_ptrs(buf.as_ptr(), unsafe { &(*buf.as_ptr()).cxx_base }) - } - - fn get_offset_within_embedder() -> FieldOffset - where - T: ChannelImpl, - { - let buf = std::mem::MaybeUninit::::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() -> RustVTable<&'static dyn ChannelImpl> - where - T: ChannelImpl, - { - let buf = std::mem::MaybeUninit::::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() -> Self - where - T: ChannelImpl, - { - Self { - cxx_base: Self::construct_cxx_base(), - offset_within_embedder: Self::get_offset_within_embedder::(), - rust_vtable: Self::get_rust_vtable::(), - } - } - - pub unsafe fn dispatch(channel: &Channel) -> &dyn ChannelImpl { - let this = Self::get_cxx_base_offset().to_embedder::(channel); - let embedder = this.offset_within_embedder.to_embedder::(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::(channel); - let vtable = this.rust_vtable; - let embedder = this.offset_within_embedder.to_embedder_mut::(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, - ) { - 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) { - 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::(), - 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); - } -} diff --git a/src/v8/string_buffer.rs b/src/v8/string_buffer.rs deleted file mode 100644 index 2034cd80..00000000 --- a/src/v8/string_buffer.rs +++ /dev/null @@ -1,76 +0,0 @@ -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 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` 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; -} - -#[repr(C)] -#[derive(Debug)] -pub struct StringBuffer { - _cxx_vtable: CxxVTable, -} - -// TODO: make it possible to obtain a `UniquePtr` directly from -// an owned `Vec` or `Vec`, -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`. - pub fn string(&mut self) -> &StringView { - unsafe { v8_inspector__StringBuffer__string(self) } - } - - /// This method copies contents. - pub fn create(source: &StringView) -> UniquePtr { - 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); - } - } -}