# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['wasmbind']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'wasmbind',
    'version': '0.3',
    'description': '',
    'long_description': '# wasmbind\n\nWraps your WebAssembly exports to provide you are with a more usable interface in Python. \nCurrently works with [AssemblyScript](https://assemblyscript.org/) modules, and \n[python-ext-wasm](https://github.com/wasmerio/python-ext-wasm) as the loader.\n\nIn doing so, it tries to play a similar role as [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) \nor [as-bind](https://github.com/torch2424/as-bind) in JavaScript.\n\nInstall with `pip install wasmbind` or [`poetry add wasmbind`](https://github.com/python-poetry/poetry).\n\n**WARNING**: As of this writing, the latest published version 0.3 of `python-ext-wasm` is not supported;\nyou need to run on git master. The released version does not allow us to access the WASM memory. \n\n\n## Features\n\nFeatures: \n\n- ✅ Strings, Arrays, Maps, Custom Classes.\n- ✅ Work with AssemblyScript objects in Python.\n- ✅ Instantiate new AssemblyScript objects in Python. \n\nFuture plans:\n\n- [ ] Allow wrapping arrays returned from WASM.\n- [ ] Improve array allocation by finding available types in RTTI.\n- [ ] Support imports (needs [#28](https://github.com/wasmerio/python-ext-wasm/issues/28))\n- [ ] Improve these docs.\n- [ ] See if we can use RTTI to remove the need for a manual `as_`. We might have to create a class registry\n      similar to [as-bind](https://github.com/torch2424/as-bind/blob/97353ef6f8e39a4277957079b5d6a9e7d85ee709/lib/assembly/as-bind.ts)\n- [ ] Investigate an alternative approach wherein you predefine classes (with types) in Python code.\n- [ ] Allow creation of types without a constructor.\n\n\n## Usage\n\nSetup your module like this:\n\n```python\nfrom wasmer import Instance\nwasm = Instance(open(\'yourscript.wasm\', \'rb\').read())\n\nfrom wasmbind import Module\nmodule = Module(wasm)\n```\n\nHere are some sample interactions.\n\n#### Strings\n\n```typescript\nexport function helloworld(name: string): string {\n    return "hello, " + name\n}\n```\n\n```python\n>>> module.helloworld("michael", as_=str)\n"hello, michael"\n```\n\nYou\'ll note that you have to specificy the desired return type via `as_`. This is because WASM only\ngives us a pointer to a memory location, and we otherwise have no idea what the type is. See the section\n`Resolving Return Values` for other options.\n\nPassing values *into* AssemblyScript works, because we know it the type. In this case, we can allocate\na `string` on the AssemblyScript side and pass the pointer to it into `helloworld`.\n\nNote: You\'ll get a real Python `str` from AssemblyScript, and you are expected to pass real `str` \nobjects to AssemblyScript functions. Strings are immutable in AssemblyScript and Python. Those\nthings mean that for the boundary Python <-> AssemblyScript, they are passed by value and copied. No\nreference counting is involved.\n\n\n#### Objects & Properties\n\n```typescript\nexport class File {\n  constructor(\n    public size: i32,\n  ) {}\n}\n```\n\n```python\n>>> dir = module.Directory(3)\n>>> dir.size\n3\n>>> dir.size = 10\n>>> dir.size\n10\n```\n\n#### Objects\n\n```typescript\nexport class Line {\n  constructor(\n    public s: string\n  ) {}\n}\n\nexport class File {\n  public lines: Line[] = []\n\n  constructor() {}\n  \n  addLine(line: Line): number {\n    this.lines.push(line);\n    return this.lines.length; \n  }\n}\n```\n\n```python\n>>> file = module.File()\n>>> line = module.Line("line 1")\n>>> file.addLine(line)\n1\n```\n\n#### Maps and other generic types\n \nLet\'s say you have a function that takes a map as an argument:\n\n```typescript\nexport function getMap(): Map<string, i32> {\n  return new Map();\n}\n```\n\nFirst, if you look into this module\'s exports, you will note that there is only `getMap()`. The \n`Map` class itself was not exported. \n\nNow, if you add `export {Map}`, depending on your code, you might see exports such as:\n\n```\n\'Map<~lib/string/String,~lib/string/String>#get\', \'Map<i32,i32>#constructor\', \'Map<i32,i32>#clear\'\n```\n\nEvery concrete version of the generic `Map` type is exported separately, the names aren\'t \nvery nice, and finally, the classes are incomplete: Only methods which were used at some\npoint in your code are exported, the rest, I assume, have been optimized away.\n\nCurrently, `wasmbind` does not do anything special with those exports, which means you can\nuse them, but they are not very accessible.\n\nThe best way to use a map, which I have found so far, is this:\n\n```typescript\nexport class StringMap extends Map<string, string> {};\n```\n\nThis will give you a complete and fully-functional `StringMap` class in Python.\n\n\n## Resolving Return Values\n\nIf you have a memory address, you can do:\n\n``module.resolve()`` or ``module.resolve(as_=T)``\n\nIf you have an opaque `AssemblyScriptObject`, you can do `obj.as_(T)`.\n\nPossible values for `as_`:\n\n- If not given, we\'ll try to auto-detect.\n- `str`\n- Any `AssemblyScriptClass` exported by the module.\n- `typing.List` or `typing.List[SomeOtherType]`, with `SomeOtherType` being any `as` value.\n\nOptions for the future:\n\n```python\n# Every return value is a a Opaque Type that you can either call .native() on or .as().\nmodule = Module(instance, value_handler=wrap_opaque)\n\n# Every return value is auto-instantiated via the object header \nmodule = Module(instance, value_handler=auto_resolve)\n\n# Using mypy to predefine the return types of each method and function call. \nmodule = Module(instance, class_registry={})\n```\n\n## Opaque Values\n\nSometimes it can be nice to pass data structures to AssemblyScript that you just want to keep as-is, without \nAssemblyScript touching them, and getting them back; in particular, when dealing with complex data structures.\n\nTo help support this case, `wasmbind` supports a mechanism by which:\n\n- You can put an arbitrary Python value into a local registry.\n- You\'ll be given an opaque object that you can pass to AssemblyScript functions.\n- AssemblyScript will see an integer (we start counting at 1, so it\'s up to you if you want to use u8, u32, ...)\n- When a value comes out of AssemblyScript, you need to instruct `wasmbind`, using the regular mechanisms, to\n  resolve this opaque pointer as a `wasmbind.OpaqueValue` instance.\n  \nHere is an example:\n\n```typescript\nexport function take(val: u8): u8 { return val; }\n```\n\n```python\nfrom wasmbind import OpaqueValue\nmy_map = {"x": 1}\nwrapped_map = module.register_opaque_value(my_map)\nassert module.take(wrapped_map, as_=OpaqueValue) == {"x": 1}\n```\n \n\n## Notes\n\nIn part, this is a port of the AssemblyScript loader. The following links were helpful in implementing this:\n\n- [AssemblyScript Loader code](https://github.com/AssemblyScript/assemblyscript/blob/master/lib/loader/index.js)\n- [AssemblyScript Loader docs](https://docs.assemblyscript.org/basics/loader#why-not-more-convenient)\n- [wasmer-as code](https://github.com/onsails/wasmer-as)\n- [as-bind code](https://github.com/torch2424/as-bind)\n- [python-ext-wasm docs](https://github.com/wasmerio/python-ext-wasm)',
    'author': 'Michael Elsdörfer',
    'author_email': 'michael@elsdoerfer.info',
    'maintainer': None,
    'maintainer_email': None,
    'url': None,
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
