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