1use core::marker::PhantomData;
34
35use alloc::{boxed::Box, vec::Vec};
36
37use crate::{
38 core::{
39 reader::{types::FuncType, WasmReader},
40 utils::ToUsizeExt,
41 },
42 ValType, ValidationError,
43};
44
45pub trait Idx: Copy + core::fmt::Debug + core::fmt::Display + Eq {
49 fn new(index: u32) -> Self;
50
51 fn into_inner(self) -> u32;
52}
53
54pub struct IdxVec<I: Idx, T> {
58 inner: Box<[T]>,
59 _phantom: PhantomData<I>,
60}
61
62impl<I: Idx, T> Default for IdxVec<I, T> {
63 fn default() -> Self {
64 Self {
65 inner: Box::default(),
66 _phantom: PhantomData,
67 }
68 }
69}
70
71impl<I: Idx, T: Clone> Clone for IdxVec<I, T> {
72 fn clone(&self) -> Self {
73 Self {
74 inner: self.inner.clone(),
75 _phantom: PhantomData,
76 }
77 }
78}
79
80impl<I: Idx, T: core::fmt::Debug> core::fmt::Debug for IdxVec<I, T> {
81 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
82 f.debug_list().entries(&*self.inner).finish()
83 }
84}
85
86#[derive(Debug)]
88pub struct IdxVecOverflowError;
89
90impl<I: Idx, T> IdxVec<I, T> {
91 pub fn new(elements: Vec<T>) -> Result<Self, IdxVecOverflowError> {
96 if u32::try_from(elements.len()).is_err() {
97 return Err(IdxVecOverflowError);
98 }
99
100 Ok(Self {
101 inner: elements.into_boxed_slice(),
102 _phantom: PhantomData,
103 })
104 }
105
106 fn validate_index(&self, index: u32) -> Option<I> {
107 let index_as_usize = index.into_usize();
108 let _element = self.inner.get(index_as_usize)?;
109 Some(I::new(index))
110 }
111
112 pub unsafe fn get(&self, index: I) -> &T {
120 let index = index.into_inner().into_usize();
121
122 self.inner
125 .get(index)
126 .expect("this to be a valid index due to the safety guarantees made by the caller")
127 }
128
129 #[allow(unused)] pub fn len(&self) -> u32 {
131 u32::try_from(self.inner.len()).expect(
132 "this to never be larger than u32::MAX, because this was checked for in Self::new",
133 )
134 }
135
136 pub fn iter_enumerated(&self) -> impl Iterator<Item = (I, &T)> {
137 self.inner.iter().enumerate().map(|(index, t)| {
138 (
139 I::new(
140 u32::try_from(index)
141 .expect("this vector to contain a maximum of 2^32-1 elements"),
142 ),
143 t,
144 )
145 })
146 }
147
148 pub fn map<R, E>(&self, mapper: impl FnMut(&T) -> Result<R, E>) -> Result<IdxVec<I, R>, E> {
151 Ok(IdxVec {
152 inner: self
153 .inner
154 .iter()
155 .map(mapper)
156 .collect::<Result<Box<[R]>, E>>()?,
157 _phantom: PhantomData,
158 })
159 }
160}
161
162#[derive(Debug)]
164pub struct ExtendedIdxVec<I: Idx, T> {
165 inner: IdxVec<I, T>,
166 num_imports: u32,
167}
168
169impl<I: Idx, T> Default for ExtendedIdxVec<I, T> {
170 fn default() -> Self {
171 Self {
172 inner: IdxVec::default(),
173 num_imports: 0,
174 }
175 }
176}
177
178impl<I: Idx, T: Clone> Clone for ExtendedIdxVec<I, T> {
179 fn clone(&self) -> Self {
180 Self {
181 inner: self.inner.clone(),
182 num_imports: self.num_imports,
183 }
184 }
185}
186
187impl<I: Idx, T> ExtendedIdxVec<I, T> {
188 pub fn new(imports: Vec<T>, locals: Vec<T>) -> Result<Self, IdxVecOverflowError> {
194 let num_imports = u32::try_from(imports.len()).map_err(|_| IdxVecOverflowError)?;
195
196 let mut combined = imports;
197 combined.extend(locals);
198
199 Ok(Self {
200 inner: IdxVec::new(combined)?,
201 num_imports,
202 })
203 }
204
205 pub fn len_local_definitions(&self) -> u32 {
208 self.inner
209 .len()
210 .checked_sub(self.num_imports)
211 .expect("that the number of imports is never larger than the total length of self")
212 }
213
214 pub fn map<R>(
220 &self,
221 new_imported_definitions: Vec<R>,
222 new_local_definitions: Vec<R>,
223 ) -> Option<ExtendedIdxVec<I, R>> {
224 if new_imported_definitions.len() != self.num_imports.into_usize()
225 || u32::try_from(new_local_definitions.len()).ok()? != self.len_local_definitions()
226 {
227 return None;
228 }
229
230 Some(
231 ExtendedIdxVec::new(new_imported_definitions, new_local_definitions)
232 .expect("no overflow can happen because the length did not change"),
233 )
234 }
235
236 pub fn iter_local_definitions(&self) -> core::slice::Iter<'_, T> {
237 self.inner
238 .inner
239 .get(self.num_imports.into_usize()..)
240 .expect("the imports length to never be larger than the total length")
241 .iter()
242 }
243
244 pub fn inner(&self) -> &IdxVec<I, T> {
245 &self.inner
246 }
247
248 pub fn into_inner(self) -> IdxVec<I, T> {
249 self.inner
250 }
251}
252
253#[derive(Copy, Clone, Debug, PartialEq, Eq)]
261pub struct TypeIdx(u32);
262
263impl core::fmt::Display for TypeIdx {
264 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
265 write!(f, "type index {}", self.0)
266 }
267}
268
269impl Idx for TypeIdx {
270 fn new(index: u32) -> Self {
271 Self(index)
272 }
273
274 fn into_inner(self) -> u32 {
275 self.0
276 }
277}
278
279impl TypeIdx {
280 pub fn new(index: u32) -> Self {
285 Self(index)
286 }
287
288 pub fn validate(
293 index: u32,
294 c_types: &IdxVec<TypeIdx, FuncType>,
295 ) -> Result<Self, ValidationError> {
296 c_types
297 .validate_index(index)
298 .ok_or(ValidationError::InvalidTypeIdx(index))
299 }
300
301 pub fn read_and_validate(
304 wasm: &mut WasmReader,
305 c_types: &IdxVec<TypeIdx, FuncType>,
306 ) -> Result<Self, ValidationError> {
307 let index = wasm.read_var_u32()?;
308 Self::validate(index, c_types)
309 }
310
311 pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
319 let index = wasm.read_var_u32().unwrap();
320 Self::new(index)
321 }
322}
323
324#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
325pub struct FuncIdx(u32);
326
327impl core::fmt::Display for FuncIdx {
328 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
329 write!(f, "function index {}", self.0)
330 }
331}
332
333impl Idx for FuncIdx {
334 fn new(index: u32) -> Self {
335 Self(index)
336 }
337
338 fn into_inner(self) -> u32 {
339 self.0
340 }
341}
342
343impl FuncIdx {
344 pub fn validate<T>(index: u32, c_funcs: &IdxVec<FuncIdx, T>) -> Result<Self, ValidationError> {
349 c_funcs
350 .validate_index(index)
351 .ok_or(ValidationError::InvalidFuncIdx(index))
352 }
353
354 pub fn read_and_validate<T>(
357 wasm: &mut WasmReader,
358 c_funcs: &IdxVec<FuncIdx, T>,
359 ) -> Result<Self, ValidationError> {
360 let index = wasm.read_var_u32()?;
361 Self::validate(index, c_funcs)
362 }
363
364 pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
372 let index = wasm.read_var_u32().unwrap();
373 Self::new(index)
374 }
375}
376
377#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
378pub struct TableIdx(u32);
379
380impl core::fmt::Display for TableIdx {
381 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
382 write!(f, "table index {}", self.0)
383 }
384}
385
386impl Idx for TableIdx {
387 fn new(index: u32) -> Self {
388 Self(index)
389 }
390
391 fn into_inner(self) -> u32 {
392 self.0
393 }
394}
395
396impl TableIdx {
397 pub fn validate<T>(
402 index: u32,
403 c_tables: &IdxVec<TableIdx, T>,
404 ) -> Result<Self, ValidationError> {
405 c_tables
406 .validate_index(index)
407 .ok_or(ValidationError::InvalidTableIdx(index))
408 }
409
410 pub fn read_and_validate<T>(
413 wasm: &mut WasmReader,
414 c_tables: &IdxVec<TableIdx, T>,
415 ) -> Result<Self, ValidationError> {
416 let index = wasm.read_var_u32()?;
417 Self::validate(index, c_tables)
418 }
419
420 pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
428 let index = wasm.read_var_u32().unwrap();
429 Self::new(index)
430 }
431}
432
433#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
434pub struct MemIdx(u32);
435
436impl core::fmt::Display for MemIdx {
437 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
438 write!(f, "memory index {}", self.0)
439 }
440}
441
442impl Idx for MemIdx {
443 fn new(index: u32) -> Self {
444 Self(index)
445 }
446
447 fn into_inner(self) -> u32 {
448 self.0
449 }
450}
451
452impl MemIdx {
453 pub fn validate<T>(index: u32, c_mems: &IdxVec<MemIdx, T>) -> Result<Self, ValidationError> {
458 c_mems
459 .validate_index(index)
460 .ok_or(ValidationError::InvalidMemIdx(index))
461 }
462
463 pub fn read_and_validate<T>(
466 wasm: &mut WasmReader,
467 c_mems: &IdxVec<MemIdx, T>,
468 ) -> Result<Self, ValidationError> {
469 let index = wasm.read_var_u32()?;
470 Self::validate(index, c_mems)
471 }
472
473 #[allow(unused)] pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
482 let index = wasm.read_var_u32().unwrap();
483 Self::new(index)
484 }
485}
486
487#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
488pub struct GlobalIdx(u32);
489
490impl core::fmt::Display for GlobalIdx {
491 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
492 write!(f, "global index {}", self.0)
493 }
494}
495
496impl Idx for GlobalIdx {
497 fn new(index: u32) -> Self {
498 Self(index)
499 }
500
501 fn into_inner(self) -> u32 {
502 self.0
503 }
504}
505
506impl GlobalIdx {
507 pub fn validate<T>(
512 index: u32,
513 c_globals: &IdxVec<GlobalIdx, T>,
514 ) -> Result<Self, ValidationError> {
515 c_globals
516 .validate_index(index)
517 .ok_or(ValidationError::InvalidGlobalIdx(index))
518 }
519
520 pub fn read_and_validate<T>(
523 wasm: &mut WasmReader,
524 c_globals: &IdxVec<GlobalIdx, T>,
525 ) -> Result<Self, ValidationError> {
526 let index = wasm.read_var_u32()?;
527 Self::validate(index, c_globals)
528 }
529
530 pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
538 let index = wasm.read_var_u32().unwrap();
539 Self::new(index)
540 }
541}
542
543#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
544pub struct ElemIdx(u32);
545
546impl core::fmt::Display for ElemIdx {
547 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
548 write!(f, "element index {}", self.0)
549 }
550}
551
552impl Idx for ElemIdx {
553 fn new(index: u32) -> Self {
554 Self(index)
555 }
556
557 fn into_inner(self) -> u32 {
558 self.0
559 }
560}
561
562impl ElemIdx {
563 pub fn validate<T>(index: u32, c_elems: &IdxVec<ElemIdx, T>) -> Result<Self, ValidationError> {
568 c_elems
569 .validate_index(index)
570 .ok_or(ValidationError::InvalidElemIdx(index))
571 }
572
573 pub fn read_and_validate<T>(
576 wasm: &mut WasmReader,
577 c_elems: &IdxVec<ElemIdx, T>,
578 ) -> Result<Self, ValidationError> {
579 let index = wasm.read_var_u32()?;
580 Self::validate(index, c_elems)
581 }
582
583 pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
591 let index = wasm.read_var_u32().unwrap();
592 Self::new(index)
593 }
594}
595
596#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
597pub struct DataIdx(u32);
598
599impl core::fmt::Display for DataIdx {
600 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
601 write!(f, "data index {}", self.0)
602 }
603}
604
605impl Idx for DataIdx {
606 fn new(index: u32) -> Self {
607 Self(index)
608 }
609
610 fn into_inner(self) -> u32 {
611 self.0
612 }
613}
614
615impl DataIdx {
616 pub fn validate(index: u32, data_count: u32) -> Result<Self, ValidationError> {
621 (index < data_count)
622 .then_some(Self(index))
623 .ok_or(ValidationError::InvalidDataIdx(index))
624 }
625
626 pub fn read_and_validate(
629 wasm: &mut WasmReader,
630 data_count: u32,
631 ) -> Result<Self, ValidationError> {
632 let index = wasm.read_var_u32()?;
633 Self::validate(index, data_count)
634 }
635
636 pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
644 let index = wasm.read_var_u32().unwrap();
645 Self::new(index)
646 }
647}
648
649#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
650pub struct LocalIdx(u32);
651
652impl core::fmt::Display for LocalIdx {
653 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
654 write!(f, "local index {}", self.0)
655 }
656}
657
658impl LocalIdx {
659 pub fn into_inner(self) -> u32 {
660 self.0
661 }
662
663 pub fn read_and_validate(
666 wasm: &mut WasmReader,
667 locals_of_current_function: &[ValType],
668 ) -> Result<Self, ValidationError> {
669 let index = wasm.read_var_u32()?;
670 let index_as_usize = usize::try_from(index).expect("architecture to be at least 32 bits");
671
672 match locals_of_current_function.get(index_as_usize) {
673 Some(_local) => Ok(Self(index)),
674 None => Err(ValidationError::InvalidLocalIdx(index)),
675 }
676 }
677
678 pub unsafe fn read_unchecked(wasm: &mut WasmReader) -> Self {
685 let index = wasm.read_var_u32().unwrap();
686 Self(index)
687 }
688}
689
690pub fn read_label_idx(wasm: &mut WasmReader) -> Result<u32, ValidationError> {
692 wasm.read_var_u32()
693}
694
695pub unsafe fn read_label_idx_unchecked(wasm: &mut WasmReader) -> u32 {
702 wasm.read_var_u32().unwrap()
704}