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
103#[cfg_attr(
104 feature = "crown",
105 crown::unrooted_must_root_lint::allow_unrooted_interior
106)]
107pub struct RootedTraceableBox<T: Traceable + 'static> {
112 ptr: *mut T,
113}
114
115impl<T: Traceable + 'static> RootedTraceableBox<T> {
116 pub fn new(traceable: T) -> RootedTraceableBox<T> {
118 Self::from_box(Box::new(traceable))
119 }
120
121 pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
123 let traceable = Box::into_raw(boxed_traceable);
124 unsafe {
125 RootedTraceableSet::add(traceable);
126 }
127 RootedTraceableBox { ptr: traceable }
128 }
129
130 pub unsafe fn ptr(&self) -> *mut T {
132 self.ptr
133 }
134}
135
136impl<T> RootedTraceableBox<Heap<T>>
137where
138 Heap<T>: Traceable + 'static,
139 T: GCMethods + Copy,
140{
141 pub fn handle(&'_ self) -> Handle<'_, T> {
142 unsafe { Handle::from_raw((*self.ptr).handle()) }
143 }
144}
145
146unsafe impl<T: Traceable + 'static> Traceable for RootedTraceableBox<T> {
147 unsafe fn trace(&self, trc: *mut JSTracer) {
148 (*self.ptr).trace(trc)
149 }
150}
151
152impl<T: Traceable> Deref for RootedTraceableBox<T> {
153 type Target = T;
154 fn deref(&self) -> &T {
155 unsafe { &*self.ptr }
156 }
157}
158
159impl<T: Traceable> DerefMut for RootedTraceableBox<T> {
160 fn deref_mut(&mut self) -> &mut T {
161 unsafe { &mut *self.ptr }
162 }
163}
164
165impl<T: Traceable + 'static> Drop for RootedTraceableBox<T> {
166 fn drop(&mut self) {
167 unsafe {
168 RootedTraceableSet::remove(self.ptr);
169 let _ = Box::from_raw(self.ptr);
170 }
171 }
172}