1use std::sync::Arc;
10use std::sync::atomic::{AtomicU8, AtomicUsize, Ordering};
11
12#[derive(Debug)]
14pub struct SharedBytes {
15 bytes: Box<[AtomicU8]>,
16 len: AtomicUsize,
17}
18
19impl SharedBytes {
20 pub fn new(len: usize, capacity: usize) -> Arc<SharedBytes> {
21 Arc::new(SharedBytes {
22 bytes: (0..capacity.max(len)).map(|_| AtomicU8::new(0)).collect(),
23 len: AtomicUsize::new(len),
24 })
25 }
26
27 pub fn len(&self) -> usize {
28 self.len.load(Ordering::SeqCst)
29 }
30
31 pub fn is_empty(&self) -> bool {
32 self.len() == 0
33 }
34
35 pub fn capacity(&self) -> usize {
36 self.bytes.len()
37 }
38
39 pub fn grow(&self, len: usize) -> bool {
42 let current = self.len();
43 len >= current
44 && len <= self.capacity()
45 && self
46 .len
47 .compare_exchange(current, len, Ordering::SeqCst, Ordering::SeqCst)
48 .is_ok()
49 }
50
51 pub fn byte(&self, index: usize) -> &AtomicU8 {
52 &self.bytes[index]
53 }
54}
55
56#[derive(Debug)]
58pub enum Store {
59 Owned(Vec<u8>),
60 Shared(Arc<SharedBytes>),
61}
62
63#[derive(Debug)]
65pub struct Buffer {
66 pub store: Store,
67 pub detached: bool,
68 pub max: Option<usize>,
70}
71
72impl Buffer {
73 pub fn owned(len: usize, max: Option<usize>) -> Buffer {
74 Buffer {
75 store: Store::Owned(vec![0; len]),
76 detached: false,
77 max,
78 }
79 }
80
81 pub fn shared(len: usize, max: Option<usize>) -> Buffer {
82 Buffer {
83 store: Store::Shared(SharedBytes::new(len, max.unwrap_or(len))),
84 detached: false,
85 max,
86 }
87 }
88
89 pub fn is_shared(&self) -> bool {
90 matches!(self.store, Store::Shared(_))
91 }
92
93 pub fn len(&self) -> usize {
94 match &self.store {
95 Store::Owned(bytes) => bytes.len(),
96 Store::Shared(shared) => shared.len(),
97 }
98 }
99
100 pub fn is_empty(&self) -> bool {
101 self.len() == 0
102 }
103
104 pub fn owned_bytes(&self) -> usize {
105 match &self.store {
106 Store::Owned(bytes) => bytes.capacity(),
107 Store::Shared(shared) => shared.capacity(),
108 }
109 }
110
111 #[inline]
113 pub fn read(&self, offset: usize, out: &mut [u8]) {
114 if out.is_empty() {
115 return;
116 }
117 match &self.store {
118 Store::Owned(bytes) => out.copy_from_slice(&bytes[offset..offset + out.len()]),
119 Store::Shared(shared) => {
120 for (index, byte) in out.iter_mut().enumerate() {
121 *byte = shared.byte(offset + index).load(Ordering::Relaxed);
122 }
123 }
124 }
125 }
126
127 #[inline]
129 pub fn write(&mut self, offset: usize, data: &[u8]) {
130 if data.is_empty() {
131 return;
132 }
133 match &mut self.store {
134 Store::Owned(bytes) => bytes[offset..offset + data.len()].copy_from_slice(data),
135 Store::Shared(shared) => {
136 for (index, byte) in data.iter().enumerate() {
137 shared.byte(offset + index).store(*byte, Ordering::Relaxed);
138 }
139 }
140 }
141 }
142
143 pub fn copy_within(&mut self, from: usize, to: usize, len: usize) {
145 if len == 0 {
146 return;
147 }
148 match &mut self.store {
149 Store::Owned(bytes) => bytes.copy_within(from..from + len, to),
150 Store::Shared(_) => {
151 let mut temporary = vec![0; len];
152 self.read(from, &mut temporary);
153 self.write(to, &temporary);
154 }
155 }
156 }
157
158 pub fn owned_slice(&self) -> Option<&[u8]> {
160 match &self.store {
161 Store::Owned(bytes) => Some(bytes),
162 Store::Shared(_) => None,
163 }
164 }
165
166 pub fn owned_slice_mut(&mut self) -> Option<&mut Vec<u8>> {
167 match &mut self.store {
168 Store::Owned(bytes) => Some(bytes),
169 Store::Shared(_) => None,
170 }
171 }
172
173 pub fn to_vec(&self, offset: usize, len: usize) -> Vec<u8> {
175 let mut out = vec![0; len];
176 self.read(offset, &mut out);
177 out
178 }
179}
180
181#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
183#[repr(u8)]
184pub enum ElementKind {
185 Int8,
186 Uint8,
187 Uint8Clamped,
188 Int16,
189 Uint16,
190 Int32,
191 Uint32,
192 Float16,
193 Float32,
194 Float64,
195 BigInt64,
196 BigUint64,
197}
198
199impl ElementKind {
200 pub const ALL: [ElementKind; 12] = [
201 ElementKind::Int8,
202 ElementKind::Uint8,
203 ElementKind::Uint8Clamped,
204 ElementKind::Int16,
205 ElementKind::Uint16,
206 ElementKind::Int32,
207 ElementKind::Uint32,
208 ElementKind::Float16,
209 ElementKind::Float32,
210 ElementKind::Float64,
211 ElementKind::BigInt64,
212 ElementKind::BigUint64,
213 ];
214
215 #[inline]
216 pub const fn size(self) -> usize {
217 match self {
218 ElementKind::Int8 | ElementKind::Uint8 | ElementKind::Uint8Clamped => 1,
219 ElementKind::Int16 | ElementKind::Uint16 | ElementKind::Float16 => 2,
220 ElementKind::Int32 | ElementKind::Uint32 | ElementKind::Float32 => 4,
221 ElementKind::Float64 | ElementKind::BigInt64 | ElementKind::BigUint64 => 8,
222 }
223 }
224
225 #[inline]
226 pub const fn is_bigint(self) -> bool {
227 matches!(self, ElementKind::BigInt64 | ElementKind::BigUint64)
228 }
229
230 pub const fn name(self) -> &'static str {
231 match self {
232 ElementKind::Int8 => "Int8Array",
233 ElementKind::Uint8 => "Uint8Array",
234 ElementKind::Uint8Clamped => "Uint8ClampedArray",
235 ElementKind::Int16 => "Int16Array",
236 ElementKind::Uint16 => "Uint16Array",
237 ElementKind::Int32 => "Int32Array",
238 ElementKind::Uint32 => "Uint32Array",
239 ElementKind::Float16 => "Float16Array",
240 ElementKind::Float32 => "Float32Array",
241 ElementKind::Float64 => "Float64Array",
242 ElementKind::BigInt64 => "BigInt64Array",
243 ElementKind::BigUint64 => "BigUint64Array",
244 }
245 }
246
247 pub fn from_index(index: u8) -> ElementKind {
248 ElementKind::ALL[index as usize]
249 }
250}
251
252#[derive(Clone, Copy, Debug)]
254pub struct View {
255 pub kind: ElementKind,
256 pub byte_offset: usize,
257 pub length: Option<usize>,
260}
261
262impl View {
263 #[inline]
266 pub fn current_length(
267 &self,
268 buffer_len: usize,
269 detached: bool,
270 element: usize,
271 ) -> Option<usize> {
272 if detached || self.byte_offset > buffer_len {
273 return None;
274 }
275 match self.length {
276 Some(length) => (self.byte_offset + length * element <= buffer_len).then_some(length),
277 None => Some((buffer_len - self.byte_offset) / element),
278 }
279 }
280}
281
282pub const MAX_BUFFER_LENGTH: usize = i32::MAX as usize;
284
285impl super::Heap {
286 pub(crate) fn charge(
289 &mut self,
290 extra: usize,
291 keep: &[crate::value::Value],
292 ) -> Result<(), super::HeapError> {
293 self.safepoint(
294 &super::Need {
295 extra,
296 ..Default::default()
297 },
298 keep,
299 )
300 }
301}