1use super::{COMPONENT_SORT, CORE_MODULE_SORT, CORE_SORT, CORE_TYPE_SORT, TYPE_SORT};
2use crate::{
3 encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind,
4};
5
6/// Represents the kinds of outer aliasable items in a component.
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum ComponentOuterAliasKind {
9 /// The alias is to a core module.
10 CoreModule,
11 /// The alias is to a core type.
12 CoreType,
13 /// The alias is to a type.
14 Type,
15 /// The alias is to a component.
16 Component,
17}
18
19impl Encode for ComponentOuterAliasKind {
20 fn encode(&self, sink: &mut Vec<u8>) {
21 match self {
22 Self::CoreModule => {
23 sink.push(CORE_SORT);
24 sink.push(CORE_MODULE_SORT);
25 }
26 Self::CoreType => {
27 sink.push(CORE_SORT);
28 sink.push(CORE_TYPE_SORT);
29 }
30 Self::Type => sink.push(TYPE_SORT),
31 Self::Component => sink.push(COMPONENT_SORT),
32 }
33 }
34}
35
36/// An encoder for the alias section of WebAssembly component.
37///
38/// # Example
39///
40/// ```rust
41/// use wasm_encoder::{Component, Alias, ComponentAliasSection, ComponentExportKind, ComponentOuterAliasKind};
42///
43/// let mut aliases = ComponentAliasSection::new();
44/// aliases.alias(Alias::InstanceExport { instance: 0, kind: ComponentExportKind::Func, name: "f" });
45/// aliases.alias(Alias::Outer { count: 0, kind: ComponentOuterAliasKind::Type, index: 1 });
46///
47/// let mut component = Component::new();
48/// component.section(&aliases);
49///
50/// let bytes = component.finish();
51/// ```
52#[derive(Clone, Debug, Default)]
53pub struct ComponentAliasSection {
54 bytes: Vec<u8>,
55 num_added: u32,
56}
57
58/// Different forms of aliases that can be inserted into a
59/// [`ComponentAliasSection`].
60#[derive(Copy, Clone, Debug)]
61pub enum Alias<'a> {
62 /// An alias of a component instance export.
63 InstanceExport {
64 /// The index of the component instance that's being aliased from.
65 instance: u32,
66 /// The kind of item that's being extracted from the component
67 /// instance.
68 kind: ComponentExportKind,
69 /// The name of the export that's being aliased.
70 name: &'a str,
71 },
72 /// Same as `InstanceExport`, but for core instances.
73 #[allow(missing_docs)]
74 CoreInstanceExport {
75 instance: u32,
76 kind: ExportKind,
77 name: &'a str,
78 },
79 /// Aliasing an item from an outer component.
80 Outer {
81 /// The kind of item being aliased, either a type or a component.
82 kind: ComponentOuterAliasKind,
83 /// Number of levels "up" to go to lookup the index within. Level 0 is
84 /// the current scope and level 1 is the enclosing scope, and so on.
85 count: u32,
86 /// The index of the item to alias within the scope referenced by
87 /// `count`.
88 index: u32,
89 },
90}
91
92impl ComponentAliasSection {
93 /// Create a new alias section encoder.
94 pub fn new() -> Self {
95 Self::default()
96 }
97
98 /// The number of aliases in the section.
99 pub fn len(&self) -> u32 {
100 self.num_added
101 }
102
103 /// Determines if the section is empty.
104 pub fn is_empty(&self) -> bool {
105 self.num_added == 0
106 }
107
108 /// Define an alias to a component instance's export.
109 pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
110 alias.encode(&mut self.bytes);
111 self.num_added += 1;
112 self
113 }
114}
115
116impl Encode for ComponentAliasSection {
117 fn encode(&self, sink: &mut Vec<u8>) {
118 encode_section(sink, self.num_added, &self.bytes);
119 }
120}
121
122impl ComponentSection for ComponentAliasSection {
123 fn id(&self) -> u8 {
124 ComponentSectionId::Alias.into()
125 }
126}
127
128impl Encode for Alias<'_> {
129 fn encode(&self, sink: &mut Vec<u8>) {
130 match self {
131 Alias::InstanceExport {
132 instance,
133 kind,
134 name,
135 } => {
136 kind.encode(sink);
137 sink.push(0x00);
138 instance.encode(sink);
139 name.encode(sink);
140 }
141 Alias::CoreInstanceExport {
142 instance,
143 kind,
144 name,
145 } => {
146 sink.push(CORE_SORT);
147 kind.encode(sink);
148 sink.push(0x01);
149 instance.encode(sink);
150 name.encode(sink);
151 }
152 Alias::Outer { kind, count, index } => {
153 kind.encode(sink);
154 sink.push(0x02);
155 count.encode(sink);
156 index.encode(sink);
157 }
158 }
159 }
160}
161