'''
Bindings to the {{interface_name}} library.
'''
from pathlib import Path
from typing import Optional, Any
from wasmer import Store, Module, wasi # type: ignore
{%- for lib in libraries %}
from .{{lib.ident}}.bindings import (
{{lib.class_name}} as _{{lib.class_name}},
{%- for imp in lib.imports %}
add_{{imp.ident}}_to_imports as _{{lib.ident}}__add_{{imp.ident}}_to_imports,
{{imp.class_name}} as _{{lib.ident}}__{{imp.class_name}},
{%- endfor %}
)
{%- endfor %}
class Bindings:
"""
Instantiate bindings to the various libraries in this package.
"""
def __init__(self, store: Store):
self._store = store
self._cache: dict[str, Module] = {}
def _get_module(self, filename: str) -> Module:
if filename in self._cache:
return self._cache[filename]
wasm = Path(__file__).parent.joinpath(filename).read_bytes()
module = Module(self._store, wasm)
self._cache[filename] = module
return module
{% for lib in libraries -%}
def {{lib.ident}}(
self,
{%- if lib.wasi %}
env: Optional[wasi.Environment] = None,
{%- endif %}
{%- for imp in lib.imports %}
{{imp.ident}}: _{{lib.ident}}__{{imp.class_name}},
{%- endfor %}
module: Optional[Module] = None,
) -> _{{lib.class_name}}:
"""
Instantiate the "{{lib.ident}}" library.
{%- if lib.wasi %}
:param env: A pre-initialized WASI environment. If not specified, a
default value will be used.
{%- endif %}
{%- for imp in lib.imports %}
:param {{imp.ident}}: An implementation of the "{{imp.interface_name}}" interface.
{%- endfor %}
:param module: A user-specified WebAssembly module to use instead of the
one bundled with this package.
"""
filename = "{{lib.ident}}/{{lib.module_filename}}"
if not module:
module = self._get_module(filename)
imports: dict[str, Any] = {}
wrapper = None
def get_export(item_name: str):
assert wrapper is not None
return getattr(wrapper.instance.exports, item_name)
{%- for imp in lib.imports %}
_{{lib.ident}}__add_{{imp.ident}}_to_imports(self._store, imports, {{imp.ident}}, get_export)
{%- endfor %}
{%- if lib.wasi %}
version = wasi.get_version(module, strict=True)
assert version is not None, f'"{filename}" is not a valid WASI executable'
if not env:
env = wasi.StateBuilder("{{lib.ident}}").finalize()
wasi_imports = env.generate_imports(self._store, version)
imports.update(wasi_imports)
{%- endif %}
wrapper = _{{lib.class_name}}(self._store, imports, module)
return wrapper
{% endfor %}