1use super::{component::ComponentState, core::Module};
4use crate::{
5 ComponentExport, ComponentImport, Export, ExternalKind, FuncType, GlobalType, Import,
6 MemoryType, PrimitiveValType, TableType, TypeRef, ValType,
7};
8use ::alloc::borrow::ToOwned;
9use ::alloc::boxed::Box;
10use ::alloc::collections::BTreeMap;
11use ::alloc::string::String as Url;
12use ::alloc::string::String;
13use ::alloc::string::ToString;
14use ::alloc::sync::Arc;
15use ::alloc::vec::Vec;
16use ::core::{
17 borrow::Borrow,
18 fmt,
19 hash::{Hash, Hasher},
20 mem,
21 ops::{Deref, DerefMut},
22};
23use indexmap::{IndexMap, IndexSet};
24
25const MAX_FLAT_FUNC_PARAMS: usize = 16;
30const MAX_FLAT_FUNC_RESULTS: usize = 1;
35
36const MAX_LOWERED_TYPES: usize = MAX_FLAT_FUNC_PARAMS + 1;
38
39#[derive(Debug, Eq, Ord)]
48#[repr(transparent)]
49pub struct KebabStr(str);
50
51impl KebabStr {
52 pub fn new<'a>(s: impl AsRef<str> + 'a) -> Option<&'a Self> {
56 let s = Self::new_unchecked(s);
57 if s.is_kebab_case() {
58 Some(s)
59 } else {
60 None
61 }
62 }
63
64 pub(crate) fn new_unchecked<'a>(s: impl AsRef<str> + 'a) -> &'a Self {
65 unsafe { ::core::mem::transmute::<_, &Self>(s.as_ref()) }
68 }
69
70 pub fn as_str(&self) -> &str {
72 &self.0
73 }
74
75 pub fn to_kebab_string(&self) -> KebabString {
77 KebabString(self.to_string())
78 }
79
80 fn is_kebab_case(&self) -> bool {
81 let mut lower = false;
82 let mut upper = false;
83 for c in self.chars() {
84 match c {
85 'a'..='z' if !lower && !upper => lower = true,
86 'A'..='Z' if !lower && !upper => upper = true,
87 'a'..='z' if lower => {}
88 'A'..='Z' if upper => {}
89 '0'..='9' if lower || upper => {}
90 '-' if lower || upper => {
91 lower = false;
92 upper = false;
93 }
94 _ => return false,
95 }
96 }
97
98 !self.is_empty() && !self.ends_with('-')
99 }
100}
101
102impl Deref for KebabStr {
103 type Target = str;
104
105 fn deref(&self) -> &str {
106 self.as_str()
107 }
108}
109
110impl PartialOrd for KebabStr {
111 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
112 if self.eq(other) {
113 return Some(core::cmp::Ordering::Equal);
114 }
115 self.0.partial_cmp(&other.0)
116 }
117}
118
119impl PartialOrd<KebabString> for KebabStr {
120 fn partial_cmp(&self, other: &KebabString) -> Option<core::cmp::Ordering> {
121 self.partial_cmp(other.as_kebab_str())
122 }
123}
124
125impl PartialEq for KebabStr {
126 fn eq(&self, other: &Self) -> bool {
127 if self.len() != other.len() {
128 return false;
129 }
130
131 self.chars()
132 .zip(other.chars())
133 .all(|(a, b)| a.to_ascii_lowercase() == b.to_ascii_lowercase())
134 }
135}
136
137impl PartialEq<KebabString> for KebabStr {
138 fn eq(&self, other: &KebabString) -> bool {
139 self.eq(other.as_kebab_str())
140 }
141}
142
143impl Hash for KebabStr {
144 fn hash<H: Hasher>(&self, state: &mut H) {
145 self.len().hash(state);
146
147 for b in self.chars() {
148 b.to_ascii_lowercase().hash(state);
149 }
150 }
151}
152
153impl fmt::Display for KebabStr {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 (self as &str).fmt(f)
156 }
157}
158
159impl ToOwned for KebabStr {
160 type Owned = KebabString;
161
162 fn to_owned(&self) -> Self::Owned {
163 self.to_kebab_string()
164 }
165}
166
167#[derive(Debug, Clone, Eq, Ord)]
176pub struct KebabString(String);
177
178impl KebabString {
179 pub fn new(s: impl Into<String>) -> Option<Self> {
183 let s = s.into();
184 if KebabStr::new(&s).is_some() {
185 Some(Self(s))
186 } else {
187 None
188 }
189 }
190
191 pub fn as_str(&self) -> &str {
193 self.0.as_str()
194 }
195
196 pub fn as_kebab_str(&self) -> &KebabStr {
198 KebabStr::new_unchecked(self.as_str())
200 }
201}
202
203impl Deref for KebabString {
204 type Target = KebabStr;
205
206 fn deref(&self) -> &Self::Target {
207 self.as_kebab_str()
208 }
209}
210
211impl Borrow<KebabStr> for KebabString {
212 fn borrow(&self) -> &KebabStr {
213 self.as_kebab_str()
214 }
215}
216
217impl PartialOrd for KebabString {
218 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
219 self.as_kebab_str().partial_cmp(other.as_kebab_str())
220 }
221}
222
223impl PartialOrd<KebabStr> for KebabString {
224 fn partial_cmp(&self, other: &KebabStr) -> Option<core::cmp::Ordering> {
225 self.as_kebab_str().partial_cmp(other)
226 }
227}
228
229impl PartialEq for KebabString {
230 fn eq(&self, other: &Self) -> bool {
231 self.as_kebab_str().eq(other.as_kebab_str())
232 }
233}
234
235impl PartialEq<KebabStr> for KebabString {
236 fn eq(&self, other: &KebabStr) -> bool {
237 self.as_kebab_str().eq(other)
238 }
239}
240
241impl Hash for KebabString {
242 fn hash<H: Hasher>(&self, state: &mut H) {
243 self.as_kebab_str().hash(state)
244 }
245}
246
247impl fmt::Display for KebabString {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 self.as_kebab_str().fmt(f)
250 }
251}
252
253impl From<KebabString> for String {
254 fn from(s: KebabString) -> String {
255 s.0
256 }
257}
258
259pub(crate) struct LoweredTypes {
261 types: [ValType; MAX_LOWERED_TYPES],
262 len: usize,
263 max: usize,
264}
265
266impl LoweredTypes {
267 fn new(max: usize) -> Self {
268 assert!(max <= MAX_LOWERED_TYPES);
269 Self {
270 types: [ValType::I32; MAX_LOWERED_TYPES],
271 len: 0,
272 max,
273 }
274 }
275
276 fn len(&self) -> usize {
277 self.len
278 }
279
280 fn maxed(&self) -> bool {
281 self.len == self.max
282 }
283
284 fn get_mut(&mut self, index: usize) -> Option<&mut ValType> {
285 if index < self.len {
286 Some(&mut self.types[index])
287 } else {
288 None
289 }
290 }
291
292 fn push(&mut self, ty: ValType) -> bool {
293 if self.maxed() {
294 return false;
295 }
296
297 self.types[self.len] = ty;
298 self.len += 1;
299 true
300 }
301
302 fn clear(&mut self) {
303 self.len = 0;
304 }
305
306 pub fn as_slice(&self) -> &[ValType] {
307 &self.types[..self.len]
308 }
309
310 pub fn iter(&self) -> impl Iterator<Item = ValType> + '_ {
311 self.as_slice().iter().copied()
312 }
313}
314
315pub(crate) struct LoweringInfo {
317 pub(crate) params: LoweredTypes,
318 pub(crate) results: LoweredTypes,
319 pub(crate) requires_memory: bool,
320 pub(crate) requires_realloc: bool,
321}
322
323impl LoweringInfo {
324 pub(crate) fn into_func_type(self) -> FuncType {
325 FuncType::new(
326 self.params.as_slice().iter().copied(),
327 self.results.as_slice().iter().copied(),
328 )
329 }
330}
331
332impl Default for LoweringInfo {
333 fn default() -> Self {
334 Self {
335 params: LoweredTypes::new(MAX_FLAT_FUNC_PARAMS),
336 results: LoweredTypes::new(MAX_FLAT_FUNC_RESULTS),
337 requires_memory: false,
338 requires_realloc: false,
339 }
340 }
341}
342
343fn push_primitive_wasm_types(ty: &PrimitiveValType, lowered_types: &mut LoweredTypes) -> bool {
344 match ty {
345 PrimitiveValType::Bool
346 | PrimitiveValType::S8
347 | PrimitiveValType::U8
348 | PrimitiveValType::S16
349 | PrimitiveValType::U16
350 | PrimitiveValType::S32
351 | PrimitiveValType::U32
352 | PrimitiveValType::Char => lowered_types.push(ValType::I32),
353 PrimitiveValType::S64 | PrimitiveValType::U64 => lowered_types.push(ValType::I64),
354 PrimitiveValType::Float32 => lowered_types.push(ValType::F32),
355 PrimitiveValType::Float64 => lowered_types.push(ValType::F64),
356 PrimitiveValType::String => {
357 lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32)
358 }
359 }
360}
361
362#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
364pub struct TypeId {
365 pub(crate) index: usize,
367 pub(crate) type_size: u32,
372 unique_id: u32,
379}
380
381const _: () = {
384 assert!(::core::mem::size_of::<TypeId>() <= 16);
385};
386
387#[derive(Debug)]
389pub enum Type {
390 Func(FuncType),
392 Module(ModuleType),
396 Instance(InstanceType),
400 Component(ComponentType),
404 ComponentInstance(ComponentInstanceType),
408 ComponentFunc(ComponentFuncType),
412 Defined(ComponentDefinedType),
416}
417
418impl Type {
419 pub fn as_func_type(&self) -> Option<&FuncType> {
421 match self {
422 Self::Func(ty) => Some(ty),
423 _ => None,
424 }
425 }
426
427 pub fn as_module_type(&self) -> Option<&ModuleType> {
429 match self {
430 Self::Module(ty) => Some(ty),
431 _ => None,
432 }
433 }
434
435 pub fn as_instance_type(&self) -> Option<&InstanceType> {
437 match self {
438 Self::Instance(ty) => Some(ty),
439 _ => None,
440 }
441 }
442
443 pub fn as_component_type(&self) -> Option<&ComponentType> {
445 match self {
446 Self::Component(ty) => Some(ty),
447 _ => None,
448 }
449 }
450
451 pub fn as_component_instance_type(&self) -> Option<&ComponentInstanceType> {
453 match self {
454 Self::ComponentInstance(ty) => Some(ty),
455 _ => None,
456 }
457 }
458
459 pub fn as_component_func_type(&self) -> Option<&ComponentFuncType> {
461 match self {
462 Self::ComponentFunc(ty) => Some(ty),
463 _ => None,
464 }
465 }
466
467 pub fn as_defined_type(&self) -> Option<&ComponentDefinedType> {
469 match self {
470 Self::Defined(ty) => Some(ty),
471 _ => None,
472 }
473 }
474
475 pub(crate) fn type_size(&self) -> u32 {
476 match self {
477 Self::Func(ty) => 1 + (ty.params().len() + ty.results().len()) as u32,
478 Self::Module(ty) => ty.type_size,
479 Self::Instance(ty) => ty.type_size,
480 Self::Component(ty) => ty.type_size,
481 Self::ComponentInstance(ty) => ty.type_size,
482 Self::ComponentFunc(ty) => ty.type_size,
483 Self::Defined(ty) => ty.type_size(),
484 }
485 }
486}
487
488#[derive(Debug, Clone, Copy)]
490pub enum ComponentValType {
491 Primitive(PrimitiveValType),
493 Type(TypeId),
495}
496
497impl ComponentValType {
498 pub(crate) fn requires_realloc(&self, types: &TypeList) -> bool {
499 match self {
500 ComponentValType::Primitive(ty) => ty.requires_realloc(),
501 ComponentValType::Type(ty) => types[*ty]
502 .as_defined_type()
503 .unwrap()
504 .requires_realloc(types),
505 }
506 }
507
508 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
510 Self::internal_is_subtype_of(a, at.list, b, bt.list)
511 }
512
513 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
514 match (a, b) {
515 (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
516 PrimitiveValType::is_subtype_of(*a, *b)
517 }
518 (ComponentValType::Type(a), ComponentValType::Type(b)) => {
519 ComponentDefinedType::internal_is_subtype_of(
520 at[*a].as_defined_type().unwrap(),
521 at,
522 bt[*b].as_defined_type().unwrap(),
523 bt,
524 )
525 }
526 (ComponentValType::Primitive(a), ComponentValType::Type(b)) => {
527 match bt[*b].as_defined_type().unwrap() {
528 ComponentDefinedType::Primitive(b) => PrimitiveValType::is_subtype_of(*a, *b),
529 _ => false,
530 }
531 }
532 (ComponentValType::Type(a), ComponentValType::Primitive(b)) => {
533 match at[*a].as_defined_type().unwrap() {
534 ComponentDefinedType::Primitive(a) => PrimitiveValType::is_subtype_of(*a, *b),
535 _ => false,
536 }
537 }
538 }
539 }
540
541 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
542 match self {
543 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
544 Self::Type(id) => types[*id]
545 .as_defined_type()
546 .unwrap()
547 .push_wasm_types(types, lowered_types),
548 }
549 }
550
551 pub(crate) fn type_size(&self) -> u32 {
552 match self {
553 Self::Primitive(_) => 1,
554 Self::Type(id) => id.type_size,
555 }
556 }
557}
558
559#[derive(Debug, Clone, Copy)]
561pub enum EntityType {
562 Func(TypeId),
564 Table(TableType),
566 Memory(MemoryType),
568 Global(GlobalType),
570 Tag(TypeId),
572}
573
574impl EntityType {
575 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
577 Self::internal_is_subtype_of(a, at.list, b, bt.list)
578 }
579
580 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
581 macro_rules! limits_match {
582 ($a:expr, $b:expr) => {{
583 let a = $a;
584 let b = $b;
585 a.initial >= b.initial
586 && match b.maximum {
587 Some(b_max) => match a.maximum {
588 Some(a_max) => a_max <= b_max,
589 None => false,
590 },
591 None => true,
592 }
593 }};
594 }
595
596 match (a, b) {
597 (EntityType::Func(a), EntityType::Func(b)) => {
598 at[*a].as_func_type().unwrap() == bt[*b].as_func_type().unwrap()
599 }
600 (EntityType::Table(a), EntityType::Table(b)) => {
601 a.element_type == b.element_type && limits_match!(a, b)
602 }
603 (EntityType::Memory(a), EntityType::Memory(b)) => {
604 a.shared == b.shared && a.memory64 == b.memory64 && limits_match!(a, b)
605 }
606 (EntityType::Global(a), EntityType::Global(b)) => a == b,
607 (EntityType::Tag(a), EntityType::Tag(b)) => {
608 at[*a].as_func_type().unwrap() == bt[*b].as_func_type().unwrap()
609 }
610 _ => false,
611 }
612 }
613
614 pub(crate) fn desc(&self) -> &'static str {
615 match self {
616 Self::Func(_) => "function",
617 Self::Table(_) => "table",
618 Self::Memory(_) => "memory",
619 Self::Global(_) => "global",
620 Self::Tag(_) => "tag",
621 }
622 }
623
624 pub(crate) fn type_size(&self) -> u32 {
625 match self {
626 Self::Func(id) | Self::Tag(id) => id.type_size,
627 Self::Table(_) | Self::Memory(_) | Self::Global(_) => 1,
628 }
629 }
630}
631
632trait ModuleImportKey {
633 fn module(&self) -> &str;
634 fn name(&self) -> &str;
635}
636
637impl<'a> Borrow<dyn ModuleImportKey + 'a> for (String, String) {
638 fn borrow(&self) -> &(dyn ModuleImportKey + 'a) {
639 self
640 }
641}
642
643impl Hash for (dyn ModuleImportKey + '_) {
644 fn hash<H: Hasher>(&self, state: &mut H) {
645 self.module().hash(state);
646 self.name().hash(state);
647 }
648}
649
650impl PartialOrd for (dyn ModuleImportKey + '_) {
651 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
652 Some(self.cmp(other))
653 }
654}
655
656impl Ord for (dyn ModuleImportKey + '_) {
657 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
658 self.module()
659 .cmp(other.module())
660 .then(self.name().cmp(other.name()))
661 }
662}
663
664impl PartialEq for (dyn ModuleImportKey + '_) {
665 fn eq(&self, other: &Self) -> bool {
666 self.module() == other.module() && self.name() == other.name()
667 }
668}
669
670impl Eq for (dyn ModuleImportKey + '_) {}
671
672impl ModuleImportKey for (String, String) {
673 fn module(&self) -> &str {
674 &self.0
675 }
676
677 fn name(&self) -> &str {
678 &self.1
679 }
680}
681
682impl ModuleImportKey for (&str, &str) {
683 fn module(&self) -> &str {
684 self.0
685 }
686
687 fn name(&self) -> &str {
688 self.1
689 }
690}
691
692#[derive(Debug, Clone)]
694pub struct ModuleType {
695 pub(crate) type_size: u32,
697 pub imports: IndexMap<(String, String), EntityType>,
699 pub exports: IndexMap<String, EntityType>,
701}
702
703impl ModuleType {
704 pub fn lookup_import(&self, module: &str, name: &str) -> Option<&EntityType> {
708 self.imports.get(&(module, name) as &dyn ModuleImportKey)
709 }
710
711 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
713 Self::internal_is_subtype_of(a, at.list, b, bt.list)
714 }
715
716 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
717 a.imports.iter().all(|(k, a)| match b.imports.get(k) {
723 Some(b) => EntityType::internal_is_subtype_of(b, bt, a, at),
724 None => false,
725 }) && b.exports.iter().all(|(k, b)| match a.exports.get(k) {
726 Some(a) => EntityType::internal_is_subtype_of(a, at, b, bt),
727 None => false,
728 })
729 }
730}
731
732#[derive(Debug, Clone)]
734pub enum InstanceTypeKind {
735 Instantiated(TypeId),
737 Exports(IndexMap<String, EntityType>),
739}
740
741#[derive(Debug, Clone)]
743pub struct InstanceType {
744 pub(crate) type_size: u32,
746 pub kind: InstanceTypeKind,
748}
749
750impl InstanceType {
751 pub fn exports<'a>(&'a self, types: TypesRef<'a>) -> &'a IndexMap<String, EntityType> {
753 self.internal_exports(types.list)
754 }
755
756 pub(crate) fn internal_exports<'a>(
757 &'a self,
758 types: &'a TypeList,
759 ) -> &'a IndexMap<String, EntityType> {
760 match &self.kind {
761 InstanceTypeKind::Instantiated(id) => &types[*id].as_module_type().unwrap().exports,
762 InstanceTypeKind::Exports(exports) => exports,
763 }
764 }
765}
766
767#[derive(Debug, Clone, Copy)]
769pub enum ComponentEntityType {
770 Module(TypeId),
772 Func(TypeId),
774 Value(ComponentValType),
776 Type {
778 referenced: TypeId,
781 created: TypeId,
788 },
789 Instance(TypeId),
791 Component(TypeId),
793}
794
795impl ComponentEntityType {
796 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
798 Self::internal_is_subtype_of(a, at.list, b, bt.list)
799 }
800
801 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
802 match (a, b) {
803 (Self::Module(a), Self::Module(b)) => ModuleType::internal_is_subtype_of(
804 at[*a].as_module_type().unwrap(),
805 at,
806 bt[*b].as_module_type().unwrap(),
807 bt,
808 ),
809 (Self::Func(a), Self::Func(b)) => ComponentFuncType::internal_is_subtype_of(
810 at[*a].as_component_func_type().unwrap(),
811 at,
812 bt[*b].as_component_func_type().unwrap(),
813 bt,
814 ),
815 (Self::Value(a), Self::Value(b)) => {
816 ComponentValType::internal_is_subtype_of(a, at, b, bt)
817 }
818 (Self::Type { referenced: a, .. }, Self::Type { referenced: b, .. }) => {
819 ComponentDefinedType::internal_is_subtype_of(
820 at[*a].as_defined_type().unwrap(),
821 at,
822 bt[*b].as_defined_type().unwrap(),
823 bt,
824 )
825 }
826 (Self::Instance(a), Self::Instance(b)) => {
827 ComponentInstanceType::internal_is_subtype_of(
828 at[*a].as_component_instance_type().unwrap(),
829 at,
830 bt[*b].as_component_instance_type().unwrap(),
831 bt,
832 )
833 }
834 (Self::Component(a), Self::Component(b)) => ComponentType::internal_is_subtype_of(
835 at[*a].as_component_type().unwrap(),
836 at,
837 bt[*b].as_component_type().unwrap(),
838 bt,
839 ),
840 _ => false,
841 }
842 }
843
844 pub(crate) fn desc(&self) -> &'static str {
845 match self {
846 Self::Module(_) => "module",
847 Self::Func(_) => "function",
848 Self::Value(_) => "value",
849 Self::Type { .. } => "type",
850 Self::Instance(_) => "instance",
851 Self::Component(_) => "component",
852 }
853 }
854
855 pub(crate) fn type_size(&self) -> u32 {
856 match self {
857 Self::Module(ty)
858 | Self::Func(ty)
859 | Self::Type { referenced: ty, .. }
860 | Self::Instance(ty)
861 | Self::Component(ty) => ty.type_size,
862 Self::Value(ty) => ty.type_size(),
863 }
864 }
865}
866
867#[derive(Debug, Clone)]
869pub struct ComponentType {
870 pub(crate) type_size: u32,
872 pub imports: IndexMap<KebabString, (Option<Url>, ComponentEntityType)>,
874 pub exports: IndexMap<KebabString, (Option<Url>, ComponentEntityType)>,
876}
877
878impl ComponentType {
879 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
881 Self::internal_is_subtype_of(a, at.list, b, bt.list)
882 }
883
884 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
885 a.imports.iter().all(|(k, (_, a))| match b.imports.get(k) {
891 Some((_, b)) => ComponentEntityType::internal_is_subtype_of(b, bt, a, at),
892 None => false,
893 }) && b.exports.iter().all(|(k, (_, b))| match a.exports.get(k) {
894 Some((_, a)) => ComponentEntityType::internal_is_subtype_of(a, at, b, bt),
895 None => false,
896 })
897 }
898}
899
900#[derive(Debug, Clone)]
902pub enum ComponentInstanceTypeKind {
903 Defined(IndexMap<KebabString, (Option<Url>, ComponentEntityType)>),
905 Instantiated(TypeId),
907 Exports(IndexMap<KebabString, (Option<Url>, ComponentEntityType)>),
909}
910
911#[derive(Debug, Clone)]
913pub struct ComponentInstanceType {
914 pub(crate) type_size: u32,
916 pub kind: ComponentInstanceTypeKind,
918}
919
920impl ComponentInstanceType {
921 pub fn exports<'a>(
923 &'a self,
924 types: TypesRef<'a>,
925 ) -> impl ExactSizeIterator<Item = (&'a KebabStr, &'a Option<Url>, ComponentEntityType)> + Clone
926 {
927 self.internal_exports(types.list)
928 .iter()
929 .map(|(n, (u, t))| (n.as_kebab_str(), u, *t))
930 }
931
932 pub(crate) fn internal_exports<'a>(
933 &'a self,
934 types: &'a TypeList,
935 ) -> &'a IndexMap<KebabString, (Option<Url>, ComponentEntityType)> {
936 match &self.kind {
937 ComponentInstanceTypeKind::Defined(exports)
938 | ComponentInstanceTypeKind::Exports(exports) => exports,
939 ComponentInstanceTypeKind::Instantiated(id) => {
940 &types[*id].as_component_type().unwrap().exports
941 }
942 }
943 }
944
945 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
947 Self::internal_is_subtype_of(a, at.list, b, bt.list)
948 }
949
950 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
951 let exports = a.internal_exports(at);
952
953 b.internal_exports(bt)
957 .iter()
958 .all(|(k, (_, b))| match exports.get(k) {
959 Some((_, a)) => ComponentEntityType::internal_is_subtype_of(a, at, b, bt),
960 None => false,
961 })
962 }
963}
964
965#[derive(Debug, Clone)]
967pub struct ComponentFuncType {
968 pub(crate) type_size: u32,
970 pub params: Box<[(KebabString, ComponentValType)]>,
972 pub results: Box<[(Option<KebabString>, ComponentValType)]>,
974}
975
976impl ComponentFuncType {
977 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
979 Self::internal_is_subtype_of(a, at.list, b, bt.list)
980 }
981
982 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
983 a.params.len() == b.params.len()
1010 && a.results.len() == b.results.len()
1011 && a.params
1012 .iter()
1013 .zip(b.params.iter())
1014 .all(|((an, a), (bn, b))| {
1015 an == bn && ComponentValType::internal_is_subtype_of(a, at, b, bt)
1016 })
1017 && a.results
1018 .iter()
1019 .zip(b.results.iter())
1020 .all(|((an, a), (bn, b))| {
1021 an == bn && ComponentValType::internal_is_subtype_of(a, at, b, bt)
1022 })
1023 }
1024
1025 pub(crate) fn lower(&self, types: &TypeList, import: bool) -> LoweringInfo {
1028 let mut info = LoweringInfo::default();
1029
1030 for (_, ty) in self.params.iter() {
1031 if !import && !info.requires_realloc {
1034 info.requires_realloc = ty.requires_realloc(types);
1035 }
1036
1037 if !ty.push_wasm_types(types, &mut info.params) {
1038 info.params.clear();
1042 assert!(info.params.push(ValType::I32));
1043 info.requires_memory = true;
1044
1045 if !import {
1047 info.requires_realloc = true;
1048 }
1049 break;
1050 }
1051 }
1052
1053 for (_, ty) in self.results.iter() {
1054 if import && !info.requires_realloc {
1057 info.requires_realloc = ty.requires_realloc(types);
1058 }
1059
1060 if !ty.push_wasm_types(types, &mut info.results) {
1061 info.results.clear();
1064 if import {
1065 info.params.max = MAX_LOWERED_TYPES;
1066 assert!(info.params.push(ValType::I32));
1067 } else {
1068 assert!(info.results.push(ValType::I32));
1069 }
1070 info.requires_memory = true;
1071 break;
1072 }
1073 }
1074
1075 info.requires_memory |= info.requires_realloc;
1077
1078 info
1079 }
1080}
1081
1082#[derive(Debug, Clone)]
1084pub struct VariantCase {
1085 pub ty: Option<ComponentValType>,
1087 pub refines: Option<KebabString>,
1089}
1090
1091#[derive(Debug, Clone)]
1093pub struct RecordType {
1094 pub(crate) type_size: u32,
1096 pub fields: IndexMap<KebabString, ComponentValType>,
1098}
1099
1100#[derive(Debug, Clone)]
1102pub struct VariantType {
1103 pub(crate) type_size: u32,
1105 pub cases: IndexMap<KebabString, VariantCase>,
1107}
1108
1109#[derive(Debug, Clone)]
1111pub struct TupleType {
1112 pub(crate) type_size: u32,
1114 pub types: Box<[ComponentValType]>,
1116}
1117
1118#[derive(Debug, Clone)]
1120pub struct UnionType {
1121 pub(crate) type_size: u32,
1123 pub types: Box<[ComponentValType]>,
1125}
1126
1127#[derive(Debug, Clone)]
1129pub enum ComponentDefinedType {
1130 Primitive(PrimitiveValType),
1132 Record(RecordType),
1134 Variant(VariantType),
1136 List(ComponentValType),
1138 Tuple(TupleType),
1140 Flags(IndexSet<KebabString>),
1142 Enum(IndexSet<KebabString>),
1144 Union(UnionType),
1146 Option(ComponentValType),
1148 Result {
1150 ok: Option<ComponentValType>,
1152 err: Option<ComponentValType>,
1154 },
1155}
1156
1157impl ComponentDefinedType {
1158 pub(crate) fn requires_realloc(&self, types: &TypeList) -> bool {
1159 match self {
1160 Self::Primitive(ty) => ty.requires_realloc(),
1161 Self::Record(r) => r.fields.values().any(|ty| ty.requires_realloc(types)),
1162 Self::Variant(v) => v.cases.values().any(|case| {
1163 case.ty
1164 .map(|ty| ty.requires_realloc(types))
1165 .unwrap_or(false)
1166 }),
1167 Self::List(_) => true,
1168 Self::Tuple(t) => t.types.iter().any(|ty| ty.requires_realloc(types)),
1169 Self::Union(u) => u.types.iter().any(|ty| ty.requires_realloc(types)),
1170 Self::Flags(_) | Self::Enum(_) => false,
1171 Self::Option(ty) => ty.requires_realloc(types),
1172 Self::Result { ok, err } => {
1173 ok.map(|ty| ty.requires_realloc(types)).unwrap_or(false)
1174 || err.map(|ty| ty.requires_realloc(types)).unwrap_or(false)
1175 }
1176 }
1177 }
1178
1179 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
1181 Self::internal_is_subtype_of(a, at.list, b, bt.list)
1182 }
1183
1184 pub(crate) fn internal_is_subtype_of(a: &Self, at: &TypeList, b: &Self, bt: &TypeList) -> bool {
1185 match (a, b) {
1189 (Self::Primitive(a), Self::Primitive(b)) => PrimitiveValType::is_subtype_of(*a, *b),
1190 (Self::Record(a), Self::Record(b)) => {
1191 a.fields.len() == b.fields.len()
1192 && a.fields
1193 .iter()
1194 .zip(b.fields.iter())
1195 .all(|((aname, a), (bname, b))| {
1196 aname == bname && ComponentValType::internal_is_subtype_of(a, at, b, bt)
1197 })
1198 }
1199 (Self::Variant(a), Self::Variant(b)) => {
1200 a.cases.len() == b.cases.len()
1201 && a.cases
1202 .iter()
1203 .zip(b.cases.iter())
1204 .all(|((aname, a), (bname, b))| {
1205 aname == bname
1206 && match (&a.ty, &b.ty) {
1207 (Some(a), Some(b)) => {
1208 ComponentValType::internal_is_subtype_of(a, at, b, bt)
1209 }
1210 (None, None) => true,
1211 _ => false,
1212 }
1213 })
1214 }
1215 (Self::List(a), Self::List(b)) | (Self::Option(a), Self::Option(b)) => {
1216 ComponentValType::internal_is_subtype_of(a, at, b, bt)
1217 }
1218 (Self::Tuple(a), Self::Tuple(b)) => {
1219 if a.types.len() != b.types.len() {
1220 return false;
1221 }
1222 a.types
1223 .iter()
1224 .zip(b.types.iter())
1225 .all(|(a, b)| ComponentValType::internal_is_subtype_of(a, at, b, bt))
1226 }
1227 (Self::Union(a), Self::Union(b)) => {
1228 if a.types.len() != b.types.len() {
1229 return false;
1230 }
1231 a.types
1232 .iter()
1233 .zip(b.types.iter())
1234 .all(|(a, b)| ComponentValType::internal_is_subtype_of(a, at, b, bt))
1235 }
1236 (Self::Flags(a), Self::Flags(b)) | (Self::Enum(a), Self::Enum(b)) => {
1237 a.len() == b.len() && a.iter().eq(b.iter())
1238 }
1239 (Self::Result { ok: ao, err: ae }, Self::Result { ok: bo, err: be }) => {
1240 Self::is_optional_subtype_of(*ao, at, *bo, bt)
1241 && Self::is_optional_subtype_of(*ae, at, *be, bt)
1242 }
1243 _ => false,
1244 }
1245 }
1246
1247 pub(crate) fn type_size(&self) -> u32 {
1248 match self {
1249 Self::Primitive(_) => 1,
1250 Self::Flags(_) | Self::Enum(_) => 1,
1251 Self::Record(r) => r.type_size,
1252 Self::Variant(v) => v.type_size,
1253 Self::Tuple(t) => t.type_size,
1254 Self::Union(u) => u.type_size,
1255 Self::List(ty) | Self::Option(ty) => ty.type_size(),
1256 Self::Result { ok, err } => {
1257 ok.map(|ty| ty.type_size()).unwrap_or(1) + err.map(|ty| ty.type_size()).unwrap_or(1)
1258 }
1259 }
1260 }
1261
1262 fn is_optional_subtype_of(
1263 a: Option<ComponentValType>,
1264 at: &TypeList,
1265 b: Option<ComponentValType>,
1266 bt: &TypeList,
1267 ) -> bool {
1268 match (a, b) {
1269 (None, None) => true,
1270 (Some(a), Some(b)) => ComponentValType::internal_is_subtype_of(&a, at, &b, bt),
1271 _ => false,
1272 }
1273 }
1274 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1275 match self {
1276 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1277 Self::Record(r) => r
1278 .fields
1279 .iter()
1280 .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1281 Self::Variant(v) => Self::push_variant_wasm_types(
1282 v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1283 types,
1284 lowered_types,
1285 ),
1286 Self::List(_) => lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32),
1287 Self::Tuple(t) => t
1288 .types
1289 .iter()
1290 .all(|ty| ty.push_wasm_types(types, lowered_types)),
1291 Self::Flags(names) => {
1292 (0..(names.len() + 31) / 32).all(|_| lowered_types.push(ValType::I32))
1293 }
1294 Self::Enum(_) => lowered_types.push(ValType::I32),
1295 Self::Union(u) => Self::push_variant_wasm_types(u.types.iter(), types, lowered_types),
1296 Self::Option(ty) => {
1297 Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1298 }
1299 Self::Result { ok, err } => {
1300 Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1301 }
1302 }
1303 }
1304
1305 fn push_variant_wasm_types<'a>(
1306 cases: impl Iterator<Item = &'a ComponentValType>,
1307 types: &TypeList,
1308 lowered_types: &mut LoweredTypes,
1309 ) -> bool {
1310 if !lowered_types.push(ValType::I32) {
1312 return false;
1313 }
1314
1315 let start = lowered_types.len();
1316
1317 for ty in cases {
1318 let mut temp = LoweredTypes::new(lowered_types.max);
1319
1320 if !ty.push_wasm_types(types, &mut temp) {
1321 return false;
1322 }
1323
1324 for (i, ty) in temp.iter().enumerate() {
1325 match lowered_types.get_mut(start + i) {
1326 Some(prev) => *prev = Self::join_types(*prev, ty),
1327 None => {
1328 if !lowered_types.push(ty) {
1329 return false;
1330 }
1331 }
1332 }
1333 }
1334 }
1335
1336 true
1337 }
1338
1339 fn join_types(a: ValType, b: ValType) -> ValType {
1340 use ValType::*;
1341
1342 match (a, b) {
1343 (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1344 (I32, F32) | (F32, I32) => I32,
1345 (_, I64 | F64) | (I64 | F64, _) => I64,
1346 _ => panic!("unexpected wasm type for canonical ABI"),
1347 }
1348 }
1349}
1350
1351#[allow(clippy::large_enum_variant)]
1352enum TypesKind {
1353 Module(Arc<Module>),
1354 Component(ComponentState),
1355}
1356
1357pub struct Types {
1361 list: TypeList,
1362 kind: TypesKind,
1363}
1364
1365#[derive(Clone, Copy)]
1366enum TypesRefKind<'a> {
1367 Module(&'a Module),
1368 Component(&'a ComponentState),
1369}
1370
1371#[derive(Clone, Copy)]
1375pub struct TypesRef<'a> {
1376 list: &'a TypeList,
1377 kind: TypesRefKind<'a>,
1378}
1379
1380impl<'a> TypesRef<'a> {
1381 pub(crate) fn from_module(types: &'a TypeList, module: &'a Module) -> Self {
1382 Self {
1383 list: types,
1384 kind: TypesRefKind::Module(module),
1385 }
1386 }
1387
1388 pub(crate) fn from_component(types: &'a TypeList, component: &'a ComponentState) -> Self {
1389 Self {
1390 list: types,
1391 kind: TypesRefKind::Component(component),
1392 }
1393 }
1394
1395 fn types(&self, core: bool) -> Option<&'a [TypeId]> {
1396 Some(match &self.kind {
1397 TypesRefKind::Module(module) => {
1398 if core {
1399 &module.types
1400 } else {
1401 return None;
1402 }
1403 }
1404 TypesRefKind::Component(component) => {
1405 if core {
1406 &component.core_types
1407 } else {
1408 &component.types
1409 }
1410 }
1411 })
1412 }
1413
1414 pub fn type_from_id(&self, id: TypeId) -> Option<&'a Type> {
1418 self.list.get(id.index)
1419 }
1420
1421 pub fn id_from_type_index(&self, index: u32, core: bool) -> Option<TypeId> {
1426 self.types(core)?.get(index as usize).copied()
1427 }
1428
1429 pub fn type_at(&self, index: u32, core: bool) -> Option<&'a Type> {
1434 self.type_from_id(*self.types(core)?.get(index as usize)?)
1435 }
1436
1437 pub fn func_type_at(&self, index: u32) -> Option<&'a FuncType> {
1442 match self.type_at(index, true)? {
1443 Type::Func(ty) => Some(ty),
1444 _ => None,
1445 }
1446 }
1447
1448 pub fn table_at(&self, index: u32) -> Option<TableType> {
1453 let tables = match &self.kind {
1454 TypesRefKind::Module(module) => &module.tables,
1455 TypesRefKind::Component(component) => &component.core_tables,
1456 };
1457
1458 tables.get(index as usize).copied()
1459 }
1460
1461 pub fn memory_at(&self, index: u32) -> Option<MemoryType> {
1466 let memories = match &self.kind {
1467 TypesRefKind::Module(module) => &module.memories,
1468 TypesRefKind::Component(component) => &component.core_memories,
1469 };
1470
1471 memories.get(index as usize).copied()
1472 }
1473
1474 pub fn global_at(&self, index: u32) -> Option<GlobalType> {
1479 let globals = match &self.kind {
1480 TypesRefKind::Module(module) => &module.globals,
1481 TypesRefKind::Component(component) => &component.core_globals,
1482 };
1483
1484 globals.get(index as usize).copied()
1485 }
1486
1487 pub fn tag_at(&self, index: u32) -> Option<&'a FuncType> {
1492 let tags = match &self.kind {
1493 TypesRefKind::Module(module) => &module.tags,
1494 TypesRefKind::Component(component) => &component.core_tags,
1495 };
1496
1497 Some(
1498 self.list[*tags.get(index as usize)?]
1499 .as_func_type()
1500 .unwrap(),
1501 )
1502 }
1503
1504 pub fn function_at(&self, index: u32) -> Option<&'a FuncType> {
1509 let id = match &self.kind {
1510 TypesRefKind::Module(module) => {
1511 &module.types[*module.functions.get(index as usize)? as usize]
1512 }
1513 TypesRefKind::Component(component) => component.core_funcs.get(index as usize)?,
1514 };
1515
1516 match &self.list[*id] {
1517 Type::Func(ty) => Some(ty),
1518 _ => None,
1519 }
1520 }
1521
1522 pub fn element_at(&self, index: u32) -> Option<ValType> {
1527 match &self.kind {
1528 TypesRefKind::Module(module) => module.element_types.get(index as usize).copied(),
1529 TypesRefKind::Component(_) => None,
1530 }
1531 }
1532
1533 pub fn component_function_at(&self, index: u32) -> Option<&'a ComponentFuncType> {
1538 match &self.kind {
1539 TypesRefKind::Module(_) => None,
1540 TypesRefKind::Component(component) => Some(
1541 self.list[*component.funcs.get(index as usize)?]
1542 .as_component_func_type()
1543 .unwrap(),
1544 ),
1545 }
1546 }
1547
1548 pub fn module_at(&self, index: u32) -> Option<&'a ModuleType> {
1553 match &self.kind {
1554 TypesRefKind::Module(_) => None,
1555 TypesRefKind::Component(component) => Some(
1556 self.list[*component.core_modules.get(index as usize)?]
1557 .as_module_type()
1558 .unwrap(),
1559 ),
1560 }
1561 }
1562
1563 pub fn instance_at(&self, index: u32) -> Option<&'a InstanceType> {
1568 match &self.kind {
1569 TypesRefKind::Module(_) => None,
1570 TypesRefKind::Component(component) => {
1571 let id = component.core_instances.get(index as usize)?;
1572 match &self.list[*id] {
1573 Type::Instance(ty) => Some(ty),
1574 _ => None,
1575 }
1576 }
1577 }
1578 }
1579
1580 pub fn component_at(&self, index: u32) -> Option<&'a ComponentType> {
1585 match &self.kind {
1586 TypesRefKind::Module(_) => None,
1587 TypesRefKind::Component(component) => Some(
1588 self.list[*component.components.get(index as usize)?]
1589 .as_component_type()
1590 .unwrap(),
1591 ),
1592 }
1593 }
1594
1595 pub fn component_instance_at(&self, index: u32) -> Option<&'a ComponentInstanceType> {
1600 match &self.kind {
1601 TypesRefKind::Module(_) => None,
1602 TypesRefKind::Component(component) => {
1603 let id = component.instances.get(index as usize)?;
1604 match &self.list[*id] {
1605 Type::ComponentInstance(ty) => Some(ty),
1606 _ => None,
1607 }
1608 }
1609 }
1610 }
1611
1612 pub fn value_at(&self, index: u32) -> Option<ComponentValType> {
1617 match &self.kind {
1618 TypesRefKind::Module(_) => None,
1619 TypesRefKind::Component(component) => {
1620 component.values.get(index as usize).map(|(r, _)| *r)
1621 }
1622 }
1623 }
1624
1625 pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
1627 match &self.kind {
1628 TypesRefKind::Module(module) => Some(match import.ty {
1629 TypeRef::Func(idx) => EntityType::Func(*module.types.get(idx as usize)?),
1630 TypeRef::Table(ty) => EntityType::Table(ty),
1631 TypeRef::Memory(ty) => EntityType::Memory(ty),
1632 TypeRef::Global(ty) => EntityType::Global(ty),
1633 TypeRef::Tag(ty) => EntityType::Tag(*module.types.get(ty.func_type_idx as usize)?),
1634 }),
1635 TypesRefKind::Component(_) => None,
1636 }
1637 }
1638
1639 pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
1641 match &self.kind {
1642 TypesRefKind::Module(module) => Some(match export.kind {
1643 ExternalKind::Func => EntityType::Func(
1644 module.types[*module.functions.get(export.index as usize)? as usize],
1645 ),
1646 ExternalKind::Table => {
1647 EntityType::Table(*module.tables.get(export.index as usize)?)
1648 }
1649 ExternalKind::Memory => {
1650 EntityType::Memory(*module.memories.get(export.index as usize)?)
1651 }
1652 ExternalKind::Global => {
1653 EntityType::Global(*module.globals.get(export.index as usize)?)
1654 }
1655 ExternalKind::Tag => EntityType::Tag(
1656 module.types[*module.functions.get(export.index as usize)? as usize],
1657 ),
1658 }),
1659 TypesRefKind::Component(_) => None,
1660 }
1661 }
1662
1663 pub fn component_entity_type_from_import(
1665 &self,
1666 import: &ComponentImport,
1667 ) -> Option<ComponentEntityType> {
1668 match &self.kind {
1669 TypesRefKind::Module(_) => None,
1670 TypesRefKind::Component(component) => {
1671 let key = KebabStr::new(import.name)?;
1672 Some(component.imports.get(key)?.1)
1673 }
1674 }
1675 }
1676
1677 pub fn component_entity_type_from_export(
1679 &self,
1680 export: &ComponentExport,
1681 ) -> Option<ComponentEntityType> {
1682 match &self.kind {
1683 TypesRefKind::Module(_) => None,
1684 TypesRefKind::Component(component) => {
1685 let key = KebabStr::new(export.name)?;
1686 Some(component.exports.get(key)?.1)
1687 }
1688 }
1689 }
1690}
1691
1692impl Types {
1693 pub(crate) fn from_module(types: TypeList, module: Arc<Module>) -> Self {
1694 Self {
1695 list: types,
1696 kind: TypesKind::Module(module),
1697 }
1698 }
1699
1700 pub(crate) fn from_component(types: TypeList, component: ComponentState) -> Self {
1701 Self {
1702 list: types,
1703 kind: TypesKind::Component(component),
1704 }
1705 }
1706
1707 pub fn as_ref(&self) -> TypesRef {
1709 TypesRef {
1710 list: &self.list,
1711 kind: match &self.kind {
1712 TypesKind::Module(module) => TypesRefKind::Module(module),
1713 TypesKind::Component(component) => TypesRefKind::Component(component),
1714 },
1715 }
1716 }
1717
1718 pub fn type_from_id(&self, id: TypeId) -> Option<&Type> {
1722 self.as_ref().type_from_id(id)
1723 }
1724
1725 pub fn id_from_type_index(&self, index: u32, core: bool) -> Option<TypeId> {
1729 self.as_ref().id_from_type_index(index, core)
1730 }
1731
1732 pub fn type_at(&self, index: u32, core: bool) -> Option<&Type> {
1736 self.as_ref().type_at(index, core)
1737 }
1738
1739 pub fn func_type_at(&self, index: u32) -> Option<&FuncType> {
1743 self.as_ref().func_type_at(index)
1744 }
1745
1746 pub fn type_count(&self) -> usize {
1748 match &self.kind {
1749 TypesKind::Module(module) => module.types.len(),
1750 TypesKind::Component(component) => component.core_types.len(),
1751 }
1752 }
1753
1754 pub fn table_at(&self, index: u32) -> Option<TableType> {
1758 self.as_ref().table_at(index)
1759 }
1760
1761 pub fn table_count(&self) -> usize {
1763 match &self.kind {
1764 TypesKind::Module(module) => module.tables.len(),
1765 TypesKind::Component(component) => component.core_tables.len(),
1766 }
1767 }
1768
1769 pub fn memory_at(&self, index: u32) -> Option<MemoryType> {
1773 self.as_ref().memory_at(index)
1774 }
1775
1776 pub fn memory_count(&self) -> usize {
1778 match &self.kind {
1779 TypesKind::Module(module) => module.memories.len(),
1780 TypesKind::Component(component) => component.core_memories.len(),
1781 }
1782 }
1783
1784 pub fn global_at(&self, index: u32) -> Option<GlobalType> {
1788 self.as_ref().global_at(index)
1789 }
1790
1791 pub fn global_count(&self) -> usize {
1793 match &self.kind {
1794 TypesKind::Module(module) => module.globals.len(),
1795 TypesKind::Component(component) => component.core_globals.len(),
1796 }
1797 }
1798
1799 pub fn tag_at(&self, index: u32) -> Option<&FuncType> {
1803 self.as_ref().tag_at(index)
1804 }
1805
1806 pub fn tag_count(&self) -> usize {
1808 match &self.kind {
1809 TypesKind::Module(module) => module.tags.len(),
1810 TypesKind::Component(component) => component.core_tags.len(),
1811 }
1812 }
1813
1814 pub fn function_at(&self, index: u32) -> Option<&FuncType> {
1818 self.as_ref().function_at(index)
1819 }
1820
1821 pub fn function_count(&self) -> usize {
1825 match &self.kind {
1826 TypesKind::Module(module) => module.functions.len(),
1827 TypesKind::Component(component) => component.core_funcs.len(),
1828 }
1829 }
1830
1831 pub fn element_at(&self, index: u32) -> Option<ValType> {
1835 self.as_ref().element_at(index)
1836 }
1837
1838 pub fn element_count(&self) -> usize {
1840 match &self.kind {
1841 TypesKind::Module(module) => module.element_types.len(),
1842 TypesKind::Component(_) => 0,
1843 }
1844 }
1845
1846 pub fn component_function_at(&self, index: u32) -> Option<&ComponentFuncType> {
1850 self.as_ref().component_function_at(index)
1851 }
1852
1853 pub fn component_function_count(&self) -> usize {
1855 match &self.kind {
1856 TypesKind::Module(_) => 0,
1857 TypesKind::Component(component) => component.funcs.len(),
1858 }
1859 }
1860
1861 pub fn module_at(&self, index: u32) -> Option<&ModuleType> {
1865 self.as_ref().module_at(index)
1866 }
1867
1868 pub fn module_count(&self) -> usize {
1870 match &self.kind {
1871 TypesKind::Module(_) => 0,
1872 TypesKind::Component(component) => component.core_modules.len(),
1873 }
1874 }
1875
1876 pub fn instance_at(&self, index: u32) -> Option<&InstanceType> {
1880 self.as_ref().instance_at(index)
1881 }
1882
1883 pub fn instance_count(&self) -> usize {
1885 match &self.kind {
1886 TypesKind::Module(_) => 0,
1887 TypesKind::Component(component) => component.core_instances.len(),
1888 }
1889 }
1890
1891 pub fn component_at(&self, index: u32) -> Option<&ComponentType> {
1895 self.as_ref().component_at(index)
1896 }
1897
1898 pub fn component_count(&self) -> usize {
1900 match &self.kind {
1901 TypesKind::Module(_) => 0,
1902 TypesKind::Component(component) => component.components.len(),
1903 }
1904 }
1905
1906 pub fn component_instance_at(&self, index: u32) -> Option<&ComponentInstanceType> {
1910 self.as_ref().component_instance_at(index)
1911 }
1912
1913 pub fn component_instance_count(&self) -> usize {
1915 match &self.kind {
1916 TypesKind::Module(_) => 0,
1917 TypesKind::Component(component) => component.instances.len(),
1918 }
1919 }
1920
1921 pub fn value_at(&self, index: u32) -> Option<ComponentValType> {
1925 self.as_ref().value_at(index)
1926 }
1927
1928 pub fn value_count(&self) -> usize {
1930 match &self.kind {
1931 TypesKind::Module(_) => 0,
1932 TypesKind::Component(component) => component.values.len(),
1933 }
1934 }
1935
1936 pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
1938 self.as_ref().entity_type_from_import(import)
1939 }
1940
1941 pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
1943 self.as_ref().entity_type_from_export(export)
1944 }
1945
1946 pub fn component_entity_type_from_import(
1948 &self,
1949 import: &ComponentImport,
1950 ) -> Option<ComponentEntityType> {
1951 self.as_ref().component_entity_type_from_import(import)
1952 }
1953
1954 pub fn component_entity_type_from_export(
1956 &self,
1957 export: &ComponentExport,
1958 ) -> Option<ComponentEntityType> {
1959 self.as_ref().component_entity_type_from_export(export)
1960 }
1961
1962 pub fn peel_alias(&self, ty: TypeId) -> Option<TypeId> {
1966 self.list.peel_alias(ty)
1967 }
1968}
1969
1970pub(crate) struct SnapshotList<T> {
1982 snapshots: Vec<Arc<Snapshot<T>>>,
1992
1993 snapshots_total: usize,
1995
1996 cur: Vec<T>,
1998
1999 unique_mappings: BTreeMap<u32, u32>,
2000 unique_counter: u32,
2001}
2002
2003struct Snapshot<T> {
2004 prior_types: usize,
2005 unique_counter: u32,
2006 unique_mappings: BTreeMap<u32, u32>,
2007 items: Vec<T>,
2008}
2009
2010impl<T> SnapshotList<T> {
2011 pub(crate) fn get(&self, index: usize) -> Option<&T> {
2013 if index >= self.snapshots_total {
2015 return self.cur.get(index - self.snapshots_total);
2016 }
2017 let i = match self
2021 .snapshots
2022 .binary_search_by_key(&index, |snapshot| snapshot.prior_types)
2023 {
2024 Ok(i) => i,
2025 Err(i) => i - 1,
2026 };
2027 let snapshot = &self.snapshots[i];
2028 Some(&snapshot.items[index - snapshot.prior_types])
2029 }
2030
2031 pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut T> {
2041 if index >= self.snapshots_total {
2042 return self.cur.get_mut(index - self.snapshots_total);
2043 }
2044 panic!("cannot get a mutable reference in snapshotted part of list")
2045 }
2046
2047 pub(crate) fn push(&mut self, val: T) {
2049 self.cur.push(val);
2050 }
2051
2052 pub(crate) fn len(&self) -> usize {
2054 self.cur.len() + self.snapshots_total
2055 }
2056
2057 pub(crate) fn reserve(&mut self, additional: usize) {
2059 self.cur.reserve(additional);
2060 }
2061
2062 pub(crate) fn commit(&mut self) -> SnapshotList<T> {
2069 let len = self.cur.len();
2077 if len > 0 {
2078 self.unique_counter += 1;
2079 self.cur.shrink_to_fit();
2080 self.snapshots.push(Arc::new(Snapshot {
2081 prior_types: self.snapshots_total,
2082 unique_counter: self.unique_counter - 1,
2083 unique_mappings: mem::take(&mut self.unique_mappings),
2084 items: mem::take(&mut self.cur),
2085 }));
2086 self.snapshots_total += len;
2087 }
2088 SnapshotList {
2089 snapshots: self.snapshots.clone(),
2090 snapshots_total: self.snapshots_total,
2091 unique_mappings: BTreeMap::new(),
2092 unique_counter: self.unique_counter,
2093 cur: Vec::new(),
2094 }
2095 }
2096
2097 pub fn with_unique(&mut self, mut ty: TypeId) -> TypeId {
2103 self.unique_mappings
2104 .insert(self.unique_counter, ty.unique_id);
2105 ty.unique_id = self.unique_counter;
2106 self.unique_counter += 1;
2107 ty
2108 }
2109
2110 pub fn peel_alias(&self, ty: TypeId) -> Option<TypeId> {
2114 let i = match self
2121 .snapshots
2122 .binary_search_by_key(&ty.unique_id, |snapshot| snapshot.unique_counter)
2123 {
2124 Ok(_) => unreachable!(),
2125 Err(i) => i,
2126 };
2127
2128 let unique_id = match self.snapshots.get(i) {
2132 Some(snapshot) => *snapshot.unique_mappings.get(&ty.unique_id)?,
2133 None => *self.unique_mappings.get(&ty.unique_id)?,
2134 };
2135 Some(TypeId { unique_id, ..ty })
2136 }
2137}
2138
2139impl<T> ::core::ops::Index<usize> for SnapshotList<T> {
2140 type Output = T;
2141
2142 #[inline]
2143 fn index(&self, index: usize) -> &T {
2144 self.get(index).unwrap()
2145 }
2146}
2147
2148impl<T> ::core::ops::IndexMut<usize> for SnapshotList<T> {
2149 #[inline]
2150 fn index_mut(&mut self, index: usize) -> &mut T {
2151 self.get_mut(index).unwrap()
2152 }
2153}
2154
2155impl<T> ::core::ops::Index<TypeId> for SnapshotList<T> {
2156 type Output = T;
2157
2158 #[inline]
2159 fn index(&self, id: TypeId) -> &T {
2160 self.get(id.index).unwrap()
2161 }
2162}
2163
2164impl<T> ::core::ops::IndexMut<TypeId> for SnapshotList<T> {
2165 #[inline]
2166 fn index_mut(&mut self, id: TypeId) -> &mut T {
2167 self.get_mut(id.index).unwrap()
2168 }
2169}
2170
2171impl<T> Default for SnapshotList<T> {
2172 fn default() -> SnapshotList<T> {
2173 SnapshotList {
2174 snapshots: Vec::new(),
2175 snapshots_total: 0,
2176 cur: Vec::new(),
2177 unique_counter: 1,
2178 unique_mappings: BTreeMap::new(),
2179 }
2180 }
2181}
2182
2183pub(crate) type TypeList = SnapshotList<Type>;
2185
2186pub(crate) struct TypeAlloc {
2189 list: TypeList,
2190}
2191
2192impl Deref for TypeAlloc {
2193 type Target = TypeList;
2194 fn deref(&self) -> &TypeList {
2195 &self.list
2196 }
2197}
2198
2199impl DerefMut for TypeAlloc {
2200 fn deref_mut(&mut self) -> &mut TypeList {
2201 &mut self.list
2202 }
2203}
2204
2205impl TypeAlloc {
2206 pub fn push_anon(&mut self, ty: Type) -> TypeId {
2209 let index = self.list.len();
2210 let type_size = ty.type_size();
2211 self.list.push(ty);
2212 TypeId {
2213 index,
2214 type_size,
2215 unique_id: 0,
2216 }
2217 }
2218
2219 pub fn push_defined(&mut self, ty: Type) -> TypeId {
2225 let id = self.push_anon(ty);
2226 self.with_unique(id)
2227 }
2228}
2229
2230impl Default for TypeAlloc {
2231 fn default() -> TypeAlloc {
2232 TypeAlloc {
2233 list: Default::default(),
2234 }
2235 }
2236}