usecrate::component::*; usecrate::{ExportKind, Module, NameMap, RawSection, ValType}; use alloc::format; use alloc::vec::Vec; use core::mem;
/// Convenience type to build a component incrementally and automatically keep /// track of index spaces. /// /// This type is intended to be a wrapper around the [`Component`] encoding type /// which is useful for building it up incrementally over time. This type will /// automatically collect definitions into sections and reports the index of all /// items added by keeping track of indices internally. #[derive(Debug, Default)] pubstruct ComponentBuilder { /// The binary component that's being built.
component: Component,
/// The last section which was appended to during encoding. This type is /// generated by the `section_accessors` macro below. /// /// When something is encoded this is used if it matches the kind of item /// being encoded, otherwise it's "flushed" to the output component and a /// new section is started.
last_section: LastSection,
impl ComponentBuilder { /// Returns the current number of core modules. pubfn core_module_count(&self) -> u32 { self.core_modules.count
}
/// Returns the current number of core funcs. pubfn core_func_count(&self) -> u32 { self.core_funcs.count
}
/// Returns the current number of core types. pubfn core_type_count(&self) -> u32 { self.core_types.count
}
/// Returns the current number of core memories. pubfn core_memory_count(&self) -> u32 { self.core_memories.count
}
/// Returns the current number of core tables. pubfn core_table_count(&self) -> u32 { self.core_tables.count
}
/// Returns the current number of core instances. pubfn core_instance_count(&self) -> u32 { self.core_instances.count
}
/// Returns the current number of core tags. pubfn core_tag_count(&self) -> u32 { self.core_tags.count
}
/// Returns the current number of core globals. pubfn core_global_count(&self) -> u32 { self.core_globals.count
}
/// Returns the current number of component funcs. pubfn func_count(&self) -> u32 { self.funcs.count
}
/// Returns the current number of component instances. pubfn instance_count(&self) -> u32 { self.instances.count
}
/// Returns the current number of component values. pubfn value_count(&self) -> u32 { self.values.count
}
/// Returns the current number of components. pubfn component_count(&self) -> u32 { self.components.count
}
/// Returns the current number of component types. pubfn type_count(&self) -> u32 { self.types.count
}
/// Add all debug names registered to the component. pubfn append_names(&mutself) { letmut names = ComponentNameSection::new(); if !self.core_funcs.names.is_empty() {
names.core_funcs(&self.core_funcs.names);
} if !self.core_tables.names.is_empty() {
names.core_tables(&self.core_tables.names);
} if !self.core_memories.names.is_empty() {
names.core_memories(&self.core_memories.names);
} if !self.core_globals.names.is_empty() {
names.core_globals(&self.core_globals.names);
} if !self.core_tags.names.is_empty() {
names.core_tags(&self.core_tags.names);
} if !self.core_types.names.is_empty() {
names.core_types(&self.core_types.names);
} if !self.core_modules.names.is_empty() {
names.core_modules(&self.core_modules.names);
} if !self.core_instances.names.is_empty() {
names.core_instances(&self.core_instances.names);
} if !self.instances.names.is_empty() {
names.instances(&self.instances.names);
} if !self.funcs.names.is_empty() {
names.funcs(&self.funcs.names);
} if !self.types.names.is_empty() {
names.types(&self.types.names);
} if !self.components.names.is_empty() {
names.components(&self.components.names);
} if !self.instances.names.is_empty() {
names.instances(&self.instances.names);
} if !names.is_empty() { self.custom_section(&names.as_custom());
}
}
/// Completes this component and returns the binary encoding of the entire /// component. pubfn finish(mutself) -> Vec<u8> { self.flush(); self.component.finish()
}
/// Encodes a core wasm `Module` into this component, returning its index. pubfn core_module(&mutself, debug_name: Option<&str>, module: &Module) -> u32 { self.flush(); self.component.section(&ModuleSection(module)); self.core_modules.add(debug_name)
}
/// Encodes a core wasm `module` into this component, returning its index. pubfn core_module_raw(&mutself, debug_name: Option<&str>, module: &[u8]) -> u32 { self.flush(); self.component.section(&RawSection {
id: ComponentSectionId::CoreModule.into(),
data: module,
}); self.core_modules.add(debug_name)
}
/// Instantiates a core wasm module at `module_index` with the `args` /// provided. /// /// Returns the index of the core wasm instance created. pubfn core_instantiate<'a, A>(
&mutself,
debug_name: Option<&str>,
module_index: u32,
args: A,
) -> u32 where
A: IntoIterator<Item = (&'a str, ModuleArg)>,
A::IntoIter: ExactSizeIterator,
{ self.instances().instantiate(module_index, args); self.core_instances.add(debug_name)
}
/// Creates a new core wasm instance from the `exports` provided. /// /// Returns the index of the core wasm instance created. pubfn core_instantiate_exports<'a, E>(&mut self, debug_name: Option<&str>, exports: E) -> u32 where
E: IntoIterator<Item = (&'a str, ExportKind, u32)>,
E::IntoIter: ExactSizeIterator,
{ self.instances().export_items(exports); self.core_instances.add(debug_name)
}
/// Creates a new aliased item where the core `instance` specified has its /// export `name` aliased out with the `kind` specified. /// /// Returns the index of the item created. pubfn core_alias_export(
&mutself,
debug_name: Option<&str>,
instance: u32,
name: &str,
kind: ExportKind,
) -> u32 { self.alias(
debug_name,
Alias::CoreInstanceExport {
instance,
kind,
name,
},
)
}
/// Creates an alias to a previous component instance's exported item. /// /// The `instance` provided is the instance to access and the `name` is the /// item to access. /// /// Returns the index of the new item defined. pubfn alias_export(&mutself, instance: u32, name: &str, kind: ComponentExportKind) -> u32 { self.alias(
Some(name),
Alias::InstanceExport {
instance,
kind,
name,
},
)
}
/// Lowers the `func_index` component function into a core wasm function /// using the `options` provided. /// /// Returns the index of the core wasm function created. pubfn lower_func<O>(&mutself, debug_name: Option<&str>, func_index: u32, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions().lower(func_index, options); self.core_funcs.add(debug_name)
}
/// Lifts the core wasm `core_func_index` function with the component /// function type `type_index` and `options`. /// /// Returns the index of the component function created. pubfn lift_func<O>(
&mutself,
debug_name: Option<&str>,
core_func_index: u32,
type_index: u32,
options: O,
) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions()
.lift(core_func_index, type_index, options); self.funcs.add(debug_name)
}
/// Imports a new item into this component with the `name` and `ty` specified. pubfn import(&mutself, name: &str, ty: ComponentTypeRef) -> u32 { let ret = match &ty {
ComponentTypeRef::Instance(_) => self.instances.add(Some(name)),
ComponentTypeRef::Func(_) => self.funcs.add(Some(name)),
ComponentTypeRef::Type(..) => self.types.add(Some(name)),
ComponentTypeRef::Component(_) => self.components.add(Some(name)),
ComponentTypeRef::Module(_) => self.core_modules.add(Some(name)),
ComponentTypeRef::Value(_) => self.values.add(Some(name)),
}; self.imports().import(name, ty);
ret
}
/// Exports a new item from this component with the `name` and `kind` /// specified. /// /// The `idx` is the item to export and the `ty` is an optional type to /// ascribe to the export. pubfn export(
&mutself,
name: &str,
kind: ComponentExportKind,
idx: u32,
ty: Option<ComponentTypeRef>,
) -> u32 { self.exports().export(name, kind, idx, ty); self.inc_kind(Some(name), kind)
}
/// Creates a new encoder for the next core type in this component. pubfn core_type(&mutself, debug_name: Option<&str>) -> (u32, ComponentCoreTypeEncoder<'_>) {
(self.core_types.add(debug_name), self.core_types().ty())
}
/// Creates a new encoder for the next type in this component. pubfn ty(&mutself, debug_name: Option<&str>) -> (u32, ComponentTypeEncoder<'_>) {
(self.types.add(debug_name), self.types().ty())
}
/// Creates a new instance type within this component. pubfn type_instance(&mutself, debug_name: Option<&str>, ty: &InstanceType) -> u32 { self.types().instance(ty); self.types.add(debug_name)
}
/// Creates a new component type within this component. pubfn type_component(&mutself, debug_name: Option<&str>, ty: &ComponentType) -> u32 { self.types().component(ty); self.types.add(debug_name)
}
/// Creates a new defined component type within this component. pubfn type_defined(
&mutself,
debug_name: Option<&str>,
) -> (u32, ComponentDefinedTypeEncoder<'_>) {
(self.types.add(debug_name), self.types().defined_type())
}
/// Creates a new component function type within this component. pubfn type_function(
&mutself,
debug_name: Option<&str>,
) -> (u32, ComponentFuncTypeEncoder<'_>) {
(self.types.add(debug_name), self.types().function())
}
/// Declares a new resource type within this component. pubfn type_resource(
&mutself,
debug_name: Option<&str>,
rep: ValType,
dtor: Option<u32>,
) -> u32 { self.types().resource(rep, dtor); self.types.add(debug_name)
}
/// Defines a new subcomponent of this component. pubfn component(&mutself, debug_name: Option<&str>, mut builder: ComponentBuilder) -> u32 {
builder.flush(); self.flush(); self.component
.section(&NestedComponentSection(&builder.component)); self.components.add(debug_name)
}
/// Defines a new subcomponent of this component. pubfn component_raw(&mutself, debug_name: Option<&str>, data: &[u8]) -> u32 { let raw_section = RawSection {
id: ComponentSectionId::Component.into(),
data,
}; self.flush(); self.component.section(&raw_section); self.components.add(debug_name)
}
/// Instantiates the `component_index` specified with the `args` specified. pubfn instantiate<A, S>(
&mutself,
debug_name: Option<&str>,
component_index: u32,
args: A,
) -> u32 where
A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
A::IntoIter: ExactSizeIterator,
S: AsRef<str>,
{ self.component_instances()
.instantiate(component_index, args); self.instances.add(debug_name)
}
/// Declares a new `resource.drop` intrinsic. pubfn resource_drop(&mutself, ty: u32) -> u32 { self.canonical_functions().resource_drop(ty); self.core_funcs.add(Some("resource.drop"))
}
/// Declares a new `resource.drop` intrinsic. pubfn resource_drop_async(&mutself, ty: u32) -> u32 { self.canonical_functions().resource_drop_async(ty); self.core_funcs.add(Some("resource.drop async"))
}
/// Declares a new `resource.new` intrinsic. pubfn resource_new(&mutself, ty: u32) -> u32 { self.canonical_functions().resource_new(ty); self.core_funcs.add(Some("resource.new"))
}
/// Declares a new `resource.rep` intrinsic. pubfn resource_rep(&mutself, ty: u32) -> u32 { self.canonical_functions().resource_rep(ty); self.core_funcs.add(Some("resource.rep"))
}
/// Declares a new `thread.spawn_ref` intrinsic. pubfn thread_spawn_ref(&mutself, ty: u32) -> u32 { self.canonical_functions().thread_spawn_ref(ty); self.core_funcs.add(Some("thread.spawn-ref"))
}
/// Declares a new `thread.available_parallelism` intrinsic. pubfn thread_available_parallelism(&mutself) -> u32 { self.canonical_functions().thread_available_parallelism(); self.core_funcs.add(Some("thread.available-parallelism"))
}
/// Declares a new `backpressure.inc` intrinsic. pubfn backpressure_inc(&mutself) -> u32 { self.canonical_functions().backpressure_inc(); self.core_funcs.add(Some("backpressure.inc"))
}
/// Declares a new `backpressure.dec` intrinsic. pubfn backpressure_dec(&mutself) -> u32 { self.canonical_functions().backpressure_dec(); self.core_funcs.add(Some("backpressure.dec"))
}
/// Declares a new `task.return` intrinsic. pubfn task_return<O>(&mutself, ty: Option<ComponentValType>, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions().task_return(ty, options); self.core_funcs.add(Some("task.return"))
}
/// Declares a new `task.cancel` intrinsic. pubfn task_cancel(&mutself) -> u32 { self.canonical_functions().task_cancel(); self.core_funcs.add(Some("task.cancel"))
}
/// Declares a new `context.get` intrinsic. pubfn context_get(&mutself, i: u32) -> u32 { self.canonical_functions().context_get(i); self.core_funcs.add(Some(&format!("context.get {i}")))
}
/// Declares a new `context.set` intrinsic. pubfn context_set(&mutself, i: u32) -> u32 { self.canonical_functions().context_set(i); self.core_funcs.add(Some(&format!("context.set {i}")))
}
/// Declares a new `thread.yield` intrinsic. pubfn thread_yield(&mutself, cancellable: bool) -> u32 { self.canonical_functions().thread_yield(cancellable); self.core_funcs.add(Some("thread.yield"))
}
/// Declares a new `subtask.drop` intrinsic. pubfn subtask_drop(&mutself) -> u32 { self.canonical_functions().subtask_drop(); self.core_funcs.add(Some("subtask.drop"))
}
/// Declares a new `subtask.cancel` intrinsic. pubfn subtask_cancel(&mutself, async_: bool) -> u32 { self.canonical_functions().subtask_cancel(async_); self.core_funcs.add(Some("subtask.cancel"))
}
/// Declares a new `stream.new` intrinsic. pubfn stream_new(&mutself, ty: u32) -> u32 { self.canonical_functions().stream_new(ty); self.core_funcs.add(Some("stream.new"))
}
/// Declares a new `stream.read` intrinsic. pubfn stream_read<O>(&mutself, ty: u32, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions().stream_read(ty, options); self.core_funcs.add(Some("stream.read"))
}
/// Declares a new `stream.write` intrinsic. pubfn stream_write<O>(&mutself, ty: u32, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions().stream_write(ty, options); self.core_funcs.add(Some("stream.write"))
}
/// Declares a new `stream.cancel-read` intrinsic. pubfn stream_cancel_read(&mutself, ty: u32, async_: bool) -> u32 { self.canonical_functions().stream_cancel_read(ty, async_); self.core_funcs.add(Some("stream.cancel-read"))
}
/// Declares a new `stream.cancel-write` intrinsic. pubfn stream_cancel_write(&mutself, ty: u32, async_: bool) -> u32 { self.canonical_functions().stream_cancel_write(ty, async_); self.core_funcs.add(Some("stream.cancel-write"))
}
/// Declares a new `stream.drop-readable` intrinsic. pubfn stream_drop_readable(&mutself, ty: u32) -> u32 { self.canonical_functions().stream_drop_readable(ty); self.core_funcs.add(Some("stream.drop-readable"))
}
/// Declares a new `stream.drop-writable` intrinsic. pubfn stream_drop_writable(&mutself, ty: u32) -> u32 { self.canonical_functions().stream_drop_writable(ty); self.core_funcs.add(Some("stream.drop-writable"))
}
/// Declares a new `future.new` intrinsic. pubfn future_new(&mutself, ty: u32) -> u32 { self.canonical_functions().future_new(ty); self.core_funcs.add(Some("future.new"))
}
/// Declares a new `future.read` intrinsic. pubfn future_read<O>(&mutself, ty: u32, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions().future_read(ty, options); self.core_funcs.add(Some("future.read"))
}
/// Declares a new `future.write` intrinsic. pubfn future_write<O>(&mutself, ty: u32, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions().future_write(ty, options); self.core_funcs.add(Some("future.write"))
}
/// Declares a new `future.cancel-read` intrinsic. pubfn future_cancel_read(&mutself, ty: u32, async_: bool) -> u32 { self.canonical_functions().future_cancel_read(ty, async_); self.core_funcs.add(Some("future.cancel-read"))
}
/// Declares a new `future.cancel-write` intrinsic. pubfn future_cancel_write(&mutself, ty: u32, async_: bool) -> u32 { self.canonical_functions().future_cancel_write(ty, async_); self.core_funcs.add(Some("future.cancel-write"))
}
/// Declares a new `future.drop-readable` intrinsic. pubfn future_drop_readable(&mutself, ty: u32) -> u32 { self.canonical_functions().future_drop_readable(ty); self.core_funcs.add(Some("future.drop-readable"))
}
/// Declares a new `future.drop-writable` intrinsic. pubfn future_drop_writable(&mutself, ty: u32) -> u32 { self.canonical_functions().future_drop_writable(ty); self.core_funcs.add(Some("future.drop-writable"))
}
/// Declares a new `error-context.new` intrinsic. pubfn error_context_new<O>(&mutself, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions().error_context_new(options); self.core_funcs.add(Some("error-context.new"))
}
/// Declares a new `error-context.debug-message` intrinsic. pubfn error_context_debug_message<O>(&mutself, options: O) -> u32 where
O: IntoIterator<Item = CanonicalOption>,
O::IntoIter: ExactSizeIterator,
{ self.canonical_functions()
.error_context_debug_message(options); self.core_funcs.add(Some("error-context.debug-message"))
}
/// Declares a new `error-context.drop` intrinsic. pubfn error_context_drop(&mutself) -> u32 { self.canonical_functions().error_context_drop(); self.core_funcs.add(Some("error-context.drop"))
}
/// Declares a new `waitable-set.new` intrinsic. pubfn waitable_set_new(&mutself) -> u32 { self.canonical_functions().waitable_set_new(); self.core_funcs.add(Some("waitable-set.new"))
}
/// Declares a new `waitable-set.wait` intrinsic. pubfn waitable_set_wait(&mutself, cancellable: bool, memory: u32) -> u32 { self.canonical_functions()
.waitable_set_wait(cancellable, memory); self.core_funcs.add(Some("waitable-set.wait"))
}
/// Declares a new `waitable-set.poll` intrinsic. pubfn waitable_set_poll(&mutself, cancellable: bool, memory: u32) -> u32 { self.canonical_functions()
.waitable_set_poll(cancellable, memory); self.core_funcs.add(Some("waitable-set.poll"))
}
/// Declares a new `waitable-set.drop` intrinsic. pubfn waitable_set_drop(&mutself) -> u32 { self.canonical_functions().waitable_set_drop(); self.core_funcs.add(Some("waitable-set.drop"))
}
/// Declares a new `waitable.join` intrinsic. pubfn waitable_join(&mutself) -> u32 { self.canonical_functions().waitable_join(); self.core_funcs.add(Some("waitable.join"))
}
/// Declares a new `thread.index` intrinsic. pubfn thread_index(&mutself) -> u32 { self.canonical_functions().thread_index(); self.core_funcs.add(Some("thread.index"))
}
/// Declares a new `thread.new-indirect` intrinsic. pubfn thread_new_indirect(&mutself, func_ty_idx: u32, table_index: u32) -> u32 { self.canonical_functions()
.thread_new_indirect(func_ty_idx, table_index); self.core_funcs.add(Some("thread.new-indirect"))
}
/// Declares a new `thread.switch-to` intrinsic. pubfn thread_switch_to(&mutself, cancellable: bool) -> u32 { self.canonical_functions().thread_switch_to(cancellable); self.core_funcs.add(Some("thread.switch-to"))
}
/// Declares a new `thread.suspend` intrinsic. pubfn thread_suspend(&mutself, cancellable: bool) -> u32 { self.canonical_functions().thread_suspend(cancellable); self.core_funcs.add(Some("thread.suspend"))
}
/// Declares a new `thread.resume-later` intrinsic. pubfn thread_resume_later(&mutself) -> u32 { self.canonical_functions().thread_resume_later(); self.core_funcs.add(Some("thread.resume-later"))
}
/// Declares a new `thread.yield-to` intrinsic. pubfn thread_yield_to(&mutself, cancellable: bool) -> u32 { self.canonical_functions().thread_yield_to(cancellable); self.core_funcs.add(Some("thread.yield-to"))
}
/// Adds a new custom section to this component. pubfn custom_section(&mutself, section: &CustomSection<'_>) { self.flush(); self.component.section(section);
}
/// Adds a new custom section to this component. pubfn raw_custom_section(&mutself, section: &[u8]) { self.flush(); self.component.section(&RawCustomSection(section));
}
}
// Helper macro to generate methods on `ComponentBuilder` to get specific // section encoders that automatically flush and write out prior sections as // necessary.
macro_rules! section_accessors {
($($method:ident => $section:ident)*) => ( #[derive(Debug, Default)] enum LastSection { #[default]
None,
$($section($section),)*
}
impl ComponentBuilder {
$( fn $method(&mutself) -> &mut $section { match &self.last_section { // The last encoded section matches the section that's // being requested, so no change is necessary.
LastSection::$section(_) => {}
// Otherwise the last section didn't match this section, // so flush any prior section if needed and start // encoding the desired section of this method.
_ => { self.flush(); self.last_section = LastSection::$section($section::new());
}
} match &mutself.last_section {
LastSection::$section(ret) => ret,
_ => unreachable!()
}
}
)*
/// Writes out the last section into the final component binary if /// there is a section specified, otherwise does nothing. fn flush(&mutself) { match mem::take(&mutself.last_section) {
LastSection::None => {}
$(
LastSection::$section(section) => { self.component.section(§ion);
}
)*
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.