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