/build/cargo-vendor-dir/wasm-encoder-0.200.0/src/component/imports.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::{ |
2 | | encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, ComponentValType, |
3 | | Encode, |
4 | | }; |
5 | | |
6 | | /// Represents the possible type bounds for type references. |
7 | | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] |
8 | | pub enum TypeBounds { |
9 | | /// The type is bounded by equality to the type index specified. |
10 | | Eq(u32), |
11 | | /// This type is a fresh resource type, |
12 | | SubResource, |
13 | | } |
14 | | |
15 | | impl Encode for TypeBounds { |
16 | 0 | fn encode(&self, sink: &mut Vec<u8>) { |
17 | 0 | match self { |
18 | 0 | Self::Eq(i) => { |
19 | 0 | sink.push(0x00); |
20 | 0 | i.encode(sink); |
21 | 0 | } |
22 | 0 | Self::SubResource => sink.push(0x01), |
23 | | } |
24 | 0 | } |
25 | | } |
26 | | |
27 | | /// Represents a reference to a type. |
28 | | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] |
29 | | pub enum ComponentTypeRef { |
30 | | /// The reference is to a core module type. |
31 | | /// |
32 | | /// The index is expected to be core type index to a core module type. |
33 | | Module(u32), |
34 | | /// The reference is to a function type. |
35 | | /// |
36 | | /// The index is expected to be a type index to a function type. |
37 | | Func(u32), |
38 | | /// The reference is to a value type. |
39 | | Value(ComponentValType), |
40 | | /// The reference is to a bounded type. |
41 | | Type(TypeBounds), |
42 | | /// The reference is to an instance type. |
43 | | /// |
44 | | /// The index is expected to be a type index to an instance type. |
45 | | Instance(u32), |
46 | | /// The reference is to a component type. |
47 | | /// |
48 | | /// The index is expected to be a type index to a component type. |
49 | | Component(u32), |
50 | | } |
51 | | |
52 | | impl ComponentTypeRef { |
53 | | /// Gets the export kind of the reference. |
54 | 0 | pub fn kind(&self) -> ComponentExportKind { |
55 | 0 | match self { |
56 | 0 | Self::Module(_) => ComponentExportKind::Module, |
57 | 0 | Self::Func(_) => ComponentExportKind::Func, |
58 | 0 | Self::Value(_) => ComponentExportKind::Value, |
59 | 0 | Self::Type(..) => ComponentExportKind::Type, |
60 | 0 | Self::Instance(_) => ComponentExportKind::Instance, |
61 | 0 | Self::Component(_) => ComponentExportKind::Component, |
62 | | } |
63 | 0 | } |
64 | | } |
65 | | |
66 | | impl Encode for ComponentTypeRef { |
67 | 0 | fn encode(&self, sink: &mut Vec<u8>) { |
68 | 0 | self.kind().encode(sink); |
69 | 0 |
|
70 | 0 | match self { |
71 | 0 | Self::Module(idx) | Self::Func(idx) | Self::Instance(idx) | Self::Component(idx) => { |
72 | 0 | idx.encode(sink); |
73 | 0 | } |
74 | 0 | Self::Value(ty) => ty.encode(sink), |
75 | 0 | Self::Type(bounds) => bounds.encode(sink), |
76 | | } |
77 | 0 | } |
78 | | } |
79 | | |
80 | | /// An encoder for the import section of WebAssembly components. |
81 | | /// |
82 | | /// # Example |
83 | | /// |
84 | | /// ```rust |
85 | | /// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType, ComponentImportSection, ComponentTypeRef}; |
86 | | /// |
87 | | /// let mut types = ComponentTypeSection::new(); |
88 | | /// |
89 | | /// // Define a function type of `[string, string] -> string`. |
90 | | /// types |
91 | | /// .function() |
92 | | /// .params( |
93 | | /// [ |
94 | | /// ("a", PrimitiveValType::String), |
95 | | /// ("b", PrimitiveValType::String) |
96 | | /// ] |
97 | | /// ) |
98 | | /// .result(PrimitiveValType::String); |
99 | | /// |
100 | | /// // This imports a function named `f` with the type defined above |
101 | | /// let mut imports = ComponentImportSection::new(); |
102 | | /// imports.import("f", ComponentTypeRef::Func(0)); |
103 | | /// |
104 | | /// let mut component = Component::new(); |
105 | | /// component.section(&types); |
106 | | /// component.section(&imports); |
107 | | /// |
108 | | /// let bytes = component.finish(); |
109 | | /// ``` |
110 | | #[derive(Clone, Debug, Default)] |
111 | | pub struct ComponentImportSection { |
112 | | bytes: Vec<u8>, |
113 | | num_added: u32, |
114 | | } |
115 | | |
116 | | impl ComponentImportSection { |
117 | | /// Create a new component import section encoder. |
118 | 0 | pub fn new() -> Self { |
119 | 0 | Self::default() |
120 | 0 | } |
121 | | |
122 | | /// The number of imports in the section. |
123 | 0 | pub fn len(&self) -> u32 { |
124 | 0 | self.num_added |
125 | 0 | } |
126 | | |
127 | | /// Determines if the section is empty. |
128 | 0 | pub fn is_empty(&self) -> bool { |
129 | 0 | self.num_added == 0 |
130 | 0 | } |
131 | | |
132 | | /// Define an import in the component import section. |
133 | 0 | pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self { |
134 | 0 | push_extern_name_byte(&mut self.bytes, name); |
135 | 0 | name.encode(&mut self.bytes); |
136 | 0 | ty.encode(&mut self.bytes); |
137 | 0 | self.num_added += 1; |
138 | 0 | self |
139 | 0 | } |
140 | | } |
141 | | |
142 | | impl Encode for ComponentImportSection { |
143 | 0 | fn encode(&self, sink: &mut Vec<u8>) { |
144 | 0 | encode_section(sink, self.num_added, &self.bytes); |
145 | 0 | } |
146 | | } |
147 | | |
148 | | impl ComponentSection for ComponentImportSection { |
149 | 0 | fn id(&self) -> u8 { |
150 | 0 | ComponentSectionId::Import.into() |
151 | 0 | } |
152 | | } |
153 | | |
154 | | /// Prior to WebAssembly/component-model#263 import and export names were |
155 | | /// discriminated with a leading byte indicating what kind of import they are. |
156 | | /// After that PR though names are always prefixed with a 0x00 byte. |
157 | | /// |
158 | | /// This function is a compatibility shim for the time being while this change |
159 | | /// is being rolled out. That PR is technically a spec-breaking change relative |
160 | | /// to prior but we want old tooling to continue to work with new modules. To |
161 | | /// handle that names that look like IDs, `a:b/c`, get an 0x01 prefix instead of |
162 | | /// the spec-defined 0x00 prefix. That makes components produced by current |
163 | | /// versions of this crate compatible with older parsers. |
164 | | /// |
165 | | /// Note that wasmparser has a similar case where it parses either 0x01 or 0x00. |
166 | | /// That means that the selection of a byte here doesn't actually matter for |
167 | | /// wasmparser's own validation. Eventually this will go away and an 0x00 byte |
168 | | /// will always be emitted to align with the spec. |
169 | 0 | pub(crate) fn push_extern_name_byte(bytes: &mut Vec<u8>, name: &str) { |
170 | 0 | if name.contains(':') { |
171 | 0 | bytes.push(0x01); |
172 | 0 | } else { |
173 | 0 | bytes.push(0x00); |
174 | 0 | } |
175 | 0 | } |