wasm_encoder/component/
types.rs

1use super::CORE_TYPE_SORT;
2use crate::{
3    Alias, ComponentExportKind, ComponentOuterAliasKind, ComponentSection, ComponentSectionId,
4    ComponentTypeRef, CoreTypeEncoder, Encode, EntityType, ValType, encode_section,
5};
6use alloc::vec::Vec;
7
8/// Represents the type of a core module.
9#[derive(Debug, Clone, Default)]
10pub struct ModuleType {
11    bytes: Vec<u8>,
12    num_added: u32,
13    types_added: u32,
14}
15
16impl ModuleType {
17    /// Creates a new core module type.
18    pub fn new() -> Self {
19        Self::default()
20    }
21
22    /// Defines an import in this module type.
23    pub fn import(&mut self, module: &str, name: &str, ty: EntityType) -> &mut Self {
24        self.bytes.push(0x00);
25        module.encode(&mut self.bytes);
26        name.encode(&mut self.bytes);
27        ty.encode(&mut self.bytes);
28        self.num_added += 1;
29        self
30    }
31
32    /// Define a type in this module type.
33    ///
34    /// The returned encoder must be used before adding another definition.
35    #[must_use = "the encoder must be used to encode the type"]
36    pub fn ty(&mut self) -> CoreTypeEncoder<'_> {
37        self.bytes.push(0x01);
38        self.num_added += 1;
39        self.types_added += 1;
40        CoreTypeEncoder {
41            push_prefix_if_component_core_type: false,
42            bytes: &mut self.bytes,
43        }
44    }
45
46    /// Defines an outer core type alias in this module type.
47    pub fn alias_outer_core_type(&mut self, count: u32, index: u32) -> &mut Self {
48        self.bytes.push(0x02);
49        self.bytes.push(CORE_TYPE_SORT);
50        self.bytes.push(0x01); // outer
51        count.encode(&mut self.bytes);
52        index.encode(&mut self.bytes);
53        self.num_added += 1;
54        self.types_added += 1;
55        self
56    }
57
58    /// Defines an export in this module type.
59    pub fn export(&mut self, name: &str, ty: EntityType) -> &mut Self {
60        self.bytes.push(0x03);
61        name.encode(&mut self.bytes);
62        ty.encode(&mut self.bytes);
63        self.num_added += 1;
64        self
65    }
66
67    /// Gets the number of types that have been added to this module type.
68    pub fn type_count(&self) -> u32 {
69        self.types_added
70    }
71}
72
73impl Encode for ModuleType {
74    fn encode(&self, sink: &mut Vec<u8>) {
75        sink.push(0x50);
76        self.num_added.encode(sink);
77        sink.extend(&self.bytes);
78    }
79}
80
81/// Used to encode core types.
82#[derive(Debug)]
83pub struct ComponentCoreTypeEncoder<'a>(pub(crate) &'a mut Vec<u8>);
84
85impl<'a> ComponentCoreTypeEncoder<'a> {
86    /// Define a module type.
87    pub fn module(self, ty: &ModuleType) {
88        ty.encode(self.0);
89    }
90
91    /// Define any core type other than a module type.
92    #[must_use = "the encoder must be used to encode the type"]
93    pub fn core(self) -> CoreTypeEncoder<'a> {
94        CoreTypeEncoder {
95            bytes: self.0,
96            push_prefix_if_component_core_type: true,
97        }
98    }
99}
100
101/// An encoder for the core type section of WebAssembly components.
102///
103/// # Example
104///
105/// ```rust
106/// use wasm_encoder::{Component, CoreTypeSection, ModuleType};
107///
108/// let mut types = CoreTypeSection::new();
109///
110/// types.ty().module(&ModuleType::new());
111///
112/// let mut component = Component::new();
113/// component.section(&types);
114///
115/// let bytes = component.finish();
116/// ```
117#[derive(Clone, Debug, Default)]
118pub struct CoreTypeSection {
119    bytes: Vec<u8>,
120    num_added: u32,
121}
122
123impl CoreTypeSection {
124    /// Create a new core type section encoder.
125    pub fn new() -> Self {
126        Self::default()
127    }
128
129    /// The number of types in the section.
130    pub fn len(&self) -> u32 {
131        self.num_added
132    }
133
134    /// Determines if the section is empty.
135    pub fn is_empty(&self) -> bool {
136        self.num_added == 0
137    }
138
139    /// Encode a type into this section.
140    ///
141    /// The returned encoder must be finished before adding another type.
142    #[must_use = "the encoder must be used to encode the type"]
143    pub fn ty(&mut self) -> ComponentCoreTypeEncoder<'_> {
144        self.num_added += 1;
145        ComponentCoreTypeEncoder(&mut self.bytes)
146    }
147}
148
149impl Encode for CoreTypeSection {
150    fn encode(&self, sink: &mut Vec<u8>) {
151        encode_section(sink, self.num_added, &self.bytes);
152    }
153}
154
155impl ComponentSection for CoreTypeSection {
156    fn id(&self) -> u8 {
157        ComponentSectionId::CoreType.into()
158    }
159}
160
161/// Represents a component type.
162#[derive(Debug, Clone, Default)]
163pub struct ComponentType {
164    bytes: Vec<u8>,
165    num_added: u32,
166    core_types_added: u32,
167    types_added: u32,
168    instances_added: u32,
169}
170
171impl ComponentType {
172    /// Creates a new component type.
173    pub fn new() -> Self {
174        Self::default()
175    }
176
177    /// Define a core type in this component type.
178    ///
179    /// The returned encoder must be used before adding another definition.
180    #[must_use = "the encoder must be used to encode the type"]
181    pub fn core_type(&mut self) -> ComponentCoreTypeEncoder<'_> {
182        self.bytes.push(0x00);
183        self.num_added += 1;
184        self.core_types_added += 1;
185        ComponentCoreTypeEncoder(&mut self.bytes)
186    }
187
188    /// Define a type in this component type.
189    ///
190    /// The returned encoder must be used before adding another definition.
191    #[must_use = "the encoder must be used to encode the type"]
192    pub fn ty(&mut self) -> ComponentTypeEncoder<'_> {
193        self.bytes.push(0x01);
194        self.num_added += 1;
195        self.types_added += 1;
196        ComponentTypeEncoder(&mut self.bytes)
197    }
198
199    /// Defines an alias for an exported item of a prior instance or an
200    /// outer type.
201    pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
202        self.bytes.push(0x02);
203        alias.encode(&mut self.bytes);
204        self.num_added += 1;
205        match &alias {
206            Alias::InstanceExport {
207                kind: ComponentExportKind::Type,
208                ..
209            }
210            | Alias::Outer {
211                kind: ComponentOuterAliasKind::Type,
212                ..
213            } => self.types_added += 1,
214            Alias::Outer {
215                kind: ComponentOuterAliasKind::CoreType,
216                ..
217            } => self.core_types_added += 1,
218            Alias::InstanceExport {
219                kind: ComponentExportKind::Instance,
220                ..
221            } => self.instances_added += 1,
222            _ => {}
223        }
224        self
225    }
226
227    /// Defines an import in this component type.
228    pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
229        self.bytes.push(0x03);
230        crate::encode_component_import_name(&mut self.bytes, name);
231        ty.encode(&mut self.bytes);
232        self.num_added += 1;
233        match ty {
234            ComponentTypeRef::Type(..) => self.types_added += 1,
235            ComponentTypeRef::Instance(..) => self.instances_added += 1,
236            _ => {}
237        }
238        self
239    }
240
241    /// Defines an export in this component type.
242    pub fn export(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
243        self.bytes.push(0x04);
244        crate::encode_component_export_name(&mut self.bytes, name);
245        ty.encode(&mut self.bytes);
246        self.num_added += 1;
247        match ty {
248            ComponentTypeRef::Type(..) => self.types_added += 1,
249            ComponentTypeRef::Instance(..) => self.instances_added += 1,
250            _ => {}
251        }
252        self
253    }
254
255    /// Gets the number of core types that have been added to this component type.
256    pub fn core_type_count(&self) -> u32 {
257        self.core_types_added
258    }
259
260    /// Gets the number of types that have been added or aliased in this component type.
261    pub fn type_count(&self) -> u32 {
262        self.types_added
263    }
264
265    /// Gets the number of instances that have been defined in this component
266    /// type through imports, exports, or aliases.
267    pub fn instance_count(&self) -> u32 {
268        self.instances_added
269    }
270}
271
272impl Encode for ComponentType {
273    fn encode(&self, sink: &mut Vec<u8>) {
274        sink.push(0x41);
275        self.num_added.encode(sink);
276        sink.extend(&self.bytes);
277    }
278}
279
280/// Represents an instance type.
281#[derive(Debug, Clone, Default)]
282pub struct InstanceType(ComponentType);
283
284impl InstanceType {
285    /// Creates a new instance type.
286    pub fn new() -> Self {
287        Self::default()
288    }
289
290    /// Define a core type in this instance type.
291    ///
292    /// The returned encoder must be used before adding another definition.
293    #[must_use = "the encoder must be used to encode the type"]
294    pub fn core_type(&mut self) -> ComponentCoreTypeEncoder<'_> {
295        self.0.core_type()
296    }
297
298    /// Define a type in this instance type.
299    ///
300    /// The returned encoder must be used before adding another definition.
301    #[must_use = "the encoder must be used to encode the type"]
302    pub fn ty(&mut self) -> ComponentTypeEncoder<'_> {
303        self.0.ty()
304    }
305
306    /// Defines an outer core type alias in this component type.
307    pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
308        self.0.alias(alias);
309        self
310    }
311
312    /// Defines an export in this instance type.
313    pub fn export(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
314        self.0.export(name, ty);
315        self
316    }
317
318    /// Gets the number of core types that have been added to this instance type.
319    pub fn core_type_count(&self) -> u32 {
320        self.0.core_types_added
321    }
322
323    /// Gets the number of types that have been added or aliased in this instance type.
324    pub fn type_count(&self) -> u32 {
325        self.0.types_added
326    }
327
328    /// Gets the number of instances that have been imported or exported or
329    /// aliased in this instance type.
330    pub fn instance_count(&self) -> u32 {
331        self.0.instances_added
332    }
333
334    /// Returns whether or not this instance type is empty.
335    pub fn is_empty(&self) -> bool {
336        self.0.num_added == 0
337    }
338
339    /// Returns the number of entries added to this instance types.
340    pub fn len(&self) -> u32 {
341        self.0.num_added
342    }
343}
344
345impl Encode for InstanceType {
346    fn encode(&self, sink: &mut Vec<u8>) {
347        sink.push(0x42);
348        self.0.num_added.encode(sink);
349        sink.extend(&self.0.bytes);
350    }
351}
352
353/// Used to encode component function types.
354#[derive(Debug)]
355pub struct ComponentFuncTypeEncoder<'a> {
356    async_encoded: bool,
357    params_encoded: bool,
358    results_encoded: bool,
359    sink: &'a mut Vec<u8>,
360}
361
362impl<'a> ComponentFuncTypeEncoder<'a> {
363    fn new(sink: &'a mut Vec<u8>) -> Self {
364        Self {
365            async_encoded: false,
366            params_encoded: false,
367            results_encoded: false,
368            sink,
369        }
370    }
371
372    /// Indicates whether this is an `async` function or not.
373    ///
374    /// If this function is not invoked then the function type will not be
375    /// `async`.
376    ///
377    /// # Panics
378    ///
379    /// This method will panic if parameters or results have already been
380    /// encoded.
381    pub fn async_(&mut self, is_async: bool) -> &mut Self {
382        assert!(!self.params_encoded);
383        assert!(!self.results_encoded);
384        assert!(!self.async_encoded);
385        self.async_encoded = true;
386        if is_async {
387            self.sink.push(0x43);
388        } else {
389            self.sink.push(0x40);
390        }
391        self
392    }
393
394    /// Defines named parameters.
395    ///
396    /// Parameters must be defined before defining results.
397    ///
398    /// # Panics
399    ///
400    /// This method will panic if the function is called twice since parameters
401    /// can only be encoded once.
402    pub fn params<'b, P, T>(&mut self, params: P) -> &mut Self
403    where
404        P: IntoIterator<Item = (&'b str, T)>,
405        P::IntoIter: ExactSizeIterator,
406        T: Into<ComponentValType>,
407    {
408        assert!(!self.params_encoded);
409        if !self.async_encoded {
410            self.async_(false);
411        }
412        self.params_encoded = true;
413        let params = params.into_iter();
414        params.len().encode(self.sink);
415        for (name, ty) in params {
416            name.encode(self.sink);
417            ty.into().encode(self.sink);
418        }
419        self
420    }
421
422    /// Defines a single unnamed result.
423    ///
424    /// This method cannot be used with `results`.
425    ///
426    /// # Panics
427    ///
428    /// This method will panic if the function is called twice, called before
429    /// the `params` method, or called in addition to the `results` method.
430    pub fn result(&mut self, ty: Option<ComponentValType>) -> &mut Self {
431        assert!(self.async_encoded);
432        assert!(self.params_encoded);
433        assert!(!self.results_encoded);
434        self.results_encoded = true;
435        encode_resultlist(self.sink, ty);
436        self
437    }
438}
439
440pub(crate) fn encode_resultlist(sink: &mut Vec<u8>, ty: Option<ComponentValType>) {
441    match ty {
442        Some(ty) => {
443            sink.push(0x00);
444            ty.encode(sink);
445        }
446        None => {
447            sink.push(0x01);
448            sink.push(0x00);
449        }
450    }
451}
452
453/// Used to encode component and instance types.
454#[derive(Debug)]
455pub struct ComponentTypeEncoder<'a>(&'a mut Vec<u8>);
456
457impl<'a> ComponentTypeEncoder<'a> {
458    /// Define a component type.
459    pub fn component(self, ty: &ComponentType) {
460        ty.encode(self.0);
461    }
462
463    /// Define an instance type.
464    pub fn instance(self, ty: &InstanceType) {
465        ty.encode(self.0);
466    }
467
468    /// Define a function type.
469    pub fn function(self) -> ComponentFuncTypeEncoder<'a> {
470        ComponentFuncTypeEncoder::new(self.0)
471    }
472
473    /// Define a defined component type.
474    ///
475    /// The returned encoder must be used before adding another type.
476    #[must_use = "the encoder must be used to encode the type"]
477    pub fn defined_type(self) -> ComponentDefinedTypeEncoder<'a> {
478        ComponentDefinedTypeEncoder(self.0)
479    }
480
481    /// Define a resource type.
482    pub fn resource(self, rep: ValType, dtor: Option<u32>) {
483        self.0.push(0x3f);
484        rep.encode(self.0);
485        match dtor {
486            Some(i) => {
487                self.0.push(0x01);
488                i.encode(self.0);
489            }
490            None => self.0.push(0x00),
491        }
492    }
493}
494
495/// Represents a primitive component value type.
496#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
497pub enum PrimitiveValType {
498    /// The type is a boolean.
499    Bool,
500    /// The type is a signed 8-bit integer.
501    S8,
502    /// The type is an unsigned 8-bit integer.
503    U8,
504    /// The type is a signed 16-bit integer.
505    S16,
506    /// The type is an unsigned 16-bit integer.
507    U16,
508    /// The type is a signed 32-bit integer.
509    S32,
510    /// The type is an unsigned 32-bit integer.
511    U32,
512    /// The type is a signed 64-bit integer.
513    S64,
514    /// The type is an unsigned 64-bit integer.
515    U64,
516    /// The type is a 32-bit floating point number with only one NaN.
517    F32,
518    /// The type is a 64-bit floating point number with only one NaN.
519    F64,
520    /// The type is a Unicode character.
521    Char,
522    /// The type is a string.
523    String,
524    /// Type for `error-context` added with async support in the component model.
525    ErrorContext,
526}
527
528impl Encode for PrimitiveValType {
529    fn encode(&self, sink: &mut Vec<u8>) {
530        sink.push(match self {
531            Self::Bool => 0x7f,
532            Self::S8 => 0x7e,
533            Self::U8 => 0x7d,
534            Self::S16 => 0x7c,
535            Self::U16 => 0x7b,
536            Self::S32 => 0x7a,
537            Self::U32 => 0x79,
538            Self::S64 => 0x78,
539            Self::U64 => 0x77,
540            Self::F32 => 0x76,
541            Self::F64 => 0x75,
542            Self::Char => 0x74,
543            Self::String => 0x73,
544            Self::ErrorContext => 0x64,
545        });
546    }
547}
548
549/// Represents a component value type.
550#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
551pub enum ComponentValType {
552    /// The value is a primitive type.
553    Primitive(PrimitiveValType),
554    /// The value is to a defined value type.
555    ///
556    /// The type index must be to a value type.
557    Type(u32),
558}
559
560impl Encode for ComponentValType {
561    fn encode(&self, sink: &mut Vec<u8>) {
562        match self {
563            Self::Primitive(ty) => ty.encode(sink),
564            Self::Type(index) => (*index as i64).encode(sink),
565        }
566    }
567}
568
569impl From<PrimitiveValType> for ComponentValType {
570    fn from(ty: PrimitiveValType) -> Self {
571        Self::Primitive(ty)
572    }
573}
574
575/// Used for encoding component defined types.
576#[derive(Debug)]
577pub struct ComponentDefinedTypeEncoder<'a>(&'a mut Vec<u8>);
578
579impl ComponentDefinedTypeEncoder<'_> {
580    /// Define a primitive value type.
581    pub fn primitive(self, ty: PrimitiveValType) {
582        ty.encode(self.0);
583    }
584
585    /// Define a record type.
586    pub fn record<'a, F, T>(self, fields: F)
587    where
588        F: IntoIterator<Item = (&'a str, T)>,
589        F::IntoIter: ExactSizeIterator,
590        T: Into<ComponentValType>,
591    {
592        let fields = fields.into_iter();
593        self.0.push(0x72);
594        fields.len().encode(self.0);
595        for (name, ty) in fields {
596            name.encode(self.0);
597            ty.into().encode(self.0);
598        }
599    }
600
601    /// Define a variant type.
602    pub fn variant<'a, C>(self, cases: C)
603    where
604        C: IntoIterator<Item = (&'a str, Option<ComponentValType>, Option<u32>)>,
605        C::IntoIter: ExactSizeIterator,
606    {
607        let cases = cases.into_iter();
608        self.0.push(0x71);
609        cases.len().encode(self.0);
610        for (name, ty, refines) in cases {
611            name.encode(self.0);
612            ty.encode(self.0);
613            refines.encode(self.0);
614        }
615    }
616
617    /// Define a list type.
618    pub fn list(self, ty: impl Into<ComponentValType>) {
619        self.0.push(0x70);
620        ty.into().encode(self.0);
621    }
622
623    /// Define a map type.
624    pub fn map(self, key: impl Into<ComponentValType>, value: impl Into<ComponentValType>) {
625        self.0.push(0x63);
626        key.into().encode(self.0);
627        value.into().encode(self.0);
628    }
629
630    /// Define a fixed size list type.
631    pub fn fixed_size_list(self, ty: impl Into<ComponentValType>, elements: u32) {
632        self.0.push(0x67);
633        ty.into().encode(self.0);
634        elements.encode(self.0);
635    }
636
637    /// Define a tuple type.
638    pub fn tuple<I, T>(self, types: I)
639    where
640        I: IntoIterator<Item = T>,
641        I::IntoIter: ExactSizeIterator,
642        T: Into<ComponentValType>,
643    {
644        let types = types.into_iter();
645        self.0.push(0x6F);
646        types.len().encode(self.0);
647        for ty in types {
648            ty.into().encode(self.0);
649        }
650    }
651
652    /// Define a flags type.
653    pub fn flags<'a, I>(self, names: I)
654    where
655        I: IntoIterator<Item = &'a str>,
656        I::IntoIter: ExactSizeIterator,
657    {
658        let names = names.into_iter();
659        self.0.push(0x6E);
660        names.len().encode(self.0);
661        for name in names {
662            name.encode(self.0);
663        }
664    }
665
666    /// Define an enum type.
667    pub fn enum_type<'a, I>(self, tags: I)
668    where
669        I: IntoIterator<Item = &'a str>,
670        I::IntoIter: ExactSizeIterator,
671    {
672        let tags = tags.into_iter();
673        self.0.push(0x6D);
674        tags.len().encode(self.0);
675        for tag in tags {
676            tag.encode(self.0);
677        }
678    }
679
680    /// Define an option type.
681    pub fn option(self, ty: impl Into<ComponentValType>) {
682        self.0.push(0x6B);
683        ty.into().encode(self.0);
684    }
685
686    /// Define a result type.
687    pub fn result(self, ok: Option<ComponentValType>, err: Option<ComponentValType>) {
688        self.0.push(0x6A);
689        ok.encode(self.0);
690        err.encode(self.0);
691    }
692
693    /// Define a `own` handle type
694    pub fn own(self, idx: u32) {
695        self.0.push(0x69);
696        idx.encode(self.0);
697    }
698
699    /// Define a `borrow` handle type
700    pub fn borrow(self, idx: u32) {
701        self.0.push(0x68);
702        idx.encode(self.0);
703    }
704
705    /// Define a `future` type with the specified payload.
706    pub fn future(self, payload: Option<ComponentValType>) {
707        self.0.push(0x65);
708        payload.encode(self.0);
709    }
710
711    /// Define a `stream` type with the specified payload.
712    pub fn stream(self, payload: Option<ComponentValType>) {
713        self.0.push(0x66);
714        payload.encode(self.0);
715    }
716}
717
718/// An encoder for the type section of WebAssembly components.
719///
720/// # Example
721///
722/// ```rust
723/// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType};
724///
725/// let mut types = ComponentTypeSection::new();
726///
727/// // Define a function type of `[string, string] -> string`.
728/// types
729///   .function()
730///   .params(
731///     [
732///       ("a", PrimitiveValType::String),
733///       ("b", PrimitiveValType::String)
734///     ]
735///   )
736///   .result(Some(PrimitiveValType::String.into()));
737///
738/// let mut component = Component::new();
739/// component.section(&types);
740///
741/// let bytes = component.finish();
742/// ```
743#[derive(Clone, Debug, Default)]
744pub struct ComponentTypeSection {
745    bytes: Vec<u8>,
746    num_added: u32,
747}
748
749impl ComponentTypeSection {
750    /// Create a new component type section encoder.
751    pub fn new() -> Self {
752        Self::default()
753    }
754
755    /// The number of types in the section.
756    pub fn len(&self) -> u32 {
757        self.num_added
758    }
759
760    /// Determines if the section is empty.
761    pub fn is_empty(&self) -> bool {
762        self.num_added == 0
763    }
764
765    /// Encode a type into this section.
766    ///
767    /// The returned encoder must be finished before adding another type.
768    #[must_use = "the encoder must be used to encode the type"]
769    pub fn ty(&mut self) -> ComponentTypeEncoder<'_> {
770        self.num_added += 1;
771        ComponentTypeEncoder(&mut self.bytes)
772    }
773
774    /// Define a component type in this type section.
775    pub fn component(&mut self, ty: &ComponentType) -> &mut Self {
776        self.ty().component(ty);
777        self
778    }
779
780    /// Define an instance type in this type section.
781    pub fn instance(&mut self, ty: &InstanceType) -> &mut Self {
782        self.ty().instance(ty);
783        self
784    }
785
786    /// Define a function type in this type section.
787    pub fn function(&mut self) -> ComponentFuncTypeEncoder<'_> {
788        self.ty().function()
789    }
790
791    /// Add a component defined type to this type section.
792    ///
793    /// The returned encoder must be used before adding another type.
794    #[must_use = "the encoder must be used to encode the type"]
795    pub fn defined_type(&mut self) -> ComponentDefinedTypeEncoder<'_> {
796        self.ty().defined_type()
797    }
798
799    /// Defines a new resource type.
800    pub fn resource(&mut self, rep: ValType, dtor: Option<u32>) -> &mut Self {
801        self.ty().resource(rep, dtor);
802        self
803    }
804}
805
806impl Encode for ComponentTypeSection {
807    fn encode(&self, sink: &mut Vec<u8>) {
808        encode_section(sink, self.num_added, &self.bytes);
809    }
810}
811
812impl ComponentSection for ComponentTypeSection {
813    fn id(&self) -> u8 {
814        ComponentSectionId::Type.into()
815    }
816}