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};
9use std::ptr;
10
11#[cfg_attr(feature = "crown", allow(crown::unrooted_must_root))]
14#[cfg_attr(
15 feature = "crown",
16 crown::unrooted_must_root_lint::allow_unrooted_interior
17)]
18pub struct RootableVec<T: Traceable> {
19 v: Vec<T>,
20}
21
22impl<T: Traceable> RootableVec<T> {
23 pub fn new_unrooted() -> RootableVec<T> {
25 RootableVec { v: Vec::new() }
26 }
27}
28
29unsafe impl<T: Traceable> Traceable for RootableVec<T> {
30 unsafe fn trace(&self, trc: *mut JSTracer) {
31 self.v.trace(trc);
32 }
33}
34
35#[cfg_attr(
37 feature = "crown",
38 crown::unrooted_must_root_lint::allow_unrooted_interior
39)]
40pub struct RootedVec<'a, T: Traceable + 'static> {
41 root: &'a mut RootableVec<T>,
42}
43
44impl From<&RootedVec<'_, JSVal>> for JS::HandleValueArray {
45 fn from(vec: &RootedVec<'_, JSVal>) -> JS::HandleValueArray {
46 JS::HandleValueArray {
47 length_: vec.root.v.len(),
48 elements_: vec.root.v.as_ptr(),
49 }
50 }
51}
52
53impl From<&super::RootedGuard<'_, Vec<JSVal>>> for JS::HandleValueArray {
54 fn from(vec: &super::RootedGuard<'_, Vec<JSVal>>) -> JS::HandleValueArray {
55 JS::HandleValueArray {
56 length_: vec.len(),
57 elements_: vec.deref().as_ptr(),
58 }
59 }
60}
61
62impl<'a, T: Traceable + 'static> RootedVec<'a, T> {
63 pub fn new(root: &'a mut RootableVec<T>) -> RootedVec<'a, T> {
64 unsafe {
65 RootedTraceableSet::add(root);
66 }
67 RootedVec { root }
68 }
69
70 pub fn from_iter<I>(root: &'a mut RootableVec<T>, iter: I) -> Self
71 where
72 I: Iterator<Item = T>,
73 {
74 unsafe {
75 RootedTraceableSet::add(root);
76 }
77 root.v.extend(iter);
78 RootedVec { root }
79 }
80}
81
82impl<'a, T: Traceable + 'static> Drop for RootedVec<'a, T> {
83 fn drop(&mut self) {
84 self.clear();
85 unsafe {
86 RootedTraceableSet::remove(self.root);
87 }
88 }
89}
90
91impl<'a, T: Traceable> Deref for RootedVec<'a, T> {
92 type Target = Vec<T>;
93 fn deref(&self) -> &Vec<T> {
94 &self.root.v
95 }
96}
97
98impl<'a, T: Traceable> DerefMut for RootedVec<'a, T> {
99 fn deref_mut(&mut self) -> &mut Vec<T> {
100 &mut self.root.v
101 }
102}
103
104#[cfg_attr(
105 feature = "crown",
106 crown::unrooted_must_root_lint::allow_unrooted_interior
107)]
108pub struct RootedTraceableBox<T: Traceable + 'static> {
113 ptr: *mut T,
114}
115
116impl<T: Traceable + 'static> RootedTraceableBox<T> {
117 pub fn new(traceable: T) -> RootedTraceableBox<T> {
119 Self::from_box(Box::new(traceable))
120 }
121
122 pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
124 let traceable = Box::into_raw(boxed_traceable);
125 unsafe {
126 RootedTraceableSet::add(traceable);
127 }
128 RootedTraceableBox { ptr: traceable }
129 }
130
131 pub unsafe fn ptr(&self) -> *mut T {
133 self.ptr
134 }
135
136 pub fn into_box(mut self) -> Box<T> {
140 self.cleanup()
141 }
142
143 fn cleanup(&mut self) -> Box<T> {
144 unsafe {
145 let ptr = std::mem::replace(&mut self.ptr, ptr::null_mut());
146 RootedTraceableSet::remove(ptr);
147 Box::from_raw(ptr)
148 }
149 }
150}
151
152impl<T> RootedTraceableBox<Heap<T>>
153where
154 Heap<T>: Traceable + 'static,
155 T: GCMethods + Copy,
156{
157 pub fn handle(&'_ self) -> Handle<'_, T> {
158 unsafe { Handle::from_raw((*self.ptr).handle()) }
159 }
160}
161
162unsafe impl<T: Traceable + 'static> Traceable for RootedTraceableBox<T> {
163 unsafe fn trace(&self, trc: *mut JSTracer) {
164 (*self.ptr).trace(trc)
165 }
166}
167
168impl<T: Traceable> Deref for RootedTraceableBox<T> {
169 type Target = T;
170 fn deref(&self) -> &T {
171 unsafe { &*self.ptr }
172 }
173}
174
175impl<T: Traceable> DerefMut for RootedTraceableBox<T> {
176 fn deref_mut(&mut self) -> &mut T {
177 unsafe { &mut *self.ptr }
178 }
179}
180
181impl<T: Traceable + 'static> Drop for RootedTraceableBox<T> {
182 fn drop(&mut self) {
183 if !self.ptr.is_null() {
184 self.cleanup();
185 }
186 }
187}