1use crate::gc::RootedTraceableSet;
2use crate::jsapi::{Heap, JSTracer};
3use crate::rust::Handle;
4use mozjs_sys::jsapi::JS;
5use mozjs_sys::jsgc::GCMethods;
6use mozjs_sys::jsval::JSVal;
7use mozjs_sys::trace::Traceable;
8use std::ops::{Deref, DerefMut};
9
10#[cfg_attr(feature = "crown", allow(crown::unrooted_must_root))]
13#[cfg_attr(
14 feature = "crown",
15 crown::unrooted_must_root_lint::allow_unrooted_interior
16)]
17pub struct RootableVec<T: Traceable> {
18 v: Vec<T>,
19}
20
21impl<T: Traceable> RootableVec<T> {
22 pub fn new_unrooted() -> RootableVec<T> {
24 RootableVec { v: Vec::new() }
25 }
26}
27
28unsafe impl<T: Traceable> Traceable for RootableVec<T> {
29 unsafe fn trace(&self, trc: *mut JSTracer) {
30 self.v.trace(trc);
31 }
32}
33
34#[cfg_attr(
36 feature = "crown",
37 crown::unrooted_must_root_lint::allow_unrooted_interior
38)]
39pub struct RootedVec<'a, T: Traceable + 'static> {
40 root: &'a mut RootableVec<T>,
41}
42
43impl From<&RootedVec<'_, JSVal>> for JS::HandleValueArray {
44 fn from(vec: &RootedVec<'_, JSVal>) -> JS::HandleValueArray {
45 JS::HandleValueArray {
46 length_: vec.root.v.len(),
47 elements_: vec.root.v.as_ptr(),
48 }
49 }
50}
51
52impl From<&super::RootedGuard<'_, Vec<JSVal>>> for JS::HandleValueArray {
53 fn from(vec: &super::RootedGuard<'_, Vec<JSVal>>) -> JS::HandleValueArray {
54 JS::HandleValueArray {
55 length_: vec.len(),
56 elements_: vec.deref().as_ptr(),
57 }
58 }
59}
60
61impl<'a, T: Traceable + 'static> RootedVec<'a, T> {
62 pub fn new(root: &'a mut RootableVec<T>) -> RootedVec<'a, T> {
63 unsafe {
64 RootedTraceableSet::add(root);
65 }
66 RootedVec { root }
67 }
68
69 pub fn from_iter<I>(root: &'a mut RootableVec<T>, iter: I) -> Self
70 where
71 I: Iterator<Item = T>,
72 {
73 unsafe {
74 RootedTraceableSet::add(root);
75 }
76 root.v.extend(iter);
77 RootedVec { root }
78 }
79}
80
81impl<'a, T: Traceable + 'static> Drop for RootedVec<'a, T> {
82 fn drop(&mut self) {
83 self.clear();
84 unsafe {
85 RootedTraceableSet::remove(self.root);
86 }
87 }
88}
89
90impl<'a, T: Traceable> Deref for RootedVec<'a, T> {
91 type Target = Vec<T>;
92 fn deref(&self) -> &Vec<T> {
93 &self.root.v
94 }
95}
96
97impl<'a, T: Traceable> DerefMut for RootedVec<'a, T> {
98 fn deref_mut(&mut self) -> &mut Vec<T> {
99 &mut self.root.v
100 }
101}
102
103pub struct RootedTraceableBox<T: Traceable + 'static> {
108 ptr: *mut T,
109}
110
111impl<T: Traceable + 'static> RootedTraceableBox<T> {
112 pub fn new(traceable: T) -> RootedTraceableBox<T> {
114 Self::from_box(Box::new(traceable))
115 }
116
117 pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
119 let traceable = Box::into_raw(boxed_traceable);
120 unsafe {
121 RootedTraceableSet::add(traceable);
122 }
123 RootedTraceableBox { ptr: traceable }
124 }
125
126 pub unsafe fn ptr(&self) -> *mut T {
128 self.ptr
129 }
130}
131
132impl<T> RootedTraceableBox<Heap<T>>
133where
134 Heap<T>: Traceable + 'static,
135 T: GCMethods + Copy,
136{
137 pub fn handle(&self) -> Handle<T> {
138 unsafe { Handle::from_raw((*self.ptr).handle()) }
139 }
140}
141
142unsafe impl<T: Traceable + 'static> Traceable for RootedTraceableBox<T> {
143 unsafe fn trace(&self, trc: *mut JSTracer) {
144 (*self.ptr).trace(trc)
145 }
146}
147
148impl<T: Traceable> Deref for RootedTraceableBox<T> {
149 type Target = T;
150 fn deref(&self) -> &T {
151 unsafe { &*self.ptr }
152 }
153}
154
155impl<T: Traceable> DerefMut for RootedTraceableBox<T> {
156 fn deref_mut(&mut self) -> &mut T {
157 unsafe { &mut *self.ptr }
158 }
159}
160
161impl<T: Traceable + 'static> Drop for RootedTraceableBox<T> {
162 fn drop(&mut self) {
163 unsafe {
164 RootedTraceableSet::remove(self.ptr);
165 let _ = Box::from_raw(self.ptr);
166 }
167 }
168}