1use crate::support::int;
17use crate::support::CxxVTable;
18use crate::support::FieldOffset;
19use crate::support::Opaque;
20use crate::support::RustVTable;
21use crate::support::UniquePtr;
22use crate::support::UniqueRef;
23use crate::Context;
24use crate::Isolate;
25use crate::Local;
26use std::fmt::{self, Debug, Formatter};
27
28extern "C" {
29 fn v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(
30 buf: &mut std::mem::MaybeUninit<Channel>,
31 );
32
33 fn v8_inspector__V8Inspector__Channel__sendResponse(
34 this: &mut Channel,
35 call_id: int,
36 message: UniquePtr<StringBuffer>,
37 );
38 fn v8_inspector__V8Inspector__Channel__sendNotification(
39 this: &mut Channel,
40 message: UniquePtr<StringBuffer>,
41 );
42 fn v8_inspector__V8Inspector__Channel__flushProtocolNotifications(
43 this: &mut Channel,
44 );
45
46 fn v8_inspector__V8InspectorClient__BASE__CONSTRUCT(
47 buf: &mut std::mem::MaybeUninit<V8InspectorClient>,
48 );
49
50 fn v8_inspector__V8InspectorClient__generateUniqueId(
51 this: &mut V8InspectorClient,
52 ) -> i64;
53 fn v8_inspector__V8InspectorClient__runMessageLoopOnPause(
54 this: &mut V8InspectorClient,
55 context_group_id: int,
56 );
57 fn v8_inspector__V8InspectorClient__quitMessageLoopOnPause(
58 this: &mut V8InspectorClient,
59 );
60 fn v8_inspector__V8InspectorClient__runIfWaitingForDebugger(
61 this: &mut V8InspectorClient,
62 context_group_id: int,
63 );
64 fn v8_inspector__V8InspectorClient__consoleAPIMessage(
65 this: &mut V8InspectorClient,
66 context_group_id: int,
67 level: int,
68 message: &StringView,
69 url: &StringView,
70 line_number: u32,
71 column_number: u32,
72 stack_trace: &mut V8StackTrace,
73 );
74
75 fn v8_inspector__V8InspectorSession__DELETE(this: &mut V8InspectorSession);
76 fn v8_inspector__V8InspectorSession__dispatchProtocolMessage(
77 session: *mut V8InspectorSession,
78 message: StringView,
79 );
80 fn v8_inspector__V8InspectorSession__schedulePauseOnNextStatement(
81 session: *mut V8InspectorSession,
82 break_reason: StringView,
83 break_details: StringView,
84 );
85 fn v8_inspector__V8InspectorSession__canDispatchMethod(
86 method: StringView,
87 ) -> bool;
88
89 fn v8_inspector__StringBuffer__DELETE(this: &mut StringBuffer);
90 fn v8_inspector__StringBuffer__string(this: &StringBuffer) -> StringView;
91 fn v8_inspector__StringBuffer__create(
92 source: StringView,
93 ) -> UniquePtr<StringBuffer>;
94
95 fn v8_inspector__V8Inspector__DELETE(this: &mut V8Inspector);
96 fn v8_inspector__V8Inspector__create(
97 isolate: *mut Isolate,
98 client: *mut V8InspectorClient,
99 ) -> *mut V8Inspector;
100 fn v8_inspector__V8Inspector__connect(
101 inspector: *mut V8Inspector,
102 context_group_id: int,
103 channel: *mut Channel,
104 state: StringView,
105 ) -> *mut V8InspectorSession;
106 fn v8_inspector__V8Inspector__contextCreated(
107 this: *mut V8Inspector,
108 context: *const Context,
109 contextGroupId: int,
110 humanReadableName: StringView,
111 );
112}
113
114#[no_mangle]
115pub unsafe extern "C" fn v8_inspector__V8Inspector__Channel__BASE__sendResponse(
116 this: &mut Channel,
117 call_id: int,
118 message: UniquePtr<StringBuffer>,
119) {
120 ChannelBase::dispatch_mut(this).send_response(call_id, message)
121}
122
123#[no_mangle]
124pub unsafe extern "C" fn v8_inspector__V8Inspector__Channel__BASE__sendNotification(
125 this: &mut Channel,
126 message: UniquePtr<StringBuffer>,
127) {
128 ChannelBase::dispatch_mut(this).send_notification(message)
129}
130
131#[no_mangle]
132pub unsafe extern "C" fn v8_inspector__V8Inspector__Channel__BASE__flushProtocolNotifications(
133 this: &mut Channel,
134) {
135 ChannelBase::dispatch_mut(this).flush_protocol_notifications()
136}
137
138#[no_mangle]
139pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__generateUniqueId(
140 this: &mut V8InspectorClient,
141) -> i64 {
142 V8InspectorClientBase::dispatch_mut(this).generate_unique_id()
143}
144
145#[no_mangle]
146pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__runMessageLoopOnPause(
147 this: &mut V8InspectorClient,
148 context_group_id: int,
149) {
150 V8InspectorClientBase::dispatch_mut(this)
151 .run_message_loop_on_pause(context_group_id)
152}
153
154#[no_mangle]
155pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__quitMessageLoopOnPause(
156 this: &mut V8InspectorClient,
157) {
158 V8InspectorClientBase::dispatch_mut(this).quit_message_loop_on_pause()
159}
160
161#[no_mangle]
162pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__runIfWaitingForDebugger(
163 this: &mut V8InspectorClient,
164 context_group_id: int,
165) {
166 V8InspectorClientBase::dispatch_mut(this)
167 .run_if_waiting_for_debugger(context_group_id)
168}
169
170#[no_mangle]
171pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__consoleAPIMessage(
172 this: &mut V8InspectorClient,
173 context_group_id: int,
174 level: int,
175 message: &StringView,
176 url: &StringView,
177 line_number: u32,
178 column_number: u32,
179 stack_trace: &mut V8StackTrace,
180) {
181 V8InspectorClientBase::dispatch_mut(this).console_api_message(
182 context_group_id,
183 level,
184 message,
185 url,
186 line_number,
187 column_number,
188 stack_trace,
189 )
190}
191
192#[repr(C)]
193#[derive(Debug)]
194pub struct Channel {
195 _cxx_vtable: CxxVTable,
196}
197
198impl Channel {
199 pub fn send_response(
200 &mut self,
201 call_id: i32,
202 message: UniquePtr<StringBuffer>,
203 ) {
204 unsafe {
205 v8_inspector__V8Inspector__Channel__sendResponse(self, call_id, message)
206 }
207 }
208 pub fn send_notification(&mut self, message: UniquePtr<StringBuffer>) {
209 unsafe {
210 v8_inspector__V8Inspector__Channel__sendNotification(self, message)
211 }
212 }
213 pub fn flush_protocol_notifications(&mut self) {
214 unsafe {
215 v8_inspector__V8Inspector__Channel__flushProtocolNotifications(self)
216 }
217 }
218}
219
220pub trait AsChannel {
221 fn as_channel(&self) -> &Channel;
222 fn as_channel_mut(&mut self) -> &mut Channel;
223}
224
225impl AsChannel for Channel {
226 fn as_channel(&self) -> &Channel {
227 self
228 }
229 fn as_channel_mut(&mut self) -> &mut Channel {
230 self
231 }
232}
233
234impl<T> AsChannel for T
235where
236 T: ChannelImpl,
237{
238 fn as_channel(&self) -> &Channel {
239 &self.base().cxx_base
240 }
241 fn as_channel_mut(&mut self) -> &mut Channel {
242 &mut self.base_mut().cxx_base
243 }
244}
245
246pub trait ChannelImpl: AsChannel {
247 fn base(&self) -> &ChannelBase;
248 fn base_mut(&mut self) -> &mut ChannelBase;
249
250 fn send_response(&mut self, call_id: i32, message: UniquePtr<StringBuffer>);
251 fn send_notification(&mut self, message: UniquePtr<StringBuffer>);
252 fn flush_protocol_notifications(&mut self);
253}
254
255pub struct ChannelBase {
256 cxx_base: Channel,
257 offset_within_embedder: FieldOffset<Self>,
258 rust_vtable: RustVTable<&'static dyn ChannelImpl>,
259}
260
261impl ChannelBase {
262 fn construct_cxx_base() -> Channel {
263 unsafe {
264 let mut buf = std::mem::MaybeUninit::<Channel>::uninit();
265 v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(&mut buf);
266 buf.assume_init()
267 }
268 }
269
270 fn get_cxx_base_offset() -> FieldOffset<Channel> {
271 let buf = std::mem::MaybeUninit::<Self>::uninit();
272 FieldOffset::from_ptrs(buf.as_ptr(), unsafe { &(*buf.as_ptr()).cxx_base })
273 }
274
275 fn get_offset_within_embedder<T>() -> FieldOffset<Self>
276 where
277 T: ChannelImpl,
278 {
279 let buf = std::mem::MaybeUninit::<T>::uninit();
280 let embedder_ptr: *const T = buf.as_ptr();
281 let self_ptr: *const Self = unsafe { (*embedder_ptr).base() };
282 FieldOffset::from_ptrs(embedder_ptr, self_ptr)
283 }
284
285 fn get_rust_vtable<T>() -> RustVTable<&'static dyn ChannelImpl>
286 where
287 T: ChannelImpl,
288 {
289 let buf = std::mem::MaybeUninit::<T>::uninit();
290 let embedder_ptr = buf.as_ptr();
291 let trait_object: *const dyn ChannelImpl = embedder_ptr;
292 let (data_ptr, vtable): (*const T, RustVTable<_>) =
293 unsafe { std::mem::transmute(trait_object) };
294 assert_eq!(data_ptr, embedder_ptr);
295 vtable
296 }
297
298 pub fn new<T>() -> Self
299 where
300 T: ChannelImpl,
301 {
302 Self {
303 cxx_base: Self::construct_cxx_base(),
304 offset_within_embedder: Self::get_offset_within_embedder::<T>(),
305 rust_vtable: Self::get_rust_vtable::<T>(),
306 }
307 }
308
309 pub unsafe fn dispatch(channel: &Channel) -> &dyn ChannelImpl {
310 let this = Self::get_cxx_base_offset().to_embedder::<Self>(channel);
311 let embedder = this.offset_within_embedder.to_embedder::<Opaque>(this);
312 std::mem::transmute((embedder, this.rust_vtable))
313 }
314
315 pub unsafe fn dispatch_mut(channel: &mut Channel) -> &mut dyn ChannelImpl {
316 let this = Self::get_cxx_base_offset().to_embedder_mut::<Self>(channel);
317 let vtable = this.rust_vtable;
318 let embedder = this.offset_within_embedder.to_embedder_mut::<Opaque>(this);
319 std::mem::transmute((embedder, vtable))
320 }
321}
322
323impl Debug for ChannelBase {
324 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
325 f.debug_struct("ChannelBase")
326 .field("cxx_base", &self.cxx_base)
327 .field("offset_within_embedder", &self.offset_within_embedder)
328 .finish()
329 }
330}
331
332#[cfg(test)]
333mod tests {
334 use super::*;
335 use crate::support::UniquePtr;
336 use std::sync::atomic::AtomicUsize;
337 use std::sync::atomic::Ordering::SeqCst;
338
339 static MESSAGE: &[u8] = b"Hello Pluto!";
340 static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
341
342 #[repr(C)]
345 #[derive(Debug)]
346 pub struct TestChannel {
347 field1: i32,
348 base: ChannelBase,
349 field2: u64,
350 }
351
352 impl ChannelImpl for TestChannel {
353 fn base(&self) -> &ChannelBase {
354 &self.base
355 }
356 fn base_mut(&mut self) -> &mut ChannelBase {
357 &mut self.base
358 }
359 fn send_response(
360 &mut self,
361 call_id: i32,
362 mut message: UniquePtr<StringBuffer>,
363 ) {
364 assert_eq!(call_id, 999);
365 assert_eq!(message.as_mut().unwrap().string().len(), MESSAGE.len());
366 self.log_call();
367 }
368 fn send_notification(&mut self, mut message: UniquePtr<StringBuffer>) {
369 assert_eq!(message.as_mut().unwrap().string().len(), MESSAGE.len());
370 self.log_call();
371 }
372 fn flush_protocol_notifications(&mut self) {
373 self.log_call()
374 }
375 }
376
377 impl TestChannel {
378 pub fn new() -> Self {
379 Self {
380 base: ChannelBase::new::<Self>(),
381 field1: -42,
382 field2: 420,
383 }
384 }
385
386 fn log_call(&self) {
387 assert_eq!(self.field1, -42);
388 assert_eq!(self.field2, 420);
389 CALL_COUNT.fetch_add(1, SeqCst);
390 }
391 }
392
393 #[test]
394 fn test_channel() {
395 let mut channel = TestChannel::new();
396 let msg_view = StringView::from(MESSAGE);
397 channel.send_response(999, StringBuffer::create(msg_view));
398 assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
399 channel.send_notification(StringBuffer::create(msg_view));
400 assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
401 channel.flush_protocol_notifications();
402 assert_eq!(CALL_COUNT.swap(0, SeqCst), 1);
403 }
404}
405
406#[repr(C)]
407#[derive(Debug)]
408pub struct V8InspectorClient {
409 _cxx_vtable: CxxVTable,
410}
411
412impl V8InspectorClient {
413 pub fn run_message_loop_on_pause(&mut self, context_group_id: i32) {
414 unsafe {
415 v8_inspector__V8InspectorClient__runMessageLoopOnPause(
416 self,
417 context_group_id,
418 )
419 }
420 }
421
422 pub fn quit_message_loop_on_pause(&mut self) {
423 unsafe { v8_inspector__V8InspectorClient__quitMessageLoopOnPause(self) }
424 }
425
426 pub fn run_if_waiting_for_debugger(&mut self, context_group_id: i32) {
427 unsafe {
428 v8_inspector__V8InspectorClient__runIfWaitingForDebugger(
429 self,
430 context_group_id,
431 )
432 }
433 }
434
435 #[allow(clippy::too_many_arguments)]
436 pub fn console_api_message(
437 &mut self,
438 context_group_id: i32,
439 level: i32,
440 message: &StringView,
441 url: &StringView,
442 line_number: u32,
443 column_number: u32,
444 stack_trace: &mut V8StackTrace,
445 ) {
446 unsafe {
447 v8_inspector__V8InspectorClient__consoleAPIMessage(
448 self,
449 context_group_id,
450 level,
451 message,
452 url,
453 line_number,
454 column_number,
455 stack_trace,
456 )
457 }
458 }
459
460 pub fn generate_unique_id(&mut self) -> i64 {
461 unsafe { v8_inspector__V8InspectorClient__generateUniqueId(self) }
462 }
463}
464
465pub trait AsV8InspectorClient {
466 fn as_client(&self) -> &V8InspectorClient;
467 fn as_client_mut(&mut self) -> &mut V8InspectorClient;
468}
469
470impl AsV8InspectorClient for V8InspectorClient {
471 fn as_client(&self) -> &V8InspectorClient {
472 self
473 }
474 fn as_client_mut(&mut self) -> &mut V8InspectorClient {
475 self
476 }
477}
478
479impl<T> AsV8InspectorClient for T
480where
481 T: V8InspectorClientImpl,
482{
483 fn as_client(&self) -> &V8InspectorClient {
484 &self.base().cxx_base
485 }
486 fn as_client_mut(&mut self) -> &mut V8InspectorClient {
487 &mut self.base_mut().cxx_base
488 }
489}
490
491#[allow(unused_variables)]
492pub trait V8InspectorClientImpl: AsV8InspectorClient {
493 fn base(&self) -> &V8InspectorClientBase;
494 fn base_mut(&mut self) -> &mut V8InspectorClientBase;
495
496 fn run_message_loop_on_pause(&mut self, context_group_id: i32) {}
497 fn quit_message_loop_on_pause(&mut self) {}
498 fn run_if_waiting_for_debugger(&mut self, context_group_id: i32) {}
499
500 fn generate_unique_id(&mut self) -> i64 {
501 0 }
503
504 #[allow(clippy::too_many_arguments)]
505 fn console_api_message(
506 &mut self,
507 context_group_id: i32,
508 level: i32,
509 message: &StringView,
510 url: &StringView,
511 line_number: u32,
512 column_number: u32,
513 stack_trace: &mut V8StackTrace,
514 ) {
515 }
516}
517
518pub struct V8InspectorClientBase {
519 cxx_base: V8InspectorClient,
520 offset_within_embedder: FieldOffset<Self>,
521 rust_vtable: RustVTable<&'static dyn V8InspectorClientImpl>,
522}
523
524impl V8InspectorClientBase {
525 fn construct_cxx_base() -> V8InspectorClient {
526 unsafe {
527 let mut buf = std::mem::MaybeUninit::<V8InspectorClient>::uninit();
528 v8_inspector__V8InspectorClient__BASE__CONSTRUCT(&mut buf);
529 buf.assume_init()
530 }
531 }
532
533 fn get_cxx_base_offset() -> FieldOffset<V8InspectorClient> {
534 let buf = std::mem::MaybeUninit::<Self>::uninit();
535 FieldOffset::from_ptrs(buf.as_ptr(), unsafe { &(*buf.as_ptr()).cxx_base })
536 }
537
538 fn get_offset_within_embedder<T>() -> FieldOffset<Self>
539 where
540 T: V8InspectorClientImpl,
541 {
542 let buf = std::mem::MaybeUninit::<T>::uninit();
543 let embedder_ptr: *const T = buf.as_ptr();
544 let self_ptr: *const Self = unsafe { (*embedder_ptr).base() };
545 FieldOffset::from_ptrs(embedder_ptr, self_ptr)
546 }
547
548 fn get_rust_vtable<T>() -> RustVTable<&'static dyn V8InspectorClientImpl>
549 where
550 T: V8InspectorClientImpl,
551 {
552 let buf = std::mem::MaybeUninit::<T>::uninit();
553 let embedder_ptr = buf.as_ptr();
554 let trait_object: *const dyn V8InspectorClientImpl = embedder_ptr;
555 let (data_ptr, vtable): (*const T, RustVTable<_>) =
556 unsafe { std::mem::transmute(trait_object) };
557 assert_eq!(data_ptr, embedder_ptr);
558 vtable
559 }
560
561 pub fn new<T>() -> Self
562 where
563 T: V8InspectorClientImpl,
564 {
565 Self {
566 cxx_base: Self::construct_cxx_base(),
567 offset_within_embedder: Self::get_offset_within_embedder::<T>(),
568 rust_vtable: Self::get_rust_vtable::<T>(),
569 }
570 }
571
572 pub unsafe fn dispatch(
573 client: &V8InspectorClient,
574 ) -> &dyn V8InspectorClientImpl {
575 let this = Self::get_cxx_base_offset().to_embedder::<Self>(client);
576 let embedder = this.offset_within_embedder.to_embedder::<Opaque>(this);
577 std::mem::transmute((embedder, this.rust_vtable))
578 }
579
580 pub unsafe fn dispatch_mut(
581 client: &mut V8InspectorClient,
582 ) -> &mut dyn V8InspectorClientImpl {
583 let this = Self::get_cxx_base_offset().to_embedder_mut::<Self>(client);
584 let vtable = this.rust_vtable;
585 let embedder = this.offset_within_embedder.to_embedder_mut::<Opaque>(this);
586 std::mem::transmute((embedder, vtable))
587 }
588}
589
590impl Debug for V8InspectorClientBase {
591 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
592 f.debug_struct("V8InspectorClientBase")
593 .field("cxx_base", &self.cxx_base)
594 .field("offset_within_embedder", &self.offset_within_embedder)
595 .finish()
596 }
597}
598
599#[repr(C)]
600#[derive(Debug)]
601pub struct V8InspectorSession(Opaque);
602
603impl V8InspectorSession {
604 pub fn can_dispatch_method(method: StringView) -> bool {
605 unsafe { v8_inspector__V8InspectorSession__canDispatchMethod(method) }
606 }
607
608 pub fn dispatch_protocol_message(&mut self, message: StringView) {
609 unsafe {
610 v8_inspector__V8InspectorSession__dispatchProtocolMessage(self, message)
611 }
612 }
613
614 pub fn schedule_pause_on_next_statement(
615 &mut self,
616 reason: StringView,
617 detail: StringView,
618 ) {
619 unsafe {
620 v8_inspector__V8InspectorSession__schedulePauseOnNextStatement(
621 self, reason, detail,
622 )
623 }
624 }
625}
626
627impl Drop for V8InspectorSession {
628 fn drop(&mut self) {
629 unsafe { v8_inspector__V8InspectorSession__DELETE(self) };
630 }
631}
632
633#[repr(C)]
638#[derive(Debug)]
639pub struct StringBuffer {
640 _cxx_vtable: CxxVTable,
641}
642
643impl StringBuffer {
646 pub fn string(&self) -> StringView {
651 unsafe { v8_inspector__StringBuffer__string(self) }
652 }
653
654 pub fn create(source: StringView) -> UniquePtr<StringBuffer> {
656 unsafe { v8_inspector__StringBuffer__create(source) }
657 }
658}
659
660impl Drop for StringBuffer {
661 fn drop(&mut self) {
662 unsafe { v8_inspector__StringBuffer__DELETE(self) }
663 }
664}
665
666unsafe impl Send for StringBuffer {}
667use std::iter::ExactSizeIterator;
668use std::iter::IntoIterator;
669use std::marker::PhantomData;
670use std::ops::Deref;
671use std::ptr::null;
672use std::ptr::NonNull;
673use std::slice;
674use std::string;
675
676#[derive(Clone, Debug, Copy)]
683#[repr(u8)]
684pub enum StringView<'a> {
685 U16(CharacterArray<'a, u16>),
687 U8(CharacterArray<'a, u8>),
688}
689
690impl StringView<'static> {
691 pub fn empty() -> Self {
692 Self::U8(CharacterArray::<'static, u8>::empty())
693 }
694}
695
696impl fmt::Display for StringView<'_> {
697 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
698 match self {
699 Self::U16(v) => write!(f, "{}", v),
700 Self::U8(v) => write!(f, "{}", v),
701 }
702 }
703}
704
705impl<'a> From<&'a [u8]> for StringView<'a> {
706 fn from(v: &'a [u8]) -> Self {
707 Self::U8(CharacterArray::<'a, u8>::from(v))
708 }
709}
710
711impl<'a> From<&'a [u16]> for StringView<'a> {
712 fn from(v: &'a [u16]) -> Self {
713 Self::U16(CharacterArray::<'a, u16>::from(v))
714 }
715}
716
717impl<'a> StringView<'a> {
718 pub fn is_8bit(&self) -> bool {
719 match self {
720 Self::U16(..) => false,
721 Self::U8(..) => true,
722 }
723 }
724
725 pub fn is_empty(&self) -> bool {
726 self.len() == 0
727 }
728
729 pub fn len(&self) -> usize {
730 match self {
731 Self::U16(v) => v.len(),
732 Self::U8(v) => v.len(),
733 }
734 }
735
736 pub fn characters8(&self) -> Option<&[u8]> {
737 match self {
738 Self::U16(..) => None,
739 Self::U8(v) => Some(v),
740 }
741 }
742
743 pub fn characters16(&self) -> Option<&[u16]> {
744 match self {
745 Self::U16(v) => Some(v),
746 Self::U8(..) => None,
747 }
748 }
749}
750
751impl<'a> IntoIterator for StringView<'a> {
752 type IntoIter = StringViewIterator<'a>;
753 type Item = u16;
754
755 fn into_iter(self) -> Self::IntoIter {
756 StringViewIterator { view: self, pos: 0 }
757 }
758}
759
760#[repr(C)]
761#[derive(Copy, Clone, Debug)]
762pub struct CharacterArray<'a, T> {
763 m_length: usize,
764 m_characters: *const T,
765 _phantom: PhantomData<&'a T>,
766}
767
768impl CharacterArray<'static, u8> {
769 pub fn empty() -> Self {
770 Self {
771 m_length: 0,
772 m_characters: null(),
773 _phantom: PhantomData,
774 }
775 }
776}
777
778impl<'a, T> CharacterArray<'a, T>
779where
780 T: Copy,
781{
782 #[inline(always)]
783 fn len(&self) -> usize {
784 self.m_length
785 }
786
787 #[inline(always)]
788 fn get_at(&self, index: usize) -> Option<T> {
789 if index < self.m_length {
790 Some(unsafe { *self.m_characters.add(index) })
791 } else {
792 None
793 }
794 }
795}
796
797unsafe impl<'a, T> Send for CharacterArray<'a, T> where T: Copy {}
798unsafe impl<'a, T> Sync for CharacterArray<'a, T> where T: Sync {}
799
800impl fmt::Display for CharacterArray<'_, u8> {
801 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
802 f.write_str(
803 self
804 .iter()
805 .cloned()
806 .map(char::from)
807 .collect::<string::String>()
808 .as_str(),
809 )
810 }
811}
812
813impl fmt::Display for CharacterArray<'_, u16> {
814 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
815 f.write_str(&string::String::from_utf16_lossy(&*self))
816 }
817}
818
819impl<'a, T> From<&'a [T]> for CharacterArray<'a, T> {
820 fn from(v: &'a [T]) -> Self {
821 Self {
822 m_length: v.len(),
823 m_characters: v.as_ptr(),
824 _phantom: PhantomData,
825 }
826 }
827}
828
829impl<'a, T> Deref for CharacterArray<'a, T> {
830 type Target = [T];
831
832 fn deref(&self) -> &[T] {
833 let Self {
834 m_length,
835 mut m_characters,
836 ..
837 } = *self;
838 if m_characters.is_null() {
839 assert_eq!(m_length, 0);
840 m_characters = NonNull::dangling().as_ptr()
841 };
842 unsafe { slice::from_raw_parts(m_characters, m_length) }
843 }
844}
845
846#[derive(Copy, Clone, Debug)]
847pub struct StringViewIterator<'a> {
848 view: StringView<'a>,
849 pos: usize,
850}
851
852impl<'a> Iterator for StringViewIterator<'a> {
853 type Item = u16;
854
855 fn next(&mut self) -> Option<Self::Item> {
856 let result = Some(match self.view {
857 StringView::U16(v) => v.get_at(self.pos)?,
858 StringView::U8(v) => u16::from(v.get_at(self.pos)?),
859 });
860 self.pos += 1;
861 result
862 }
863}
864
865impl<'a> ExactSizeIterator for StringViewIterator<'a> {
866 fn len(&self) -> usize {
867 self.view.len()
868 }
869}
870
871#[test]
872fn string_view_display() {
873 let ok: [u16; 2] = [111, 107];
874 assert_eq!("ok", format!("{}", StringView::from(&ok[..])));
875 assert_eq!("ok", format!("{}", StringView::from(&b"ok"[..])));
876 assert_eq!("ØÞ", format!("{}", StringView::from(&[216u8, 222u8][..])));
877}
878
879#[repr(C)]
880#[derive(Debug)]
881pub struct V8Inspector(Opaque);
882
883impl V8Inspector {
884 pub fn create<T>(
885 isolate: &mut Isolate,
886 client: &mut T,
887 ) -> UniqueRef<V8Inspector>
888 where
889 T: AsV8InspectorClient,
890 {
891 unsafe {
892 UniqueRef::from_raw(v8_inspector__V8Inspector__create(
893 isolate,
894 client.as_client_mut(),
895 ))
896 }
897 }
898
899 pub fn connect<T>(
900 &mut self,
901 context_group_id: i32,
902 channel: &mut T,
903 state: StringView,
904 ) -> UniqueRef<V8InspectorSession>
905 where
906 T: AsChannel,
907 {
908 unsafe {
909 UniqueRef::from_raw(v8_inspector__V8Inspector__connect(
910 self,
911 context_group_id,
912 channel.as_channel_mut(),
913 state,
914 ))
915 }
916 }
917
918 pub fn context_created(
921 &mut self,
922 context: Local<Context>,
923 context_group_id: i32,
924 human_readable_name: StringView,
925 ) {
926 unsafe {
927 v8_inspector__V8Inspector__contextCreated(
928 self,
929 &*context,
930 context_group_id,
931 human_readable_name,
932 )
933 }
934 }
935}
936
937impl Drop for V8Inspector {
938 fn drop(&mut self) {
939 unsafe { v8_inspector__V8Inspector__DELETE(self) };
940 }
941}
942
943#[repr(C)]
944#[derive(Debug)]
945pub struct V8StackTrace {
946 _cxx_vtable: CxxVTable,
947}
948
949