1use std::mem::MaybeUninit;
8use std::path::{Component, Path, PathBuf};
9use std::slice;
10use std::slice::Iter;
11
12pub fn normalise_path<P: AsRef<Path>>(path: P) -> PathBuf {
15 let mut buf = PathBuf::new();
16 let segments = path.as_ref().components();
17
18 for segment in segments {
19 match segment {
20 Component::ParentDir => {
21 let len = buf.components().count();
22 if len == 0 || buf.components().all(|c| matches!(c, Component::ParentDir)) {
23 buf.push("..");
24 } else {
25 buf.pop();
26 }
27 }
28 Component::CurDir => {}
29 segment => buf.push(segment),
30 }
31 }
32 buf
33}
34
35pub trait BoxExt<T> {
36 fn into_raw_parts(self) -> (*mut T, usize);
37
38 unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self;
39}
40
41impl<T> BoxExt<T> for Box<[T]> {
42 fn into_raw_parts(self) -> (*mut T, usize) {
43 let len = self.len();
44 (Box::into_raw(self).cast::<T>(), len)
45 }
46
47 unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
48 unsafe {
49 let slice = slice::from_raw_parts_mut(ptr, len);
50 Box::from_raw(slice)
51 }
52 }
53}
54
55#[derive(Clone, Copy, Debug)]
56pub struct ArrayVec<const CAP: usize, T: Copy> {
57 elements: [MaybeUninit<T>; CAP],
58 len: usize,
59}
60
61impl<const CAP: usize, T: Copy> ArrayVec<CAP, T> {
62 pub const fn new() -> ArrayVec<CAP, T> {
63 ArrayVec {
64 elements: unsafe { MaybeUninit::uninit().assume_init() },
65 len: 0,
66 }
67 }
68
69 pub const fn len(&self) -> usize {
70 self.len
71 }
72
73 pub const fn is_empty(&self) -> bool {
74 self.len() == 0
75 }
76
77 pub const fn is_full(&self) -> bool {
78 self.len() == CAP
79 }
80
81 pub const fn push(mut self, element: T) -> ArrayVec<CAP, T> {
82 assert!(self.len < CAP, "Exceeded capacity of ArrayVec.");
83 self.elements[self.len] = MaybeUninit::new(element);
84 self.len += 1;
85 self
86 }
87
88 pub const fn pop(mut self) -> (ArrayVec<CAP, T>, Option<T>) {
89 if self.len == 0 {
90 return (self, None);
91 }
92 let element = unsafe { self.elements[self.len].assume_init() };
93 self.len -= 1;
94 (self, Some(element))
95 }
96
97 pub const fn get(&self, index: usize) -> Option<&T> {
98 if self.is_empty() || index >= self.len() {
99 return None;
100 }
101 Some(unsafe { self.elements[index].assume_init_ref() })
102 }
103
104 pub const fn truncate(mut self, new_len: usize) -> ArrayVec<CAP, T> {
105 if new_len >= self.len {
106 return self;
107 }
108 self.len = new_len;
109 self
110 }
111
112 pub fn iter(&self) -> Iter<'_, T> {
113 unsafe { slice::from_raw_parts(self.elements.as_ptr().cast::<T>(), self.len()).iter() }
114 }
115}
116
117impl<const CAP: usize, T: Copy> Default for ArrayVec<CAP, T> {
118 fn default() -> ArrayVec<CAP, T> {
119 ArrayVec::new()
120 }
121}
122
123pub mod test {
124 use mozjs::jsapi::{JSAutoRealm, JSObject};
125 use mozjs::rust::{JSEngine, Runtime};
126
127 use crate::{Context, default_new_global};
128
129 pub struct TestRuntime {
130 pub realm: JSAutoRealm,
131 pub global: *mut JSObject,
132 pub cx: Context,
133 pub runtime: Runtime,
134 pub engine: JSEngine,
135 }
136
137 impl TestRuntime {
138 pub fn new() -> TestRuntime {
139 let engine = JSEngine::init().unwrap();
140 let runtime = Runtime::new(engine.handle());
141
142 let cx = Context::from_runtime(&runtime);
143 let global = default_new_global(&cx);
144 let realm = JSAutoRealm::new(cx.as_ptr(), global.handle().get());
145
146 TestRuntime {
147 realm,
148 global: global.handle().get(),
149 cx,
150 runtime,
151 engine,
152 }
153 }
154 }
155
156 impl Default for TestRuntime {
157 fn default() -> TestRuntime {
158 TestRuntime::new()
159 }
160 }
161}