1use std::fmt;
8use std::fmt::{Debug, Formatter};
9
10use mozjs::gc::{GCMethods, Handle, MutableHandle, RootKind};
11use mozjs::jsapi::{Handle as RawHandle, Heap, MutableHandle as RawMutableHandle, Rooted};
12
13use crate::Context;
14
15pub enum Local<'local, T: 'local>
18where
19 T: RootKind,
20{
21 Rooted(&'local mut Rooted<T>),
22 Mutable(MutableHandle<'local, T>),
23 Handle(Handle<'local, T>),
24}
25
26impl<'local, T: Copy + RootKind> Local<'local, T> {
27 pub fn handle(&self) -> Handle<'local, T> {
29 match self {
30 Self::Rooted(root) => unsafe { Handle::from_marked_location(&raw const root.data) },
31 Self::Mutable(handle) => unsafe { Handle::from_marked_location(&handle.get()) },
32 Self::Handle(handle) => *handle,
33 }
34 }
35
36 pub fn handle_mut(&mut self) -> MutableHandle<'local, T> {
41 match self {
42 Local::Rooted(root) => unsafe { MutableHandle::from_marked_location(&raw mut root.data) },
43 Local::Mutable(handle) => unsafe { MutableHandle::from_marked_location(handle.as_mut()) },
44 Local::Handle(_) => panic!("&mut Local::Handle should never be constructed"),
45 }
46 }
47
48 pub fn get(&self) -> T {
49 match self {
50 Self::Rooted(root) => root.data,
51 Self::Mutable(handle) => handle.get(),
52 Self::Handle(handle) => handle.get(),
53 }
54 }
55}
56
57impl<'local, T: RootKind> Local<'local, T> {
58 pub(crate) fn new(cx: &Context, root: &'local mut Rooted<T>) -> Local<'local, T> {
61 unsafe {
62 Rooted::add_to_root_stack(root, cx.as_ptr());
63 }
64 Local::Rooted(root)
65 }
66
67 pub fn from_handle(handle: Handle<'local, T>) -> Local<'local, T> {
69 Local::Handle(handle)
70 }
71
72 pub fn from_handle_mut(handle: MutableHandle<'local, T>) -> Local<'local, T> {
74 Local::Mutable(handle)
75 }
76
77 pub unsafe fn from_marked(ptr: *const T) -> Local<'local, T> {
82 Local::Handle(unsafe { Handle::from_marked_location(ptr) })
83 }
84
85 pub unsafe fn from_raw_handle(handle: RawHandle<T>) -> Local<'local, T> {
90 Local::Handle(unsafe { Handle::from_raw(handle) })
91 }
92
93 pub unsafe fn from_marked_mut(ptr: *mut T) -> Local<'local, T> {
98 Local::Mutable(unsafe { MutableHandle::from_marked_location(ptr) })
99 }
100
101 pub unsafe fn from_raw_handle_mut(handle: RawMutableHandle<T>) -> Local<'local, T> {
106 Local::Mutable(unsafe { MutableHandle::from_raw(handle) })
107 }
108}
109
110impl<'local, T: Copy + GCMethods + RootKind> Local<'local, T> {
111 pub unsafe fn from_heap(heap: &'local Heap<T>) -> Local<'local, T> {
112 unsafe { Local::from_raw_handle(heap.handle()) }
113 }
114}
115
116impl<T: Copy + Debug + RootKind> Debug for Local<'_, T> {
117 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
118 self.handle().fmt(f)
119 }
120}