├── .env.template ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── agent ├── ffi.mbt ├── github.mbt ├── interface_exports_wasi_http_incoming_handler_export.mbt └── moon.pkg.json ├── crypto ├── ber.mbt ├── hash.mbt ├── hmac.mbt ├── jwt.mbt ├── moon.pkg.json └── rsa.mbt ├── ffi ├── moon.pkg.json └── top.mbt ├── gen ├── ffi.mbt ├── interface_exports_wasi_http_incoming_handler_export.mbt └── moon.pkg.json ├── http ├── moon.pkg.json ├── top.mbt └── top_test.mbt ├── interface └── imports │ ├── fermyon │ └── spin │ │ ├── keyValue │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ ├── llm │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ ├── mqtt │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ ├── mysql │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ ├── postgres │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ ├── rdbmsTypes │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ ├── redis │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ ├── sqlite │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ │ └── variables │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── wasi │ ├── cli │ ├── environment │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── exit │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── stderr │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── stdin │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── stdout │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── terminalInput │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── terminalOutput │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── terminalStderr │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── terminalStdin │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── terminalStdout │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── clocks │ ├── monotonicClock │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── wallClock │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── filesystem │ ├── preopens │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── types │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── http │ ├── outgoingHandler │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── types │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── io │ ├── error │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── poll │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── streams │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── random │ ├── insecure │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ ├── insecureSeed │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── random │ │ ├── README.md │ │ ├── ffi.mbt │ │ ├── moon.pkg.json │ │ └── top.mbt │ └── sockets │ ├── instanceNetwork │ ├── README.md │ ├── ffi.mbt │ ├── moon.pkg.json │ └── top.mbt │ ├── ipNameLookup │ ├── ffi.mbt │ ├── moon.pkg.json │ └── top.mbt │ ├── network │ ├── ffi.mbt │ ├── moon.pkg.json │ └── top.mbt │ ├── tcp │ ├── ffi.mbt │ ├── moon.pkg.json │ └── top.mbt │ ├── tcpCreateSocket │ ├── ffi.mbt │ ├── moon.pkg.json │ └── top.mbt │ ├── udp │ ├── ffi.mbt │ ├── moon.pkg.json │ └── top.mbt │ └── udpCreateSocket │ ├── ffi.mbt │ ├── moon.pkg.json │ └── top.mbt ├── io ├── io.mbt └── moon.pkg.json ├── moon.mod.json ├── publish.sh ├── spin.toml ├── utils ├── base64.mbt ├── encoding.mbt ├── moon.pkg.json └── resource.mbt └── wit ├── deps.lock ├── deps.toml ├── deps ├── cli-2023-10-18 │ ├── command.wit │ ├── environment.wit │ ├── exit.wit │ ├── reactor.wit │ ├── run.wit │ ├── stdio.wit │ └── terminal.wit ├── cli-2023-11-10 │ ├── command.wit │ ├── environment.wit │ ├── exit.wit │ ├── reactor.wit │ ├── run.wit │ ├── stdio.wit │ └── terminal.wit ├── cli │ ├── command.wit │ ├── environment.wit │ ├── exit.wit │ ├── imports.wit │ ├── run.wit │ ├── stdio.wit │ └── terminal.wit ├── clocks-2023-10-18 │ ├── monotonic-clock.wit │ ├── timezone.wit │ ├── wall-clock.wit │ └── world.wit ├── clocks-2023-11-10 │ ├── monotonic-clock.wit │ ├── wall-clock.wit │ └── world.wit ├── clocks │ ├── monotonic-clock.wit │ ├── wall-clock.wit │ └── world.wit ├── filesystem-2023-10-18 │ ├── preopens.wit │ ├── types.wit │ └── world.wit ├── filesystem-2023-11-10 │ ├── preopens.wit │ ├── types.wit │ └── world.wit ├── filesystem │ ├── preopens.wit │ ├── types.wit │ └── world.wit ├── http-2023-10-18 │ ├── incoming-handler.wit │ ├── outgoing-handler.wit │ ├── proxy.wit │ └── types.wit ├── http-2023-11-10 │ ├── handler.wit │ ├── proxy.wit │ └── types.wit ├── http │ ├── handler.wit │ ├── proxy.wit │ └── types.wit ├── io-2023-10-18 │ ├── poll.wit │ ├── streams.wit │ └── world.wit ├── io-2023-11-10 │ ├── error.wit │ ├── poll.wit │ ├── streams.wit │ └── world.wit ├── io │ ├── error.wit │ ├── poll.wit │ ├── streams.wit │ └── world.wit ├── random-2023-10-18 │ ├── insecure-seed.wit │ ├── insecure.wit │ ├── random.wit │ └── world.wit ├── random-2023-11-10 │ ├── insecure-seed.wit │ ├── insecure.wit │ ├── random.wit │ └── world.wit ├── random │ ├── insecure-seed.wit │ ├── insecure.wit │ ├── random.wit │ └── world.wit ├── sockets-2023-10-18 │ ├── instance-network.wit │ ├── ip-name-lookup.wit │ ├── network.wit │ ├── tcp-create-socket.wit │ ├── tcp.wit │ ├── udp-create-socket.wit │ ├── udp.wit │ └── world.wit ├── sockets-2023-11-10 │ ├── instance-network.wit │ ├── ip-name-lookup.wit │ ├── network.wit │ ├── tcp-create-socket.wit │ ├── tcp.wit │ ├── udp-create-socket.wit │ ├── udp.wit │ └── world.wit ├── sockets │ ├── instance-network.wit │ ├── ip-name-lookup.wit │ ├── network.wit │ ├── tcp-create-socket.wit │ ├── tcp.wit │ ├── udp-create-socket.wit │ ├── udp.wit │ └── world.wit ├── spin │ ├── key-value.wit │ ├── llm.wit │ ├── mqtt.wit │ ├── mysql.wit │ ├── postgres.wit │ ├── rdbms-types.wit │ ├── redis.wit │ ├── sqlite.wit │ ├── variables.wit │ └── world.wit └── spin@unversioned │ ├── config.wit │ ├── http-types.wit │ ├── http.wit │ ├── inbound-http.wit │ ├── inbound-redis.wit │ ├── key-value.wit │ ├── llm.wit │ ├── mysql.wit │ ├── postgres.wit │ ├── rdbms-types.wit │ ├── redis-types.wit │ ├── redis.wit │ ├── sqlite.wit │ └── world.wit └── world.wit /.env.template: -------------------------------------------------------------------------------- 1 | # Rename to .env file 2 | SPIN_VARIABLE_OPENAPI_KEY="sk-your-open-api-key" 3 | SPIN_VARIABLE_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- 4 | Your RSA Private Key 5 | -----END RSA PRIVATE KEY-----" 6 | SPIN_VARIABLE_CLIENT_ID="Your GitHub Client ID" 7 | SPIN_VARIABLE_APP_ID="Your GitHub App ID" 8 | SPIN_VARIABLE_USER_AGENT="Your User Agent" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .spin 3 | .mooncakes 4 | .env -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This project uses WIT files from [spin](https://github.com/fermyon/spin) and [wit-bindgen](https://github.com/bytecodealliance/wit-bindgen) 2 | to generate code under `interface` `gen` and `ffi`. 3 | Both of the projects are licensed under Apache 2 License with LLVM exceptions. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MoonBit AI Agent using Components 2 | 3 | ## Requirements 4 | 5 | The following tools are needed: 6 | 7 | - [spin cli](https://developer.fermyon.com/spin/v2/install) and a fermyon cloud account if you'd like to deploy it at the end 8 | - [wasm-tools](https://github.com/bytecodealliance/wasm-tools) 9 | 10 | and of course, [moonbit toolchain](https://www.moonbitlang.com/download/). 11 | 12 | For this example, you will also need to [create a GitHub App](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps) and obtain the private key, the client ID and the App ID and the secret. You may consider following the step 2 through 5 with [the official tutorial](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart). You may configure the callback URL of the GitHub App with the Spin application for production or a proxy (e.g. ) for local development. 13 | 14 | You also need to have access to an AI provider, such as [DeepSeek](https://www.deepseek.com/) or [Silicon Flow](https://siliconflow.cn/models). You need an API Key to access the LLM, the endpoint the the completion functionality, and the name of the LLM that you'd like to use. We are using the DeepSeek Coder provided by Silicon Flow in this demo. 15 | 16 | ## How to use 17 | 18 | - Copy the folder `gen` to the one you like, and then implement the `let server` global variable. 19 | - Add configurations in `spin.toml` as the existing one. 20 | 21 | Build commands: 22 | - Install dependency with `moon update && moon install` 23 | - Local development: `spin build && spin up`. 24 | - Publish: `./publish.sh`. Don't forget to `spin login` the service. 25 | 26 | ### Environment variables 27 | 28 | Copy `.env.template` to `.env` and fill in the environment variables. 29 | 30 | They are configured in `variables` for `spin.toml` and `component.agent.variables` will use them so that component can have access. The example application use the environment variables to pass secrets. One may use external vault in production. Check out the [official document](https://developer.fermyon.com/spin/v2/variables). 31 | 32 | ## Project Structure 33 | 34 | Most files are generated with 35 | 36 | ```bash 37 | wit-bindgen moonbit --derive-show --derive-eq --derive-error --out-dir . wit 38 | ``` 39 | 40 | Note that the MoonBit support is accepted by the `bytecode-alliance/wit-bindgen` so there is where you should install the `wit-bindgen`now. 41 | 42 | Apart from the auto-generated code: 43 | 44 | - `agent`: an example of AI Agent using MoonBit. 45 | 46 | - `http`: a wrapper around the underlying `wasi-http` interface, providing proper lifetime handling. One should always call `response.body.trailer` before it goes out of scope. It is built with the concept of ["Your Server as a Function"](https://monkey.org/~marius/funsrv.pdf) as [http4k](https://www.http4k.org) as well as the `wasi-http` itself. 47 | 48 | - `crypto`: containing a jwt RS256 implementation for signing GitHub access token, and necessary RSA / HMAC algorithms. 49 | 50 | - `io`: a thin wrapper around the underlying `wasi-io` streams. 51 | 52 | - `utils`: some helper functions for encoding/decoding base64 and utf-8. 53 | 54 | ## Future Work 55 | 56 | As of the project itself, there are several things we can improve: 57 | 58 | - We should validate incoming deliveries with the HMAC algorithms (which is implemented) 59 | - Use Vault for keys 60 | - Use Redis Trigger for long running task (though not yet supported by fermyon cloud) -------------------------------------------------------------------------------- /agent/ffi.mbt: -------------------------------------------------------------------------------- 1 | pub fn cabi_realloc( 2 | src_offset : Int, 3 | src_size : Int, 4 | _dst_alignment : Int, 5 | dst_size : Int 6 | ) -> Int { 7 | // malloc 8 | if src_offset == 0 && src_size == 0 { 9 | return @ffi.malloc(dst_size) 10 | } 11 | // free 12 | if dst_size <= 0 { 13 | @ffi.free(src_offset) 14 | return 0 15 | } 16 | // realloc 17 | let dst = @ffi.malloc(dst_size) 18 | @ffi.copy(dst, src_offset) 19 | @ffi.free(src_offset) 20 | dst 21 | } 22 | 23 | // let return_area : Int = @ffi.malloc(0) 24 | -------------------------------------------------------------------------------- /agent/interface_exports_wasi_http_incoming_handler_export.mbt: -------------------------------------------------------------------------------- 1 | // Copyright 2024 International Digital Economy Academy 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub fn wasmExportHandle(p0 : Int, p1 : Int) -> Unit { 16 | server.serve()( 17 | @types.IncomingRequest::IncomingRequest(p0), 18 | @types.ResponseOutparam::ResponseOutparam(p1), 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /agent/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "link": { 3 | "wasm": { 4 | "exports": [ 5 | "cabi_realloc:cabi_realloc", 6 | "wasmExportHandle:wasi:http/incoming-handler@0.2.0#handle" 7 | ], 8 | "export-memory-name": "memory", 9 | "heap-start-address": 16 10 | } 11 | }, 12 | "import": [ 13 | { 14 | "path": "moonbit/spin/ffi", 15 | "alias": "ffi" 16 | }, 17 | { 18 | "path": "moonbit/spin/interface/imports/wasi/http/types", 19 | "alias": "types" 20 | }, 21 | "moonbit/spin/http", 22 | "moonbit/spin/utils", 23 | "moonbit/spin/io", 24 | "moonbit/spin/interface/imports/wasi/cli/stdout", 25 | "moonbit/spin/interface/imports/wasi/io/streams", 26 | "moonbit/spin/interface/imports/wasi/cli/stderr", 27 | "moonbit/spin/interface/imports/wasi/cli/environment", 28 | "moonbit/spin/interface/imports/fermyon/spin/variables", 29 | "moonbit/spin/crypto" 30 | ] 31 | } -------------------------------------------------------------------------------- /crypto/hash.mbt: -------------------------------------------------------------------------------- 1 | // Copyright 2024 International Digital Economy Academy 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub(all) enum HashAlgorithm { 16 | MD5 17 | SHA224 18 | SHA256 19 | } 20 | 21 | pub fn oid(self : HashAlgorithm) -> Array[Int] { 22 | match self { 23 | MD5 => [1, 2, 840, 113549, 2, 5] 24 | SHA224 => [2, 16, 840, 1, 101, 3, 4, 2, 4] 25 | SHA256 => [2, 16, 840, 1, 101, 3, 4, 2, 1] 26 | } 27 | } 28 | 29 | pub fn oid_with_rsa_encryption(self : HashAlgorithm) -> Array[Int] { 30 | let pkcs_1 = [1, 2, 840, 113549, 1, 1] 31 | match self { 32 | MD5 => [..pkcs_1, 4] 33 | SHA224 => [..pkcs_1, 14] 34 | SHA256 => [..pkcs_1, 11] 35 | } 36 | } 37 | 38 | pub fn hash(self : HashAlgorithm, input : Iter[Byte]) -> Bytes { 39 | match self { 40 | MD5 => @crypto.md5(Bytes::from_iter(input)) 41 | SHA224 => @crypto.sha224_from_iter(input) 42 | SHA256 => @crypto.sha256_from_iter(input) 43 | } 44 | } 45 | 46 | pub fn pkcs1_v1_5_digest_algorithms(self : HashAlgorithm) -> X690 { 47 | { 48 | tag: Sequence, 49 | class: Universal, 50 | construction: Constructed, 51 | content: { 52 | let buffer = Buffer::new() 53 | buffer.write_bytes( 54 | { 55 | tag: ObjectIdentifier, 56 | construction: Primitive, 57 | class: Universal, 58 | content: self.oid() |> oid_to_bytes, 59 | }.to_bytes(), 60 | ) 61 | buffer.write_bytes( 62 | { tag: Null, construction: Primitive, class: Universal, content: b"" }.to_bytes(), 63 | ) 64 | buffer.to_bytes() 65 | }, 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /crypto/hmac.mbt: -------------------------------------------------------------------------------- 1 | // Copyright 2024 International Digital Economy Academy 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // rfc2104 16 | 17 | pub fn hmac( 18 | content : Iter[Byte], 19 | hash~ : HashAlgorithm, 20 | secret~ : Bytes 21 | ) -> Bytes { 22 | // block length of the hash function 23 | // TODO: it may not be 64 for all hash algorithms 24 | let b = 64 25 | let k = if secret.length() > b { hash.hash(secret.iter()) } else { secret } 26 | let ipad = k.iter() + Bytes::new(b - k.length()).iter() 27 | |> Iter::map(fn(i) { i ^ b'\x36' }) 28 | let out = hash.hash(ipad + content) 29 | let opad = k.iter() + Bytes::new(b - k.length()).iter() 30 | |> Iter::map(fn(i) { i ^ b'\x5C' }) 31 | hash.hash(opad + out.iter()) 32 | } 33 | 34 | test "hmac" { 35 | inspect!( 36 | hmac( 37 | b"I would like to buy 100 units.".iter(), 38 | hash=HashAlgorithm::MD5, 39 | secret=b"666", 40 | ) 41 | |> BigInt::from_octets 42 | |> BigInt::to_hex, 43 | content="76320C555FF8979F16DF9539E53D4B69", 44 | ) 45 | inspect!( 46 | hmac( 47 | b"A quick brown fox jumps over the lazy dog".iter(), 48 | hash=HashAlgorithm::SHA224, 49 | secret=b"12345678901234567890123456789012", 50 | ) 51 | |> BigInt::from_octets 52 | |> BigInt::to_hex, 53 | content="870650B1A3FDB1318C93CCAFAC0F248DC356414E9FEADF5E0F268FCF", 54 | ) 55 | inspect!( 56 | hmac( 57 | b"A quick brown fox jumps over the lazy dog".iter(), 58 | hash=HashAlgorithm::SHA256, 59 | secret=b"I am a secret", 60 | ) 61 | |> BigInt::from_octets 62 | |> BigInt::to_hex, 63 | content="B7F4909B7EEE9F77A34BB0144864222B8AB6AE3CE1500161BAEBED411AA451EA", 64 | ) 65 | } 66 | -------------------------------------------------------------------------------- /crypto/jwt.mbt: -------------------------------------------------------------------------------- 1 | // Copyright 2024 International Digital Economy Academy 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub fn jwt() -> Iter[Char] { 16 | // Get information 17 | let private_key = @variables.get("private_key").unwrap() 18 | let client_id = @variables.get("client_id").unwrap() 19 | let { seconds: now, .. } = @wallClock.now() 20 | let issue_time = now - 60 // 60 seconds in the past as per GitHub suggestion 21 | let expire_time = now + 600 // no more than 10 minutes as per GitHub requirement 22 | // Prepare signature 23 | let [sequence] = private_key 24 | .split("\n") 25 | .drop(1) 26 | .take_while(fn(str) { str.starts_with("----END").not() }) 27 | .flat_map(String::iter) 28 | |> @utils.base64_decode 29 | |> from_iter 30 | |> Iter::collect 31 | let [ 32 | _version, 33 | modulus, 34 | _public_exponent, 35 | _private_exponent, 36 | prime1, 37 | prime2, 38 | exponent1, 39 | exponent2, 40 | coefficient, 41 | ] = sequence.content.iter() 42 | |> from_iter 43 | |> Iter::map( 44 | fn { 45 | { tag: Integer, construction: Primitive, class: Universal, content } => 46 | BigInt::from_octets(content) 47 | _ => panic() 48 | }, 49 | ) 50 | |> Iter::collect 51 | let metadata = ({ "alg": "RS256", "typ": "JWT" } : Json) 52 | |> @json.stringify 53 | |> String::iter 54 | |> @utils.encode_utf8 55 | |> @utils.base64_encode(url_safe=true) 56 | |> Iter::filter(fn(ch) { ch != '=' }) // omit as per rfc7515 section 2 57 | let payload = "{\"iat\":\{issue_time.to_string()}, \"exp\":\{expire_time.to_string()}, \"iss\":\"\{client_id}\"}".iter() 58 | |> @utils.encode_utf8 59 | |> @utils.base64_encode(url_safe=true) 60 | |> Iter::filter(fn(ch) { ch != '=' }) // omit as per rfc7515 section 2 61 | let signature = metadata + ".".iter() + payload 62 | |> @utils.encode_utf8 63 | |> Iter::flat_map(Bytes::iter) 64 | // |> rsassa_pkcs1_v1_5_sign(Pair(~modulus, exponent=private_exponent)) // using other format is faster 65 | |> rsassa_pkcs1_v1_5_sign( 66 | Quintuple( 67 | factor1=prime1, 68 | factor2=prime2, 69 | exponent1~, 70 | exponent2~, 71 | coefficient~, 72 | triplets=[], 73 | length=modulus.to_octets().length() * 8, 74 | ), 75 | ) 76 | let signature = [signature.to_octets()].iter() 77 | |> @utils.base64_encode(url_safe=true) 78 | |> Iter::filter(fn(ch) { ch != '=' }) // omit as per rfc7515 section 2 79 | metadata + ".".iter() + payload + ".".iter() + signature 80 | } 81 | -------------------------------------------------------------------------------- /crypto/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "import": [ 3 | "moonbit/spin/utils", 4 | "moonbitlang/x/crypto", 5 | "moonbit/spin/interface/imports/fermyon/spin/variables", 6 | "moonbit/spin/interface/imports/wasi/clocks/wallClock", 7 | "moonbit/spin/io", 8 | "moonbit/spin/interface/imports/wasi/cli/stdout" 9 | ] 10 | } -------------------------------------------------------------------------------- /ffi/moon.pkg.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /gen/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | pub fn cabi_realloc( 3 | src_offset : Int, 4 | src_size : Int, 5 | _dst_alignment : Int, 6 | dst_size : Int 7 | ) -> Int { 8 | // malloc 9 | if src_offset == 0 && src_size == 0 { 10 | return @ffi.malloc(dst_size) 11 | } 12 | // free 13 | if dst_size <= 0 { 14 | @ffi.free(src_offset) 15 | return 0 16 | } 17 | // realloc 18 | let dst = @ffi.malloc(dst_size) 19 | @ffi.copy(dst, src_offset) 20 | @ffi.free(src_offset) 21 | dst 22 | } 23 | 24 | // let return_area : Int = @ffi.malloc(0) 25 | -------------------------------------------------------------------------------- /gen/interface_exports_wasi_http_incoming_handler_export.mbt: -------------------------------------------------------------------------------- 1 | pub fn wasmExportHandle(p0 : Int, p1 : Int) -> Unit { 2 | server.serve()( 3 | @types.IncomingRequest::IncomingRequest(p0), 4 | @types.ResponseOutparam::ResponseOutparam(p1), 5 | ) 6 | } 7 | 8 | let server : @http.HTTPHandler = panic() 9 | -------------------------------------------------------------------------------- /gen/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "link": { 3 | "wasm": { 4 | "exports": [ 5 | "cabi_realloc:cabi_realloc", 6 | "wasmExportHandle:wasi:http/incoming-handler@0.2.0#handle" 7 | ], 8 | "export-memory-name": "memory", 9 | "heap-start-address": 16 10 | } 11 | }, 12 | "import": [ 13 | { 14 | "path": "moonbit/spin/ffi", 15 | "alias": "ffi" 16 | }, 17 | { 18 | "path": "moonbit/spin/interface/imports/wasi/http/types", 19 | "alias": "types" 20 | }, 21 | "moonbit/spin/http" 22 | ] 23 | } -------------------------------------------------------------------------------- /http/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "import": [ 3 | { 4 | "path": "moonbit/spin/interface/imports/wasi/http/types", 5 | "alias": "types" 6 | }, 7 | "moonbit/spin/interface/imports/wasi/http/outgoingHandler", 8 | "moonbit/spin/interface/imports/wasi/io/streams", 9 | "moonbit/spin/interface/imports/wasi/io/poll", 10 | "moonbit/spin/utils", 11 | "moonbit/spin/io" 12 | ] 13 | } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/keyValue/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropStore(resource : Int) = "fermyon:spin/key-value@2.0.0" "[resource-drop]store" 4 | 5 | fn wasmImportStaticStoreOpen(p0 : Int, p1 : Int, p2 : Int) = "fermyon:spin/key-value@2.0.0" "[static]store.open" 6 | 7 | fn wasmImportMethodStoreGet(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "fermyon:spin/key-value@2.0.0" "[method]store.get" 8 | 9 | fn wasmImportMethodStoreSet( 10 | p0 : Int, 11 | p1 : Int, 12 | p2 : Int, 13 | p3 : Int, 14 | p4 : Int, 15 | p5 : Int 16 | ) = "fermyon:spin/key-value@2.0.0" "[method]store.set" 17 | 18 | fn wasmImportMethodStoreDelete(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "fermyon:spin/key-value@2.0.0" "[method]store.delete" 19 | 20 | fn wasmImportMethodStoreExists(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "fermyon:spin/key-value@2.0.0" "[method]store.exists" 21 | 22 | fn wasmImportMethodStoreGetKeys(p0 : Int, p1 : Int) = "fermyon:spin/key-value@2.0.0" "[method]store.get-keys" 23 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/keyValue/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/llm/README.md: -------------------------------------------------------------------------------- 1 | A WASI interface dedicated to performing inferencing for Large Language Models. -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/llm/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportInfer( 3 | p0 : Int, 4 | p1 : Int, 5 | p2 : Int, 6 | p3 : Int, 7 | p4 : Int, 8 | p5 : Int, 9 | p6 : Float, 10 | p7 : Int, 11 | p8 : Float, 12 | p9 : Int, 13 | p10 : Float, 14 | p11 : Int 15 | ) = "fermyon:spin/llm@2.0.0" "infer" 16 | 17 | fn wasmImportGenerateEmbeddings( 18 | p0 : Int, 19 | p1 : Int, 20 | p2 : Int, 21 | p3 : Int, 22 | p4 : Int 23 | ) = "fermyon:spin/llm@2.0.0" "generate-embeddings" 24 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/llm/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/mqtt/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropConnection(resource : Int) = "fermyon:spin/mqtt@2.0.0" "[resource-drop]connection" 4 | 5 | fn wasmImportStaticConnectionOpen( 6 | p0 : Int, 7 | p1 : Int, 8 | p2 : Int, 9 | p3 : Int, 10 | p4 : Int, 11 | p5 : Int, 12 | p6 : Int64, 13 | p7 : Int 14 | ) = "fermyon:spin/mqtt@2.0.0" "[static]connection.open" 15 | 16 | fn wasmImportMethodConnectionPublish( 17 | p0 : Int, 18 | p1 : Int, 19 | p2 : Int, 20 | p3 : Int, 21 | p4 : Int, 22 | p5 : Int, 23 | p6 : Int 24 | ) = "fermyon:spin/mqtt@2.0.0" "[method]connection.publish" 25 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/mqtt/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/mqtt/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Errors related to interacting with Mqtt 3 | pub(all) type! Error_ { 4 | InvalidAddress 5 | TooManyConnections 6 | ConnectionFailed(String) 7 | Other(String) 8 | } derive(Show, Eq) 9 | 10 | /// QoS for publishing Mqtt messages 11 | pub(all) enum Qos { 12 | AT_MOST_ONCE 13 | AT_LEAST_ONCE 14 | EXACTLY_ONCE 15 | } derive(Show, Eq) 16 | 17 | pub fn ordinal(self : Qos) -> Int { 18 | match self { 19 | AT_MOST_ONCE => 0 20 | AT_LEAST_ONCE => 1 21 | EXACTLY_ONCE => 2 22 | } 23 | } 24 | 25 | pub fn Qos::from(self : Int) -> Qos { 26 | match self { 27 | 0 => AT_MOST_ONCE 28 | 1 => AT_LEAST_ONCE 29 | 2 => EXACTLY_ONCE 30 | _ => panic() 31 | } 32 | } 33 | 34 | pub(all) type Connection Int derive(Show, Eq) 35 | 36 | /// Drops a resource handle. 37 | pub fn Connection::drop(self : Connection) -> Unit { 38 | let Connection(resource) = self 39 | wasmImportResourceDropConnection(resource) 40 | } 41 | 42 | /// Open a connection to the Mqtt instance at `address`. 43 | pub fn Connection::open( 44 | address : String, 45 | username : String, 46 | password : String, 47 | keep_alive_interval_in_secs : UInt64 48 | ) -> Result[Connection, Error_] { 49 | let return_area = @ffi.malloc(16) 50 | wasmImportStaticConnectionOpen( 51 | @ffi.str2ptr(address), 52 | address.iter().count(), 53 | @ffi.str2ptr(username), 54 | username.iter().count(), 55 | @ffi.str2ptr(password), 56 | password.iter().count(), 57 | keep_alive_interval_in_secs.to_int64(), 58 | return_area, 59 | ) 60 | let lifted11 = match @ffi.load8_u(return_area + 0) { 61 | 0 => Result::Ok(Connection::Connection(@ffi.load32(return_area + 4))) 62 | 1 => { 63 | let lifted = match @ffi.load8_u(return_area + 4) { 64 | 0 => Error_::InvalidAddress 65 | 1 => Error_::TooManyConnections 66 | 2 => { 67 | let result = @ffi.ptr2str(@ffi.load32(return_area + 8)) 68 | Error_::ConnectionFailed(result) 69 | } 70 | 3 => { 71 | let result10 = @ffi.ptr2str(@ffi.load32(return_area + 8)) 72 | Error_::Other(result10) 73 | } 74 | _ => panic() 75 | } 76 | Result::Err(lifted) 77 | } 78 | _ => panic() 79 | } 80 | ignore(address) 81 | ignore(username) 82 | ignore(password) 83 | @ffi.free(return_area) 84 | return lifted11 85 | } 86 | 87 | /// Publish an Mqtt message to the specified `topic`. 88 | pub fn Connection::publish( 89 | self : Connection, 90 | topic : String, 91 | payload : Bytes, 92 | qos : Qos 93 | ) -> Result[Unit, Error_] { 94 | let Connection(handle) = self 95 | let return_area = @ffi.malloc(16) 96 | wasmImportMethodConnectionPublish( 97 | handle, 98 | @ffi.str2ptr(topic), 99 | topic.iter().count(), 100 | @ffi.bytes2ptr(payload), 101 | payload.length(), 102 | qos.ordinal(), 103 | return_area, 104 | ) 105 | let lifted11 = match @ffi.load8_u(return_area + 0) { 106 | 0 => Result::Ok(()) 107 | 1 => { 108 | let lifted = match @ffi.load8_u(return_area + 4) { 109 | 0 => Error_::InvalidAddress 110 | 1 => Error_::TooManyConnections 111 | 2 => { 112 | let result = @ffi.ptr2str(@ffi.load32(return_area + 8)) 113 | Error_::ConnectionFailed(result) 114 | } 115 | 3 => { 116 | let result10 = @ffi.ptr2str(@ffi.load32(return_area + 8)) 117 | Error_::Other(result10) 118 | } 119 | _ => panic() 120 | } 121 | Result::Err(lifted) 122 | } 123 | _ => panic() 124 | } 125 | ignore(topic) 126 | ignore(payload) 127 | @ffi.free(return_area) 128 | return lifted11 129 | } 130 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/mysql/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropConnection(resource : Int) = "fermyon:spin/mysql@2.0.0" "[resource-drop]connection" 4 | 5 | fn wasmImportStaticConnectionOpen(p0 : Int, p1 : Int, p2 : Int) = "fermyon:spin/mysql@2.0.0" "[static]connection.open" 6 | 7 | fn wasmImportMethodConnectionQuery( 8 | p0 : Int, 9 | p1 : Int, 10 | p2 : Int, 11 | p3 : Int, 12 | p4 : Int, 13 | p5 : Int 14 | ) = "fermyon:spin/mysql@2.0.0" "[method]connection.query" 15 | 16 | fn wasmImportMethodConnectionExecute( 17 | p0 : Int, 18 | p1 : Int, 19 | p2 : Int, 20 | p3 : Int, 21 | p4 : Int, 22 | p5 : Int 23 | ) = "fermyon:spin/mysql@2.0.0" "[method]connection.execute" 24 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/mysql/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/fermyon/spin/rdbmsTypes", "alias" : "rdbmsTypes" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/postgres/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropConnection(resource : Int) = "fermyon:spin/postgres@2.0.0" "[resource-drop]connection" 4 | 5 | fn wasmImportStaticConnectionOpen(p0 : Int, p1 : Int, p2 : Int) = "fermyon:spin/postgres@2.0.0" "[static]connection.open" 6 | 7 | fn wasmImportMethodConnectionQuery( 8 | p0 : Int, 9 | p1 : Int, 10 | p2 : Int, 11 | p3 : Int, 12 | p4 : Int, 13 | p5 : Int 14 | ) = "fermyon:spin/postgres@2.0.0" "[method]connection.query" 15 | 16 | fn wasmImportMethodConnectionExecute( 17 | p0 : Int, 18 | p1 : Int, 19 | p2 : Int, 20 | p3 : Int, 21 | p4 : Int, 22 | p5 : Int 23 | ) = "fermyon:spin/postgres@2.0.0" "[method]connection.execute" 24 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/postgres/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/fermyon/spin/rdbmsTypes", "alias" : "rdbmsTypes" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/rdbmsTypes/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/rdbmsTypes/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/rdbmsTypes/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Errors related to interacting with a database. 3 | pub(all) type! Error_ { 4 | ConnectionFailed(String) 5 | BadParameter(String) 6 | QueryFailed(String) 7 | ValueConversionFailed(String) 8 | Other(String) 9 | } derive(Show, Eq) 10 | 11 | /// Data types for a database column 12 | pub(all) enum DbDataType { 13 | BOOLEAN 14 | INT8 15 | INT16 16 | INT32 17 | INT64 18 | UINT8 19 | UINT16 20 | UINT32 21 | UINT64 22 | FLOATING32 23 | FLOATING64 24 | STR 25 | BINARY 26 | OTHER 27 | } derive(Show, Eq) 28 | 29 | pub fn ordinal(self : DbDataType) -> Int { 30 | match self { 31 | BOOLEAN => 0 32 | INT8 => 1 33 | INT16 => 2 34 | INT32 => 3 35 | INT64 => 4 36 | UINT8 => 5 37 | UINT16 => 6 38 | UINT32 => 7 39 | UINT64 => 8 40 | FLOATING32 => 9 41 | FLOATING64 => 10 42 | STR => 11 43 | BINARY => 12 44 | OTHER => 13 45 | } 46 | } 47 | 48 | pub fn DbDataType::from(self : Int) -> DbDataType { 49 | match self { 50 | 0 => BOOLEAN 51 | 1 => INT8 52 | 2 => INT16 53 | 3 => INT32 54 | 4 => INT64 55 | 5 => UINT8 56 | 6 => UINT16 57 | 7 => UINT32 58 | 8 => UINT64 59 | 9 => FLOATING32 60 | 10 => FLOATING64 61 | 11 => STR 62 | 12 => BINARY 63 | 13 => OTHER 64 | _ => panic() 65 | } 66 | } 67 | 68 | /// Database values 69 | pub(all) enum DbValue { 70 | Boolean(Bool) 71 | Int8(Int) 72 | Int16(Int) 73 | Int32(Int) 74 | Int64(Int64) 75 | Uint8(Byte) 76 | Uint16(UInt) 77 | Uint32(UInt) 78 | Uint64(UInt64) 79 | Floating32(Double) 80 | Floating64(Double) 81 | Str(String) 82 | Binary(Bytes) 83 | DbNull 84 | Unsupported 85 | } derive(Show, Eq) 86 | 87 | /// Values used in parameterized queries 88 | pub(all) enum ParameterValue { 89 | Boolean(Bool) 90 | Int8(Int) 91 | Int16(Int) 92 | Int32(Int) 93 | Int64(Int64) 94 | Uint8(Byte) 95 | Uint16(UInt) 96 | Uint32(UInt) 97 | Uint64(UInt64) 98 | Floating32(Double) 99 | Floating64(Double) 100 | Str(String) 101 | Binary(Bytes) 102 | DbNull 103 | } derive(Show, Eq) 104 | 105 | /// A database column 106 | pub(all) struct Column { 107 | name : String 108 | data_type : DbDataType 109 | } derive(Show, Eq) 110 | 111 | /// A set of database rows 112 | pub(all) struct RowSet { 113 | columns : Array[Column] 114 | rows : Array[Array[DbValue]] 115 | } derive(Show, Eq) 116 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/redis/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropConnection(resource : Int) = "fermyon:spin/redis@2.0.0" "[resource-drop]connection" 4 | 5 | fn wasmImportStaticConnectionOpen(p0 : Int, p1 : Int, p2 : Int) = "fermyon:spin/redis@2.0.0" "[static]connection.open" 6 | 7 | fn wasmImportMethodConnectionPublish( 8 | p0 : Int, 9 | p1 : Int, 10 | p2 : Int, 11 | p3 : Int, 12 | p4 : Int, 13 | p5 : Int 14 | ) = "fermyon:spin/redis@2.0.0" "[method]connection.publish" 15 | 16 | fn wasmImportMethodConnectionGet(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "fermyon:spin/redis@2.0.0" "[method]connection.get" 17 | 18 | fn wasmImportMethodConnectionSet( 19 | p0 : Int, 20 | p1 : Int, 21 | p2 : Int, 22 | p3 : Int, 23 | p4 : Int, 24 | p5 : Int 25 | ) = "fermyon:spin/redis@2.0.0" "[method]connection.set" 26 | 27 | fn wasmImportMethodConnectionIncr(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "fermyon:spin/redis@2.0.0" "[method]connection.incr" 28 | 29 | fn wasmImportMethodConnectionDel(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "fermyon:spin/redis@2.0.0" "[method]connection.del" 30 | 31 | fn wasmImportMethodConnectionSadd( 32 | p0 : Int, 33 | p1 : Int, 34 | p2 : Int, 35 | p3 : Int, 36 | p4 : Int, 37 | p5 : Int 38 | ) = "fermyon:spin/redis@2.0.0" "[method]connection.sadd" 39 | 40 | fn wasmImportMethodConnectionSmembers(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "fermyon:spin/redis@2.0.0" "[method]connection.smembers" 41 | 42 | fn wasmImportMethodConnectionSrem( 43 | p0 : Int, 44 | p1 : Int, 45 | p2 : Int, 46 | p3 : Int, 47 | p4 : Int, 48 | p5 : Int 49 | ) = "fermyon:spin/redis@2.0.0" "[method]connection.srem" 50 | 51 | fn wasmImportMethodConnectionExecute( 52 | p0 : Int, 53 | p1 : Int, 54 | p2 : Int, 55 | p3 : Int, 56 | p4 : Int, 57 | p5 : Int 58 | ) = "fermyon:spin/redis@2.0.0" "[method]connection.execute" 59 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/redis/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/sqlite/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropConnection(resource : Int) = "fermyon:spin/sqlite@2.0.0" "[resource-drop]connection" 4 | 5 | fn wasmImportStaticConnectionOpen(p0 : Int, p1 : Int, p2 : Int) = "fermyon:spin/sqlite@2.0.0" "[static]connection.open" 6 | 7 | fn wasmImportMethodConnectionExecute( 8 | p0 : Int, 9 | p1 : Int, 10 | p2 : Int, 11 | p3 : Int, 12 | p4 : Int, 13 | p5 : Int 14 | ) = "fermyon:spin/sqlite@2.0.0" "[method]connection.execute" 15 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/sqlite/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/variables/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGet(p0 : Int, p1 : Int, p2 : Int) = "fermyon:spin/variables@2.0.0" "get" 3 | -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/variables/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/fermyon/spin/variables/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// The set of errors which may be raised by functions in this interface. 3 | pub(all) type! Error_ { 4 | InvalidName(String) 5 | Undefined(String) 6 | Provider(String) 7 | Other(String) 8 | } derive(Show, Eq) 9 | 10 | /// Get an application variable value for the current component. 11 | /// 12 | /// The name must match one defined in in the component manifest. 13 | pub fn get(name : String) -> Result[String, Error_] { 14 | let return_area = @ffi.malloc(16) 15 | wasmImportGet(@ffi.str2ptr(name), name.iter().count(), return_area) 16 | let lifted14 = match @ffi.load8_u(return_area + 0) { 17 | 0 => { 18 | let result = @ffi.ptr2str(@ffi.load32(return_area + 4)) 19 | Result::Ok(result) 20 | } 21 | 1 => { 22 | let lifted = match @ffi.load8_u(return_area + 4) { 23 | 0 => { 24 | let result4 = @ffi.ptr2str(@ffi.load32(return_area + 8)) 25 | Error_::InvalidName(result4) 26 | } 27 | 1 => { 28 | let result7 = @ffi.ptr2str(@ffi.load32(return_area + 8)) 29 | Error_::Undefined(result7) 30 | } 31 | 2 => { 32 | let result10 = @ffi.ptr2str(@ffi.load32(return_area + 8)) 33 | Error_::Provider(result10) 34 | } 35 | 3 => { 36 | let result13 = @ffi.ptr2str(@ffi.load32(return_area + 8)) 37 | Error_::Other(result13) 38 | } 39 | _ => panic() 40 | } 41 | Result::Err(lifted) 42 | } 43 | _ => panic() 44 | } 45 | ignore(name) 46 | @ffi.free(return_area) 47 | return lifted14 48 | } 49 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/environment/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetEnvironment(p0 : Int) = "wasi:cli/environment@0.2.0" "get-environment" 3 | 4 | fn wasmImportGetArguments(p0 : Int) = "wasi:cli/environment@0.2.0" "get-arguments" 5 | 6 | fn wasmImportInitialCwd(p0 : Int) = "wasi:cli/environment@0.2.0" "initial-cwd" 7 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/environment/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/environment/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Get the POSIX-style environment variables. 3 | /// 4 | /// Each environment variable is provided as a pair of string variable names 5 | /// and string value. 6 | /// 7 | /// Morally, these are a value import, but until value imports are available 8 | /// in the component model, this import function should return the same 9 | /// values each time it is called. 10 | pub fn get_environment() -> Array[(String, String)] { 11 | let return_area = @ffi.malloc(8) 12 | wasmImportGetEnvironment(return_area) 13 | let array : Array[(String, String)] = [] 14 | for index = 0; index < @ffi.load32(return_area + 4); index = index + 1 { 15 | let base = @ffi.load32(return_area + 0) + index * 16 16 | let result = @ffi.ptr2str(@ffi.load32(base + 0)) 17 | let result0 = @ffi.ptr2str(@ffi.load32(base + 8)) 18 | array.push((result, result0)) 19 | } 20 | @ffi.free(@ffi.load32(return_area + 0)) 21 | @ffi.free(return_area) 22 | return array 23 | } 24 | 25 | /// Get the POSIX-style arguments to the program. 26 | pub fn get_arguments() -> Array[String] { 27 | let return_area = @ffi.malloc(8) 28 | wasmImportGetArguments(return_area) 29 | let array : Array[String] = [] 30 | for index = 0; index < @ffi.load32(return_area + 4); index = index + 1 { 31 | let base = @ffi.load32(return_area + 0) + index * 8 32 | let result = @ffi.ptr2str(@ffi.load32(base + 0)) 33 | array.push(result) 34 | } 35 | @ffi.free(@ffi.load32(return_area + 0)) 36 | @ffi.free(return_area) 37 | return array 38 | } 39 | 40 | /// Return a path that programs should use as their initial current working 41 | /// directory, interpreting `.` as shorthand for this. 42 | pub fn initial_cwd() -> String? { 43 | let return_area = @ffi.malloc(12) 44 | wasmImportInitialCwd(return_area) 45 | let lifted : String? = match @ffi.load8_u(return_area + 0) { 46 | 0 => Option::None 47 | 1 => { 48 | let result = @ffi.ptr2str(@ffi.load32(return_area + 4)) 49 | Option::Some(result) 50 | } 51 | _ => panic() 52 | } 53 | @ffi.free(return_area) 54 | return lifted 55 | } 56 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/exit/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportExit(p0 : Int) = "wasi:cli/exit@0.2.0" "exit" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/exit/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/exit/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Exit the current instance and any linked instances. 3 | pub fn exit(status : Result[Unit, Unit]) -> Unit { 4 | let lowered = match status { 5 | Ok(payload) => 0 6 | Err(payload2) => 1 7 | _ => panic() 8 | } 9 | wasmImportExit(lowered) 10 | } 11 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stderr/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetStderr() -> Int = "wasi:cli/stderr@0.2.0" "get-stderr" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stderr/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/streams", "alias" : "streams" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stderr/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | pub fn get_stderr() -> @streams.OutputStream { 4 | let result : Int = wasmImportGetStderr() 5 | return @streams.OutputStream::OutputStream(result) 6 | } 7 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stdin/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetStdin() -> Int = "wasi:cli/stdin@0.2.0" "get-stdin" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stdin/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/streams", "alias" : "streams" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stdin/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | pub fn get_stdin() -> @streams.InputStream { 4 | let result : Int = wasmImportGetStdin() 5 | return @streams.InputStream::InputStream(result) 6 | } 7 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stdout/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetStdout() -> Int = "wasi:cli/stdout@0.2.0" "get-stdout" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stdout/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/streams", "alias" : "streams" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/stdout/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | pub fn get_stdout() -> @streams.OutputStream { 4 | let result : Int = wasmImportGetStdout() 5 | return @streams.OutputStream::OutputStream(result) 6 | } 7 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalInput/README.md: -------------------------------------------------------------------------------- 1 | Terminal input. 2 | 3 | In the future, this may include functions for disabling echoing, 4 | disabling input buffering so that keyboard events are sent through 5 | immediately, querying supported features, and so on. -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalInput/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropTerminalInput(resource : Int) = "wasi:cli/terminal-input@0.2.0" "[resource-drop]terminal-input" 4 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalInput/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalInput/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// The input side of a terminal. 3 | pub(all) type TerminalInput Int derive(Show, Eq) 4 | 5 | /// Drops a resource handle. 6 | pub fn TerminalInput::drop(self : TerminalInput) -> Unit { 7 | let TerminalInput(resource) = self 8 | wasmImportResourceDropTerminalInput(resource) 9 | } 10 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalOutput/README.md: -------------------------------------------------------------------------------- 1 | Terminal output. 2 | 3 | In the future, this may include functions for querying the terminal 4 | size, being notified of terminal size changes, querying supported 5 | features, and so on. -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalOutput/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropTerminalOutput(resource : Int) = "wasi:cli/terminal-output@0.2.0" "[resource-drop]terminal-output" 4 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalOutput/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalOutput/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// The output side of a terminal. 3 | pub(all) type TerminalOutput Int derive(Show, Eq) 4 | 5 | /// Drops a resource handle. 6 | pub fn TerminalOutput::drop(self : TerminalOutput) -> Unit { 7 | let TerminalOutput(resource) = self 8 | wasmImportResourceDropTerminalOutput(resource) 9 | } 10 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStderr/README.md: -------------------------------------------------------------------------------- 1 | An interface providing an optional `terminal-output` for stderr as a 2 | link-time authority. -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStderr/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetTerminalStderr(p0 : Int) = "wasi:cli/terminal-stderr@0.2.0" "get-terminal-stderr" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStderr/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/cli/terminalOutput", "alias" : "terminalOutput" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStderr/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// If stderr is connected to a terminal, return a `terminal-output` handle 3 | /// allowing further interaction with it. 4 | pub fn get_terminal_stderr() -> @terminalOutput.TerminalOutput? { 5 | let return_area = @ffi.malloc(8) 6 | wasmImportGetTerminalStderr(return_area) 7 | let lifted : @terminalOutput.TerminalOutput? = match 8 | @ffi.load8_u(return_area + 0) { 9 | 0 => Option::None 10 | 1 => 11 | Option::Some( 12 | @terminalOutput.TerminalOutput::TerminalOutput( 13 | @ffi.load32(return_area + 4), 14 | ), 15 | ) 16 | _ => panic() 17 | } 18 | @ffi.free(return_area) 19 | return lifted 20 | } 21 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdin/README.md: -------------------------------------------------------------------------------- 1 | An interface providing an optional `terminal-input` for stdin as a 2 | link-time authority. -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdin/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetTerminalStdin(p0 : Int) = "wasi:cli/terminal-stdin@0.2.0" "get-terminal-stdin" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdin/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/cli/terminalInput", "alias" : "terminalInput" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdin/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// If stdin is connected to a terminal, return a `terminal-input` handle 3 | /// allowing further interaction with it. 4 | pub fn get_terminal_stdin() -> @terminalInput.TerminalInput? { 5 | let return_area = @ffi.malloc(8) 6 | wasmImportGetTerminalStdin(return_area) 7 | let lifted : @terminalInput.TerminalInput? = match 8 | @ffi.load8_u(return_area + 0) { 9 | 0 => Option::None 10 | 1 => 11 | Option::Some( 12 | @terminalInput.TerminalInput::TerminalInput( 13 | @ffi.load32(return_area + 4), 14 | ), 15 | ) 16 | _ => panic() 17 | } 18 | @ffi.free(return_area) 19 | return lifted 20 | } 21 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdout/README.md: -------------------------------------------------------------------------------- 1 | An interface providing an optional `terminal-output` for stdout as a 2 | link-time authority. -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdout/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetTerminalStdout(p0 : Int) = "wasi:cli/terminal-stdout@0.2.0" "get-terminal-stdout" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdout/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/cli/terminalOutput", "alias" : "terminalOutput" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/cli/terminalStdout/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// If stdout is connected to a terminal, return a `terminal-output` handle 3 | /// allowing further interaction with it. 4 | pub fn get_terminal_stdout() -> @terminalOutput.TerminalOutput? { 5 | let return_area = @ffi.malloc(8) 6 | wasmImportGetTerminalStdout(return_area) 7 | let lifted : @terminalOutput.TerminalOutput? = match 8 | @ffi.load8_u(return_area + 0) { 9 | 0 => Option::None 10 | 1 => 11 | Option::Some( 12 | @terminalOutput.TerminalOutput::TerminalOutput( 13 | @ffi.load32(return_area + 4), 14 | ), 15 | ) 16 | _ => panic() 17 | } 18 | @ffi.free(return_area) 19 | return lifted 20 | } 21 | -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/monotonicClock/README.md: -------------------------------------------------------------------------------- 1 | WASI Monotonic Clock is a clock API intended to let users measure elapsed 2 | time. 3 | 4 | It is intended to be portable at least between Unix-family platforms and 5 | Windows. 6 | 7 | A monotonic clock is a clock which has an unspecified initial value, and 8 | successive reads of the clock will produce non-decreasing values. 9 | 10 | It is intended for measuring elapsed time. -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/monotonicClock/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportNow() -> Int64 = "wasi:clocks/monotonic-clock@0.2.0" "now" 3 | 4 | fn wasmImportResolution() -> Int64 = "wasi:clocks/monotonic-clock@0.2.0" "resolution" 5 | 6 | fn wasmImportSubscribeInstant(p0 : Int64) -> Int = "wasi:clocks/monotonic-clock@0.2.0" "subscribe-instant" 7 | 8 | fn wasmImportSubscribeDuration(p0 : Int64) -> Int = "wasi:clocks/monotonic-clock@0.2.0" "subscribe-duration" 9 | -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/monotonicClock/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/poll", "alias" : "poll" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/monotonicClock/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Read the current value of the clock. 3 | /// 4 | /// The clock is monotonic, therefore calling this function repeatedly will 5 | /// produce a sequence of non-decreasing values. 6 | pub fn now() -> UInt64 { 7 | let result : Int64 = wasmImportNow() 8 | return result.to_uint64() 9 | } 10 | 11 | /// Query the resolution of the clock. Returns the duration of time 12 | /// corresponding to a clock tick. 13 | pub fn resolution() -> UInt64 { 14 | let result : Int64 = wasmImportResolution() 15 | return result.to_uint64() 16 | } 17 | 18 | /// Create a `pollable` which will resolve once the specified instant 19 | /// occured. 20 | pub fn subscribe_instant(when : UInt64) -> @poll.Pollable { 21 | let result : Int = wasmImportSubscribeInstant(when.to_int64()) 22 | return @poll.Pollable::Pollable(result) 23 | } 24 | 25 | /// Create a `pollable` which will resolve once the given duration has 26 | /// elapsed, starting at the time at which this function was called. 27 | /// occured. 28 | pub fn subscribe_duration(when : UInt64) -> @poll.Pollable { 29 | let result : Int = wasmImportSubscribeDuration(when.to_int64()) 30 | return @poll.Pollable::Pollable(result) 31 | } 32 | -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/wallClock/README.md: -------------------------------------------------------------------------------- 1 | WASI Wall Clock is a clock API intended to let users query the current 2 | time. The name "wall" makes an analogy to a "clock on the wall", which 3 | is not necessarily monotonic as it may be reset. 4 | 5 | It is intended to be portable at least between Unix-family platforms and 6 | Windows. 7 | 8 | A wall clock is a clock which measures the date and time according to 9 | some external reference. 10 | 11 | External references may be reset, so this clock is not necessarily 12 | monotonic, making it unsuitable for measuring elapsed time. 13 | 14 | It is intended for reporting the current date and time for humans. -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/wallClock/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportNow(p0 : Int) = "wasi:clocks/wall-clock@0.2.0" "now" 3 | 4 | fn wasmImportResolution(p0 : Int) = "wasi:clocks/wall-clock@0.2.0" "resolution" 5 | -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/wallClock/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/clocks/wallClock/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// A time and date in seconds plus nanoseconds. 3 | pub(all) struct Datetime { 4 | seconds : UInt64 5 | nanoseconds : UInt 6 | } derive(Show, Eq) 7 | 8 | /// Read the current value of the clock. 9 | /// 10 | /// This clock is not monotonic, therefore calling this function repeatedly 11 | /// will not necessarily produce a sequence of non-decreasing values. 12 | /// 13 | /// The returned timestamps represent the number of seconds since 14 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], 15 | /// also known as [Unix Time]. 16 | /// 17 | /// The nanoseconds field of the output is always less than 1000000000. 18 | /// 19 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 20 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time 21 | pub fn now() -> Datetime { 22 | let return_area = @ffi.malloc(16) 23 | wasmImportNow(return_area) 24 | @ffi.free(return_area) 25 | return Datetime::{ 26 | seconds: @ffi.load64(return_area + 0).to_uint64(), 27 | nanoseconds: @ffi.load32(return_area + 8).reinterpret_as_uint(), 28 | } 29 | } 30 | 31 | /// Query the resolution of the clock. 32 | /// 33 | /// The nanoseconds field of the output is always less than 1000000000. 34 | pub fn resolution() -> Datetime { 35 | let return_area = @ffi.malloc(16) 36 | wasmImportResolution(return_area) 37 | @ffi.free(return_area) 38 | return Datetime::{ 39 | seconds: @ffi.load64(return_area + 0).to_uint64(), 40 | nanoseconds: @ffi.load32(return_area + 8).reinterpret_as_uint(), 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /interface/imports/wasi/filesystem/preopens/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetDirectories(p0 : Int) = "wasi:filesystem/preopens@0.2.0" "get-directories" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/filesystem/preopens/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/filesystem/types", "alias" : "types" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/filesystem/preopens/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Return the set of preopened directories, and their path. 3 | pub fn get_directories() -> Array[(@types.Descriptor, String)] { 4 | let return_area = @ffi.malloc(8) 5 | wasmImportGetDirectories(return_area) 6 | let array : Array[(@types.Descriptor, String)] = [] 7 | for index = 0; index < @ffi.load32(return_area + 4); index = index + 1 { 8 | let base = @ffi.load32(return_area + 0) + index * 12 9 | let result = @ffi.ptr2str(@ffi.load32(base + 4)) 10 | array.push((@types.Descriptor::Descriptor(@ffi.load32(base + 0)), result)) 11 | } 12 | @ffi.free(@ffi.load32(return_area + 0)) 13 | @ffi.free(return_area) 14 | return array 15 | } 16 | -------------------------------------------------------------------------------- /interface/imports/wasi/filesystem/types/README.md: -------------------------------------------------------------------------------- 1 | WASI filesystem is a filesystem API primarily intended to let users run WASI 2 | programs that access their files on their existing filesystems, without 3 | significant overhead. 4 | 5 | It is intended to be roughly portable between Unix-family platforms and 6 | Windows, though it does not hide many of the major differences. 7 | 8 | Paths are passed as interface-type `string`s, meaning they must consist of 9 | a sequence of Unicode Scalar Values (USVs). Some filesystems may contain 10 | paths which are not accessible by this API. 11 | 12 | The directory separator in WASI is always the forward-slash (`/`). 13 | 14 | All paths in WASI are relative paths, and are interpreted relative to a 15 | `descriptor` referring to a base directory. If a `path` argument to any WASI 16 | function starts with `/`, or if any step of resolving a `path`, including 17 | `..` and symbolic link steps, reaches a directory outside of the base 18 | directory, or reaches a symlink to an absolute or rooted path in the 19 | underlying filesystem, the function fails with `error-code::not-permitted`. 20 | 21 | For more information about WASI path resolution and sandboxing, see 22 | [WASI filesystem path resolution]. 23 | 24 | [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md -------------------------------------------------------------------------------- /interface/imports/wasi/filesystem/types/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/clocks/wallClock", "alias" : "wallClock" }, { "path" : "moonbit/spin/interface/imports/wasi/io/error", "alias" : "error" }, { "path" : "moonbit/spin/interface/imports/wasi/io/streams", "alias" : "streams" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/http/outgoingHandler/README.md: -------------------------------------------------------------------------------- 1 | This interface defines a handler of outgoing HTTP Requests. It should be 2 | imported by components which wish to make HTTP Requests. -------------------------------------------------------------------------------- /interface/imports/wasi/http/outgoingHandler/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportHandle(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "wasi:http/outgoing-handler@0.2.0" "handle" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/http/outgoingHandler/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/http/types", "alias" : "types" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/http/types/README.md: -------------------------------------------------------------------------------- 1 | This interface defines all of the types and methods for implementing 2 | HTTP Requests and Responses, both incoming and outgoing, as well as 3 | their headers, trailers, and bodies. -------------------------------------------------------------------------------- /interface/imports/wasi/http/types/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/error", "alias" : "error" }, { "path" : "moonbit/spin/interface/imports/wasi/io/poll", "alias" : "poll" }, { "path" : "moonbit/spin/interface/imports/wasi/io/streams", "alias" : "streams" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/io/error/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropError_(resource : Int) = "wasi:io/error@0.2.0" "[resource-drop]error" 4 | 5 | fn wasmImportMethodErrorToDebugString(p0 : Int, p1 : Int) = "wasi:io/error@0.2.0" "[method]error.to-debug-string" 6 | -------------------------------------------------------------------------------- /interface/imports/wasi/io/error/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/io/error/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// A resource which represents some error information. 3 | /// 4 | /// The only method provided by this resource is `to-debug-string`, 5 | /// which provides some human-readable information about the error. 6 | /// 7 | /// In the `wasi:io` package, this resource is returned through the 8 | /// `wasi:io/streams/stream-error` type. 9 | /// 10 | /// To provide more specific error information, other interfaces may 11 | /// provide functions to further "downcast" this error into more specific 12 | /// error information. For example, `error`s returned in streams derived 13 | /// from filesystem types to be described using the filesystem's own 14 | /// error-code type, using the function 15 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter 16 | /// `borrow` and returns 17 | /// `option`. 18 | /// 19 | /// The set of functions which can "downcast" an `error` into a more 20 | /// concrete type is open. 21 | pub(all) type! Error_ Int derive(Show, Eq) 22 | 23 | /// Drops a resource handle. 24 | pub fn Error_::drop(self : Error_) -> Unit { 25 | let Error_(resource) = self 26 | wasmImportResourceDropError_(resource) 27 | } 28 | 29 | /// Returns a string that is suitable to assist humans in debugging 30 | /// this error. 31 | /// 32 | /// WARNING: The returned string should not be consumed mechanically! 33 | /// It may change across platforms, hosts, or other implementation 34 | /// details. Parsing this string is a major platform-compatibility 35 | /// hazard. 36 | pub fn Error_::to_debug_string(self : Error_) -> String { 37 | let Error_(handle) = self 38 | let return_area = @ffi.malloc(8) 39 | wasmImportMethodErrorToDebugString(handle, return_area) 40 | let result = @ffi.ptr2str(@ffi.load32(return_area + 0)) 41 | @ffi.free(return_area) 42 | return result 43 | } 44 | -------------------------------------------------------------------------------- /interface/imports/wasi/io/poll/README.md: -------------------------------------------------------------------------------- 1 | A poll API intended to let users wait for I/O events on multiple handles 2 | at once. -------------------------------------------------------------------------------- /interface/imports/wasi/io/poll/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropPollable(resource : Int) = "wasi:io/poll@0.2.0" "[resource-drop]pollable" 4 | 5 | fn wasmImportMethodPollableReady(p0 : Int) -> Int = "wasi:io/poll@0.2.0" "[method]pollable.ready" 6 | 7 | fn wasmImportMethodPollableBlock(p0 : Int) = "wasi:io/poll@0.2.0" "[method]pollable.block" 8 | 9 | fn wasmImportPoll(p0 : Int, p1 : Int, p2 : Int) = "wasi:io/poll@0.2.0" "poll" 10 | -------------------------------------------------------------------------------- /interface/imports/wasi/io/poll/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/io/poll/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// `pollable` represents a single I/O event which may be ready, or not. 3 | pub(all) type Pollable Int derive(Show, Eq) 4 | 5 | /// Drops a resource handle. 6 | pub fn Pollable::drop(self : Pollable) -> Unit { 7 | let Pollable(resource) = self 8 | wasmImportResourceDropPollable(resource) 9 | } 10 | 11 | /// Return the readiness of a pollable. This function never blocks. 12 | /// 13 | /// Returns `true` when the pollable is ready, and `false` otherwise. 14 | pub fn Pollable::ready(self : Pollable) -> Bool { 15 | let Pollable(handle) = self 16 | let result : Int = wasmImportMethodPollableReady(handle) 17 | return result != 0 18 | } 19 | 20 | /// `block` returns immediately if the pollable is ready, and otherwise 21 | /// blocks until ready. 22 | /// 23 | /// This function is equivalent to calling `poll.poll` on a list 24 | /// containing only this pollable. 25 | pub fn Pollable::block(self : Pollable) -> Unit { 26 | let Pollable(handle) = self 27 | wasmImportMethodPollableBlock(handle) 28 | } 29 | 30 | /// Poll for completion on a set of pollables. 31 | /// 32 | /// This function takes a list of pollables, which identify I/O sources of 33 | /// interest, and waits until one or more of the events is ready for I/O. 34 | /// 35 | /// The result `list` contains one or more indices of handles in the 36 | /// argument list that is ready for I/O. 37 | /// 38 | /// If the list contains more elements than can be indexed with a `u32` 39 | /// value, this function traps. 40 | /// 41 | /// A timeout can be implemented by adding a pollable from the 42 | /// wasi-clocks API to the list. 43 | /// 44 | /// This function does not return a `result`; polling in itself does not 45 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 46 | /// the pollables has an error, it is indicated by marking the source as 47 | /// being reaedy for I/O. 48 | pub fn poll(in_ : Array[Pollable]) -> FixedArray[UInt] { 49 | let address = @ffi.malloc(in_.length() * 4) 50 | for index = 0; index < in_.length(); index = index + 1 { 51 | let element : Pollable = in_[index] 52 | let base = address + index * 4 53 | let Pollable(handle) = element 54 | @ffi.store32(base + 0, handle) 55 | } 56 | let return_area = @ffi.malloc(8) 57 | wasmImportPoll(address, in_.length(), return_area) 58 | let result = @ffi.ptr2uint_array(@ffi.load32(return_area + 0)) 59 | @ffi.free(address) 60 | @ffi.free(return_area) 61 | return result 62 | } 63 | -------------------------------------------------------------------------------- /interface/imports/wasi/io/streams/README.md: -------------------------------------------------------------------------------- 1 | WASI I/O is an I/O abstraction API which is currently focused on providing 2 | stream types. 3 | 4 | In the future, the component model is expected to add built-in stream types; 5 | when it does, they are expected to subsume this API. -------------------------------------------------------------------------------- /interface/imports/wasi/io/streams/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropInputStream(resource : Int) = "wasi:io/streams@0.2.0" "[resource-drop]input-stream" 4 | 5 | fn wasmImportResourceDropOutputStream(resource : Int) = "wasi:io/streams@0.2.0" "[resource-drop]output-stream" 6 | 7 | fn wasmImportMethodInputStreamRead(p0 : Int, p1 : Int64, p2 : Int) = "wasi:io/streams@0.2.0" "[method]input-stream.read" 8 | 9 | fn wasmImportMethodInputStreamBlockingRead(p0 : Int, p1 : Int64, p2 : Int) = "wasi:io/streams@0.2.0" "[method]input-stream.blocking-read" 10 | 11 | fn wasmImportMethodInputStreamSkip(p0 : Int, p1 : Int64, p2 : Int) = "wasi:io/streams@0.2.0" "[method]input-stream.skip" 12 | 13 | fn wasmImportMethodInputStreamBlockingSkip(p0 : Int, p1 : Int64, p2 : Int) = "wasi:io/streams@0.2.0" "[method]input-stream.blocking-skip" 14 | 15 | fn wasmImportMethodInputStreamSubscribe(p0 : Int) -> Int = "wasi:io/streams@0.2.0" "[method]input-stream.subscribe" 16 | 17 | fn wasmImportMethodOutputStreamCheckWrite(p0 : Int, p1 : Int) = "wasi:io/streams@0.2.0" "[method]output-stream.check-write" 18 | 19 | fn wasmImportMethodOutputStreamWrite(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "wasi:io/streams@0.2.0" "[method]output-stream.write" 20 | 21 | fn wasmImportMethodOutputStreamBlockingWriteAndFlush( 22 | p0 : Int, 23 | p1 : Int, 24 | p2 : Int, 25 | p3 : Int 26 | ) = "wasi:io/streams@0.2.0" "[method]output-stream.blocking-write-and-flush" 27 | 28 | fn wasmImportMethodOutputStreamFlush(p0 : Int, p1 : Int) = "wasi:io/streams@0.2.0" "[method]output-stream.flush" 29 | 30 | fn wasmImportMethodOutputStreamBlockingFlush(p0 : Int, p1 : Int) = "wasi:io/streams@0.2.0" "[method]output-stream.blocking-flush" 31 | 32 | fn wasmImportMethodOutputStreamSubscribe(p0 : Int) -> Int = "wasi:io/streams@0.2.0" "[method]output-stream.subscribe" 33 | 34 | fn wasmImportMethodOutputStreamWriteZeroes(p0 : Int, p1 : Int64, p2 : Int) = "wasi:io/streams@0.2.0" "[method]output-stream.write-zeroes" 35 | 36 | fn wasmImportMethodOutputStreamBlockingWriteZeroesAndFlush( 37 | p0 : Int, 38 | p1 : Int64, 39 | p2 : Int 40 | ) = "wasi:io/streams@0.2.0" "[method]output-stream.blocking-write-zeroes-and-flush" 41 | 42 | fn wasmImportMethodOutputStreamSplice(p0 : Int, p1 : Int, p2 : Int64, p3 : Int) = "wasi:io/streams@0.2.0" "[method]output-stream.splice" 43 | 44 | fn wasmImportMethodOutputStreamBlockingSplice( 45 | p0 : Int, 46 | p1 : Int, 47 | p2 : Int64, 48 | p3 : Int 49 | ) = "wasi:io/streams@0.2.0" "[method]output-stream.blocking-splice" 50 | -------------------------------------------------------------------------------- /interface/imports/wasi/io/streams/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/error", "alias" : "error" }, { "path" : "moonbit/spin/interface/imports/wasi/io/poll", "alias" : "poll" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecure/README.md: -------------------------------------------------------------------------------- 1 | The insecure interface for insecure pseudo-random numbers. 2 | 3 | It is intended to be portable at least between Unix-family platforms and 4 | Windows. -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecure/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetInsecureRandomBytes(p0 : Int64, p1 : Int) = "wasi:random/insecure@0.2.0" "get-insecure-random-bytes" 3 | 4 | fn wasmImportGetInsecureRandomU64() -> Int64 = "wasi:random/insecure@0.2.0" "get-insecure-random-u64" 5 | -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecure/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecure/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Return `len` insecure pseudo-random bytes. 3 | /// 4 | /// This function is not cryptographically secure. Do not use it for 5 | /// anything related to security. 6 | /// 7 | /// There are no requirements on the values of the returned bytes, however 8 | /// implementations are encouraged to return evenly distributed values with 9 | /// a long period. 10 | pub fn get_insecure_random_bytes(len : UInt64) -> Bytes { 11 | let return_area = @ffi.malloc(8) 12 | wasmImportGetInsecureRandomBytes(len.to_int64(), return_area) 13 | let result = @ffi.ptr2bytes(@ffi.load32(return_area + 0)) 14 | @ffi.free(return_area) 15 | return result 16 | } 17 | 18 | /// Return an insecure pseudo-random `u64` value. 19 | /// 20 | /// This function returns the same type of pseudo-random data as 21 | /// `get-insecure-random-bytes`, represented as a `u64`. 22 | pub fn get_insecure_random_u64() -> UInt64 { 23 | let result : Int64 = wasmImportGetInsecureRandomU64() 24 | return result.to_uint64() 25 | } 26 | -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecureSeed/README.md: -------------------------------------------------------------------------------- 1 | The insecure-seed interface for seeding hash-map DoS resistance. 2 | 3 | It is intended to be portable at least between Unix-family platforms and 4 | Windows. -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecureSeed/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportInsecureSeed(p0 : Int) = "wasi:random/insecure-seed@0.2.0" "insecure-seed" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecureSeed/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/random/insecureSeed/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Return a 128-bit value that may contain a pseudo-random value. 3 | /// 4 | /// The returned value is not required to be computed from a CSPRNG, and may 5 | /// even be entirely deterministic. Host implementations are encouraged to 6 | /// provide pseudo-random values to any program exposed to 7 | /// attacker-controlled content, to enable DoS protection built into many 8 | /// languages' hash-map implementations. 9 | /// 10 | /// This function is intended to only be called once, by a source language 11 | /// to initialize Denial Of Service (DoS) protection in its hash-map 12 | /// implementation. 13 | /// 14 | /// # Expected future evolution 15 | /// 16 | /// This will likely be changed to a value import, to prevent it from being 17 | /// called multiple times and potentially used for purposes other than DoS 18 | /// protection. 19 | pub fn insecure_seed() -> (UInt64, UInt64) { 20 | let return_area = @ffi.malloc(16) 21 | wasmImportInsecureSeed(return_area) 22 | @ffi.free(return_area) 23 | return ( 24 | @ffi.load64(return_area + 0).to_uint64(), 25 | @ffi.load64(return_area + 8).to_uint64(), 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /interface/imports/wasi/random/random/README.md: -------------------------------------------------------------------------------- 1 | WASI Random is a random data API. 2 | 3 | It is intended to be portable at least between Unix-family platforms and 4 | Windows. -------------------------------------------------------------------------------- /interface/imports/wasi/random/random/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportGetRandomBytes(p0 : Int64, p1 : Int) = "wasi:random/random@0.2.0" "get-random-bytes" 3 | 4 | fn wasmImportGetRandomU64() -> Int64 = "wasi:random/random@0.2.0" "get-random-u64" 5 | -------------------------------------------------------------------------------- /interface/imports/wasi/random/random/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/random/random/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Return `len` cryptographically-secure random or pseudo-random bytes. 3 | /// 4 | /// This function must produce data at least as cryptographically secure and 5 | /// fast as an adequately seeded cryptographically-secure pseudo-random 6 | /// number generator (CSPRNG). It must not block, from the perspective of 7 | /// the calling program, under any circumstances, including on the first 8 | /// request and on requests for numbers of bytes. The returned data must 9 | /// always be unpredictable. 10 | /// 11 | /// This function must always return fresh data. Deterministic environments 12 | /// must omit this function, rather than implementing it with deterministic 13 | /// data. 14 | pub fn get_random_bytes(len : UInt64) -> Bytes { 15 | let return_area = @ffi.malloc(8) 16 | wasmImportGetRandomBytes(len.to_int64(), return_area) 17 | let result = @ffi.ptr2bytes(@ffi.load32(return_area + 0)) 18 | @ffi.free(return_area) 19 | return result 20 | } 21 | 22 | /// Return a cryptographically-secure random or pseudo-random `u64` value. 23 | /// 24 | /// This function returns the same type of data as `get-random-bytes`, 25 | /// represented as a `u64`. 26 | pub fn get_random_u64() -> UInt64 { 27 | let result : Int64 = wasmImportGetRandomU64() 28 | return result.to_uint64() 29 | } 30 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/instanceNetwork/README.md: -------------------------------------------------------------------------------- 1 | This interface provides a value-export of the default network handle.. -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/instanceNetwork/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportInstanceNetwork() -> Int = "wasi:sockets/instance-network@0.2.0" "instance-network" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/instanceNetwork/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/network", "alias" : "network" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/instanceNetwork/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Get a handle to the default network. 3 | pub fn instance_network() -> @network.Network { 4 | let result : Int = wasmImportInstanceNetwork() 5 | return @network.Network::Network(result) 6 | } 7 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/ipNameLookup/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropResolveAddressStream(resource : Int) = "wasi:sockets/ip-name-lookup@0.2.0" "[resource-drop]resolve-address-stream" 4 | 5 | fn wasmImportResolveAddresses(p0 : Int, p1 : Int, p2 : Int, p3 : Int) = "wasi:sockets/ip-name-lookup@0.2.0" "resolve-addresses" 6 | 7 | fn wasmImportMethodResolveAddressStreamResolveNextAddress(p0 : Int, p1 : Int) = "wasi:sockets/ip-name-lookup@0.2.0" "[method]resolve-address-stream.resolve-next-address" 8 | 9 | fn wasmImportMethodResolveAddressStreamSubscribe(p0 : Int) -> Int = "wasi:sockets/ip-name-lookup@0.2.0" "[method]resolve-address-stream.subscribe" 10 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/ipNameLookup/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/poll", "alias" : "poll" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/network", "alias" : "network" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/network/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropNetwork(resource : Int) = "wasi:sockets/network@0.2.0" "[resource-drop]network" 4 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/network/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { } -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/tcp/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/poll", "alias" : "poll" }, { "path" : "moonbit/spin/interface/imports/wasi/io/streams", "alias" : "streams" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/network", "alias" : "network" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/tcpCreateSocket/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportCreateTcpSocket(p0 : Int, p1 : Int) = "wasi:sockets/tcp-create-socket@0.2.0" "create-tcp-socket" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/tcpCreateSocket/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/network", "alias" : "network" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/tcp", "alias" : "tcp" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/tcpCreateSocket/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Create a new TCP socket. 3 | /// 4 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. 5 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 6 | /// 7 | /// This function does not require a network capability handle. This is considered to be safe because 8 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` 9 | /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 10 | /// 11 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 12 | /// 13 | /// # Typical errors 14 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 15 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 16 | /// 17 | /// # References 18 | /// - 19 | /// - 20 | /// - 21 | /// - 22 | pub fn create_tcp_socket( 23 | address_family : @network.IpAddressFamily 24 | ) -> Result[@tcp.TcpSocket, @network.ErrorCode] { 25 | let return_area = @ffi.malloc(8) 26 | wasmImportCreateTcpSocket(address_family.ordinal(), return_area) 27 | let lifted = match @ffi.load8_u(return_area + 0) { 28 | 0 => Result::Ok(@tcp.TcpSocket::TcpSocket(@ffi.load32(return_area + 4))) 29 | 1 => Result::Err(@network.ErrorCode::from(@ffi.load8_u(return_area + 4))) 30 | _ => panic() 31 | } 32 | @ffi.free(return_area) 33 | return lifted 34 | } 35 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/udp/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | 3 | fn wasmImportResourceDropUdpSocket(resource : Int) = "wasi:sockets/udp@0.2.0" "[resource-drop]udp-socket" 4 | 5 | fn wasmImportResourceDropIncomingDatagramStream(resource : Int) = "wasi:sockets/udp@0.2.0" "[resource-drop]incoming-datagram-stream" 6 | 7 | fn wasmImportResourceDropOutgoingDatagramStream(resource : Int) = "wasi:sockets/udp@0.2.0" "[resource-drop]outgoing-datagram-stream" 8 | 9 | fn wasmImportMethodUdpSocketStartBind( 10 | p0 : Int, 11 | p1 : Int, 12 | p2 : Int, 13 | p3 : Int, 14 | p4 : Int, 15 | p5 : Int, 16 | p6 : Int, 17 | p7 : Int, 18 | p8 : Int, 19 | p9 : Int, 20 | p10 : Int, 21 | p11 : Int, 22 | p12 : Int, 23 | p13 : Int, 24 | p14 : Int 25 | ) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.start-bind" 26 | 27 | fn wasmImportMethodUdpSocketFinishBind(p0 : Int, p1 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.finish-bind" 28 | 29 | fn wasmImportMethodUdpSocketStream( 30 | p0 : Int, 31 | p1 : Int, 32 | p2 : Int, 33 | p3 : Int, 34 | p4 : Int, 35 | p5 : Int, 36 | p6 : Int, 37 | p7 : Int, 38 | p8 : Int, 39 | p9 : Int, 40 | p10 : Int, 41 | p11 : Int, 42 | p12 : Int, 43 | p13 : Int, 44 | p14 : Int 45 | ) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.stream" 46 | 47 | fn wasmImportMethodUdpSocketLocalAddress(p0 : Int, p1 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.local-address" 48 | 49 | fn wasmImportMethodUdpSocketRemoteAddress(p0 : Int, p1 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.remote-address" 50 | 51 | fn wasmImportMethodUdpSocketAddressFamily(p0 : Int) -> Int = "wasi:sockets/udp@0.2.0" "[method]udp-socket.address-family" 52 | 53 | fn wasmImportMethodUdpSocketUnicastHopLimit(p0 : Int, p1 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.unicast-hop-limit" 54 | 55 | fn wasmImportMethodUdpSocketSetUnicastHopLimit(p0 : Int, p1 : Int, p2 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.set-unicast-hop-limit" 56 | 57 | fn wasmImportMethodUdpSocketReceiveBufferSize(p0 : Int, p1 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.receive-buffer-size" 58 | 59 | fn wasmImportMethodUdpSocketSetReceiveBufferSize( 60 | p0 : Int, 61 | p1 : Int64, 62 | p2 : Int 63 | ) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.set-receive-buffer-size" 64 | 65 | fn wasmImportMethodUdpSocketSendBufferSize(p0 : Int, p1 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.send-buffer-size" 66 | 67 | fn wasmImportMethodUdpSocketSetSendBufferSize(p0 : Int, p1 : Int64, p2 : Int) = "wasi:sockets/udp@0.2.0" "[method]udp-socket.set-send-buffer-size" 68 | 69 | fn wasmImportMethodUdpSocketSubscribe(p0 : Int) -> Int = "wasi:sockets/udp@0.2.0" "[method]udp-socket.subscribe" 70 | 71 | fn wasmImportMethodIncomingDatagramStreamReceive( 72 | p0 : Int, 73 | p1 : Int64, 74 | p2 : Int 75 | ) = "wasi:sockets/udp@0.2.0" "[method]incoming-datagram-stream.receive" 76 | 77 | fn wasmImportMethodIncomingDatagramStreamSubscribe(p0 : Int) -> Int = "wasi:sockets/udp@0.2.0" "[method]incoming-datagram-stream.subscribe" 78 | 79 | fn wasmImportMethodOutgoingDatagramStreamCheckSend(p0 : Int, p1 : Int) = "wasi:sockets/udp@0.2.0" "[method]outgoing-datagram-stream.check-send" 80 | 81 | fn wasmImportMethodOutgoingDatagramStreamSend( 82 | p0 : Int, 83 | p1 : Int, 84 | p2 : Int, 85 | p3 : Int 86 | ) = "wasi:sockets/udp@0.2.0" "[method]outgoing-datagram-stream.send" 87 | 88 | fn wasmImportMethodOutgoingDatagramStreamSubscribe(p0 : Int) -> Int = "wasi:sockets/udp@0.2.0" "[method]outgoing-datagram-stream.subscribe" 89 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/udp/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/io/poll", "alias" : "poll" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/network", "alias" : "network" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/udpCreateSocket/ffi.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | fn wasmImportCreateUdpSocket(p0 : Int, p1 : Int) = "wasi:sockets/udp-create-socket@0.2.0" "create-udp-socket" 3 | -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/udpCreateSocket/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { "import": [{ "path" : "moonbit/spin/ffi", "alias" : "ffi" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/network", "alias" : "network" }, { "path" : "moonbit/spin/interface/imports/wasi/sockets/udp", "alias" : "udp" }] } -------------------------------------------------------------------------------- /interface/imports/wasi/sockets/udpCreateSocket/top.mbt: -------------------------------------------------------------------------------- 1 | // Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! 2 | /// Create a new UDP socket. 3 | /// 4 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. 5 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 6 | /// 7 | /// This function does not require a network capability handle. This is considered to be safe because 8 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, 9 | /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 10 | /// 11 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 12 | /// 13 | /// # Typical errors 14 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 15 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 16 | /// 17 | /// # References: 18 | /// - 19 | /// - 20 | /// - 21 | /// - 22 | pub fn create_udp_socket( 23 | address_family : @network.IpAddressFamily 24 | ) -> Result[@udp.UdpSocket, @network.ErrorCode] { 25 | let return_area = @ffi.malloc(8) 26 | wasmImportCreateUdpSocket(address_family.ordinal(), return_area) 27 | let lifted = match @ffi.load8_u(return_area + 0) { 28 | 0 => Result::Ok(@udp.UdpSocket::UdpSocket(@ffi.load32(return_area + 4))) 29 | 1 => Result::Err(@network.ErrorCode::from(@ffi.load8_u(return_area + 4))) 30 | _ => panic() 31 | } 32 | @ffi.free(return_area) 33 | return lifted 34 | } 35 | -------------------------------------------------------------------------------- /io/io.mbt: -------------------------------------------------------------------------------- 1 | // Copyright 2024 International Digital Economy Academy 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub let stdin : @streams.InputStream = @stdin.get_stdin() 16 | 17 | pub let stdout : @streams.OutputStream = @stdout.get_stdout() 18 | 19 | pub let stderr : @streams.OutputStream = @stderr.get_stderr() 20 | 21 | pub fn read(stream : @streams.InputStream) -> Iter[Bytes] { 22 | Iter::new( 23 | fn(f) { 24 | loop stream.blocking_read(4096) { 25 | Ok(bytes) => 26 | match f(bytes) { 27 | IterEnd => return IterEnd 28 | IterContinue => continue stream.blocking_read(4096) 29 | } 30 | Err(Closed) => return IterContinue 31 | Err(_) => return IterEnd 32 | } 33 | }, 34 | ) 35 | } 36 | 37 | let output_buffer : Bytes = Bytes::new(4096) 38 | 39 | pub fn write(bytes : Iter[Bytes], stream : @streams.OutputStream) -> Unit { 40 | let mut ptr = 0 41 | for byte in bytes { 42 | ptr = loop ptr, byte.length() { 43 | ptr, 0 => ptr 44 | ptr, len => 45 | if ptr + len <= 4096 { 46 | output_buffer.blit(ptr, byte, 0, len) 47 | continue ptr + len, 0 48 | } else { 49 | let p = 4096 - ptr 50 | output_buffer.blit(ptr, byte, 0, p) 51 | stream.blocking_write_and_flush(output_buffer) |> ignore 52 | continue 0, len - p 53 | } 54 | } 55 | if ptr == 4096 { 56 | stream.blocking_write_and_flush(output_buffer) |> ignore 57 | ptr = 0 58 | } 59 | } else { 60 | let b = Bytes::new(ptr) 61 | b.blit(0, output_buffer, 0, ptr) 62 | stream.blocking_write_and_flush(b) |> ignore 63 | } 64 | } 65 | 66 | pub fn writeln(bytes : Iter[Bytes], stream : @streams.OutputStream) -> Unit { 67 | write(bytes, stream) 68 | stream.blocking_write_and_flush(b"\n") |> ignore 69 | } 70 | 71 | pub fn print(string : String, stream~ : @streams.OutputStream = stdout) -> Unit { 72 | string.iter() |> @utils.encode_utf8 |> write(stream) 73 | } 74 | 75 | pub fn println( 76 | string : String, 77 | stream~ : @streams.OutputStream = stdout 78 | ) -> Unit { 79 | string.iter() |> @utils.encode_utf8 |> writeln(stream) 80 | } 81 | 82 | pub fn eprint(string : String) -> Unit { 83 | print(string, stream=stderr) 84 | } 85 | 86 | pub fn eprintln(string : String) -> Unit { 87 | println(string, stream=stderr) 88 | } 89 | -------------------------------------------------------------------------------- /io/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "import": [ 3 | "moonbit/spin/interface/imports/wasi/io/streams", 4 | "moonbit/spin/interface/imports/wasi/io/error", 5 | "moonbit/spin/utils", 6 | "moonbit/spin/interface/imports/wasi/cli/stderr", 7 | "moonbit/spin/interface/imports/wasi/cli/stdout", 8 | "moonbit/spin/interface/imports/wasi/cli/stdin" 9 | ] 10 | } -------------------------------------------------------------------------------- /moon.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "moonbit/spin", 3 | "deps": { 4 | "moonbitlang/x": "0.4.6" 5 | } 6 | } -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source .env 3 | spin deploy --variable openapi_key="${SPIN_VARIABLE_OPENAPI_KEY}" --variable client_id="${SPIN_VARIABLE_CLIENT_ID}" --variable private_key="${SPIN_VARIABLE_PRIVATE_KEY}" --variable user_agent="${SPIN_VARIABLE_USER_AGENT}" --variable app_id="${SPIN_VARIABLE_APP_ID}" -------------------------------------------------------------------------------- /spin.toml: -------------------------------------------------------------------------------- 1 | spin_manifest_version = 2 2 | 3 | # General identification information 4 | [application] 5 | name = "moonbit-ai-agent" 6 | version = "1.0.0" 7 | description = "An application that reviews GitHub PR upon request." 8 | 9 | # Secrets 10 | [variables] 11 | openapi_key = { required = true, secret = true } 12 | private_key = { required = true, secret = true } 13 | client_id = { required = true } 14 | app_id = { required = true } 15 | user_agent = { required = true } 16 | 17 | # The application's sole trigger. This application responds to HTTP requests 18 | # on the path "/...", and handles them using the "agent" component. 19 | [[trigger.http]] 20 | route = "/..." 21 | component = "agent" 22 | 23 | # The "agent" component 24 | [component.agent] 25 | description = "The MoonBit Agent" 26 | # The Wasm module to run for the component 27 | source = "target/agent.wasm" 28 | # Permitted outgoing HTTP requests 29 | allowed_outbound_hosts = ["https://api.github.com", "https://api.deepseek.com", "https://www.github.com", "https://api.siliconflow.cn"] 30 | # How to build the Wasm module from source 31 | [component.agent.build] 32 | command = """moon build --target wasm -g 33 | wasm-tools component embed --encoding utf16 wit target/wasm/debug/build/agent/agent.wasm --world http-trigger -o target/agent.core.wasm 34 | wasm-tools component new target/agent.core.wasm -o target/agent.wasm""" 35 | [component.agent.variables] 36 | open_api_key = "{{ openapi_key }}" 37 | private_key = "{{ private_key }}" 38 | client_id = "{{ client_id }}" 39 | app_id = "{{ app_id }}" 40 | user_agent = "{{ user_agent }}" 41 | -------------------------------------------------------------------------------- /utils/encoding.mbt: -------------------------------------------------------------------------------- 1 | // Copyright 2024 International Digital Economy Academy 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub fn decode_utf8(bytes : Iter[Byte]) -> Iter[Char] { 16 | Iter::new( 17 | fn(f) { 18 | let mut len = 0 19 | let mut char = 0 20 | for byte in bytes { 21 | let b = byte.to_int() 22 | if len == 0 { 23 | if b < 0b1100_0000 { 24 | match f(Char::from_int((char << 6) | b)) { 25 | IterEnd => break IterEnd 26 | IterContinue => continue 27 | } 28 | } else if b < 0b1110_0000 { 29 | char = b & 0b11111 30 | len = 1 31 | } else if b < 0b1111_0000 { 32 | char = b & 0b1111 33 | len = 2 34 | } else if b < 0b1111_1000 { 35 | char = b & 0b111 36 | len = 3 37 | } else { 38 | break IterEnd 39 | } 40 | } else if (b >> 6) == 0b10 { 41 | char = (char << 6) | (b & 0b111111) 42 | len -= 1 43 | if len == 0 { 44 | match f(Char::from_int(char)) { 45 | IterEnd => break IterEnd 46 | IterContinue => { 47 | char = 0 48 | continue 49 | } 50 | } 51 | } 52 | } else { 53 | break IterEnd 54 | } 55 | } else { 56 | IterContinue 57 | } 58 | }, 59 | ) 60 | } 61 | 62 | pub fn iter_to_string(iter : Iter[Char]) -> String { 63 | let buffer = Buffer::new() 64 | iter.each(fn(ch) { buffer.write_char(ch) }) 65 | buffer.to_string() 66 | } 67 | 68 | pub fn encode_utf8(string : Iter[Char]) -> Iter[Bytes] { 69 | Iter::new( 70 | fn(f) { 71 | for char in string { 72 | let point = char.to_int() 73 | if point < 0x80 { 74 | let bytes = Bytes::new(1) 75 | bytes[0] = (((point >> 0) & 0x7F) | 0x00).to_byte() 76 | match f(bytes) { 77 | IterEnd => break IterEnd 78 | _ => continue 79 | } 80 | } else if point < 0x0800 { 81 | let bytes = Bytes::new(2) 82 | bytes[0] = (((point >> 6) & 0x1F) | 0xC0).to_byte() 83 | bytes[1] = (((point >> 0) & 0x3F) | 0x80).to_byte() 84 | match f(bytes) { 85 | IterEnd => break IterEnd 86 | _ => continue 87 | } 88 | } else if point < 0x10000 { 89 | let bytes = Bytes::new(3) 90 | bytes[0] = (((point >> 12) & 0x0F) | 0xE0).to_byte() 91 | bytes[1] = (((point >> 6) & 0x3F) | 0x80).to_byte() 92 | bytes[2] = (((point >> 0) & 0x3F) | 0x80).to_byte() 93 | match f(bytes) { 94 | IterEnd => break IterEnd 95 | _ => continue 96 | } 97 | } else if point < 0x110000 { 98 | let bytes = Bytes::new(4) 99 | bytes[0] = (((point >> 18) & 0x07) | 0xF0).to_byte() 100 | bytes[1] = (((point >> 12) & 0x3F) | 0x80).to_byte() 101 | bytes[2] = (((point >> 6) & 0x3F) | 0x80).to_byte() 102 | bytes[3] = (((point >> 0) & 0x3F) | 0x80).to_byte() 103 | match f(bytes) { 104 | IterEnd => break IterEnd 105 | _ => continue 106 | } 107 | } 108 | } else { 109 | IterContinue 110 | } 111 | }, 112 | ) 113 | } 114 | -------------------------------------------------------------------------------- /utils/moon.pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "import": [ 3 | "moonbitlang/x/crypto" 4 | ] 5 | } -------------------------------------------------------------------------------- /utils/resource.mbt: -------------------------------------------------------------------------------- 1 | // Copyright 2024 International Digital Economy Academy 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub(open) trait Droppable { 16 | drop(Self) -> Unit 17 | } 18 | 19 | pub fn use[T : Droppable, U](t : T, f : (T) -> U) -> U { 20 | let result = f(t) 21 | t.drop() 22 | result 23 | } 24 | -------------------------------------------------------------------------------- /wit/deps.toml: -------------------------------------------------------------------------------- 1 | spin = "https://github.com/fermyon/spin/archive/main.tar.gz" -------------------------------------------------------------------------------- /wit/deps/cli-2023-10-18/command.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.0-rc-2023-10-18; 2 | 3 | world command { 4 | include reactor; 5 | 6 | export run; 7 | } 8 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-10-18/environment.wit: -------------------------------------------------------------------------------- 1 | interface environment { 2 | /// Get the POSIX-style environment variables. 3 | /// 4 | /// Each environment variable is provided as a pair of string variable names 5 | /// and string value. 6 | /// 7 | /// Morally, these are a value import, but until value imports are available 8 | /// in the component model, this import function should return the same 9 | /// values each time it is called. 10 | get-environment: func() -> list>; 11 | 12 | /// Get the POSIX-style arguments to the program. 13 | get-arguments: func() -> list; 14 | 15 | /// Return a path that programs should use as their initial current working 16 | /// directory, interpreting `.` as shorthand for this. 17 | initial-cwd: func() -> option; 18 | } 19 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-10-18/exit.wit: -------------------------------------------------------------------------------- 1 | interface exit { 2 | /// Exit the current instance and any linked instances. 3 | exit: func(status: result); 4 | } 5 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-10-18/reactor.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.0-rc-2023-10-18; 2 | 3 | world reactor { 4 | import wasi:clocks/wall-clock@0.2.0-rc-2023-10-18; 5 | import wasi:clocks/monotonic-clock@0.2.0-rc-2023-10-18; 6 | import wasi:clocks/timezone@0.2.0-rc-2023-10-18; 7 | import wasi:filesystem/types@0.2.0-rc-2023-10-18; 8 | import wasi:filesystem/preopens@0.2.0-rc-2023-10-18; 9 | import wasi:sockets/instance-network@0.2.0-rc-2023-10-18; 10 | import wasi:sockets/ip-name-lookup@0.2.0-rc-2023-10-18; 11 | import wasi:sockets/network@0.2.0-rc-2023-10-18; 12 | import wasi:sockets/tcp-create-socket@0.2.0-rc-2023-10-18; 13 | import wasi:sockets/tcp@0.2.0-rc-2023-10-18; 14 | import wasi:sockets/udp-create-socket@0.2.0-rc-2023-10-18; 15 | import wasi:sockets/udp@0.2.0-rc-2023-10-18; 16 | import wasi:random/random@0.2.0-rc-2023-10-18; 17 | import wasi:random/insecure@0.2.0-rc-2023-10-18; 18 | import wasi:random/insecure-seed@0.2.0-rc-2023-10-18; 19 | import wasi:io/poll@0.2.0-rc-2023-10-18; 20 | import wasi:io/streams@0.2.0-rc-2023-10-18; 21 | 22 | import environment; 23 | import exit; 24 | import stdin; 25 | import stdout; 26 | import stderr; 27 | import terminal-input; 28 | import terminal-output; 29 | import terminal-stdin; 30 | import terminal-stdout; 31 | import terminal-stderr; 32 | } 33 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-10-18/run.wit: -------------------------------------------------------------------------------- 1 | interface run { 2 | /// Run the program. 3 | run: func() -> result; 4 | } 5 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-10-18/stdio.wit: -------------------------------------------------------------------------------- 1 | interface stdin { 2 | use wasi:io/streams@0.2.0-rc-2023-10-18.{input-stream}; 3 | 4 | get-stdin: func() -> input-stream; 5 | } 6 | 7 | interface stdout { 8 | use wasi:io/streams@0.2.0-rc-2023-10-18.{output-stream}; 9 | 10 | get-stdout: func() -> output-stream; 11 | } 12 | 13 | interface stderr { 14 | use wasi:io/streams@0.2.0-rc-2023-10-18.{output-stream}; 15 | 16 | get-stderr: func() -> output-stream; 17 | } 18 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-10-18/terminal.wit: -------------------------------------------------------------------------------- 1 | interface terminal-input { 2 | /// The input side of a terminal. 3 | resource terminal-input; 4 | 5 | // In the future, this may include functions for disabling echoing, 6 | // disabling input buffering so that keyboard events are sent through 7 | // immediately, querying supported features, and so on. 8 | } 9 | 10 | interface terminal-output { 11 | /// The output side of a terminal. 12 | resource terminal-output; 13 | 14 | // In the future, this may include functions for querying the terminal 15 | // size, being notified of terminal size changes, querying supported 16 | // features, and so on. 17 | } 18 | 19 | /// An interface providing an optional `terminal-input` for stdin as a 20 | /// link-time authority. 21 | interface terminal-stdin { 22 | use terminal-input.{terminal-input}; 23 | 24 | /// If stdin is connected to a terminal, return a `terminal-input` handle 25 | /// allowing further interaction with it. 26 | get-terminal-stdin: func() -> option; 27 | } 28 | 29 | /// An interface providing an optional `terminal-output` for stdout as a 30 | /// link-time authority. 31 | interface terminal-stdout { 32 | use terminal-output.{terminal-output}; 33 | 34 | /// If stdout is connected to a terminal, return a `terminal-output` handle 35 | /// allowing further interaction with it. 36 | get-terminal-stdout: func() -> option; 37 | } 38 | 39 | /// An interface providing an optional `terminal-output` for stderr as a 40 | /// link-time authority. 41 | interface terminal-stderr { 42 | use terminal-output.{terminal-output}; 43 | 44 | /// If stderr is connected to a terminal, return a `terminal-output` handle 45 | /// allowing further interaction with it. 46 | get-terminal-stderr: func() -> option; 47 | } 48 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-11-10/command.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.0-rc-2023-11-10; 2 | 3 | world command { 4 | include reactor; 5 | 6 | export run; 7 | } 8 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-11-10/environment.wit: -------------------------------------------------------------------------------- 1 | interface environment { 2 | /// Get the POSIX-style environment variables. 3 | /// 4 | /// Each environment variable is provided as a pair of string variable names 5 | /// and string value. 6 | /// 7 | /// Morally, these are a value import, but until value imports are available 8 | /// in the component model, this import function should return the same 9 | /// values each time it is called. 10 | get-environment: func() -> list>; 11 | 12 | /// Get the POSIX-style arguments to the program. 13 | get-arguments: func() -> list; 14 | 15 | /// Return a path that programs should use as their initial current working 16 | /// directory, interpreting `.` as shorthand for this. 17 | initial-cwd: func() -> option; 18 | } 19 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-11-10/exit.wit: -------------------------------------------------------------------------------- 1 | interface exit { 2 | /// Exit the current instance and any linked instances. 3 | exit: func(status: result); 4 | } 5 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-11-10/reactor.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.0-rc-2023-11-10; 2 | 3 | world reactor { 4 | import wasi:clocks/wall-clock@0.2.0-rc-2023-11-10; 5 | import wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10; 6 | import wasi:filesystem/types@0.2.0-rc-2023-11-10; 7 | import wasi:filesystem/preopens@0.2.0-rc-2023-11-10; 8 | import wasi:sockets/instance-network@0.2.0-rc-2023-11-10; 9 | import wasi:sockets/ip-name-lookup@0.2.0-rc-2023-11-10; 10 | import wasi:sockets/network@0.2.0-rc-2023-11-10; 11 | import wasi:sockets/tcp-create-socket@0.2.0-rc-2023-11-10; 12 | import wasi:sockets/tcp@0.2.0-rc-2023-11-10; 13 | import wasi:sockets/udp-create-socket@0.2.0-rc-2023-11-10; 14 | import wasi:sockets/udp@0.2.0-rc-2023-11-10; 15 | import wasi:random/random@0.2.0-rc-2023-11-10; 16 | import wasi:random/insecure@0.2.0-rc-2023-11-10; 17 | import wasi:random/insecure-seed@0.2.0-rc-2023-11-10; 18 | import wasi:io/poll@0.2.0-rc-2023-11-10; 19 | import wasi:io/streams@0.2.0-rc-2023-11-10; 20 | 21 | import environment; 22 | import exit; 23 | import stdin; 24 | import stdout; 25 | import stderr; 26 | import terminal-input; 27 | import terminal-output; 28 | import terminal-stdin; 29 | import terminal-stdout; 30 | import terminal-stderr; 31 | } 32 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-11-10/run.wit: -------------------------------------------------------------------------------- 1 | interface run { 2 | /// Run the program. 3 | run: func() -> result; 4 | } 5 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-11-10/stdio.wit: -------------------------------------------------------------------------------- 1 | interface stdin { 2 | use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream}; 3 | 4 | get-stdin: func() -> input-stream; 5 | } 6 | 7 | interface stdout { 8 | use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream}; 9 | 10 | get-stdout: func() -> output-stream; 11 | } 12 | 13 | interface stderr { 14 | use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream}; 15 | 16 | get-stderr: func() -> output-stream; 17 | } 18 | -------------------------------------------------------------------------------- /wit/deps/cli-2023-11-10/terminal.wit: -------------------------------------------------------------------------------- 1 | interface terminal-input { 2 | /// The input side of a terminal. 3 | resource terminal-input; 4 | 5 | // In the future, this may include functions for disabling echoing, 6 | // disabling input buffering so that keyboard events are sent through 7 | // immediately, querying supported features, and so on. 8 | } 9 | 10 | interface terminal-output { 11 | /// The output side of a terminal. 12 | resource terminal-output; 13 | 14 | // In the future, this may include functions for querying the terminal 15 | // size, being notified of terminal size changes, querying supported 16 | // features, and so on. 17 | } 18 | 19 | /// An interface providing an optional `terminal-input` for stdin as a 20 | /// link-time authority. 21 | interface terminal-stdin { 22 | use terminal-input.{terminal-input}; 23 | 24 | /// If stdin is connected to a terminal, return a `terminal-input` handle 25 | /// allowing further interaction with it. 26 | get-terminal-stdin: func() -> option; 27 | } 28 | 29 | /// An interface providing an optional `terminal-output` for stdout as a 30 | /// link-time authority. 31 | interface terminal-stdout { 32 | use terminal-output.{terminal-output}; 33 | 34 | /// If stdout is connected to a terminal, return a `terminal-output` handle 35 | /// allowing further interaction with it. 36 | get-terminal-stdout: func() -> option; 37 | } 38 | 39 | /// An interface providing an optional `terminal-output` for stderr as a 40 | /// link-time authority. 41 | interface terminal-stderr { 42 | use terminal-output.{terminal-output}; 43 | 44 | /// If stderr is connected to a terminal, return a `terminal-output` handle 45 | /// allowing further interaction with it. 46 | get-terminal-stderr: func() -> option; 47 | } 48 | -------------------------------------------------------------------------------- /wit/deps/cli/command.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.0; 2 | 3 | world command { 4 | include imports; 5 | 6 | export run; 7 | } 8 | -------------------------------------------------------------------------------- /wit/deps/cli/environment.wit: -------------------------------------------------------------------------------- 1 | interface environment { 2 | /// Get the POSIX-style environment variables. 3 | /// 4 | /// Each environment variable is provided as a pair of string variable names 5 | /// and string value. 6 | /// 7 | /// Morally, these are a value import, but until value imports are available 8 | /// in the component model, this import function should return the same 9 | /// values each time it is called. 10 | get-environment: func() -> list>; 11 | 12 | /// Get the POSIX-style arguments to the program. 13 | get-arguments: func() -> list; 14 | 15 | /// Return a path that programs should use as their initial current working 16 | /// directory, interpreting `.` as shorthand for this. 17 | initial-cwd: func() -> option; 18 | } 19 | -------------------------------------------------------------------------------- /wit/deps/cli/exit.wit: -------------------------------------------------------------------------------- 1 | interface exit { 2 | /// Exit the current instance and any linked instances. 3 | exit: func(status: result); 4 | } 5 | -------------------------------------------------------------------------------- /wit/deps/cli/imports.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.0; 2 | 3 | world imports { 4 | include wasi:clocks/imports@0.2.0; 5 | include wasi:filesystem/imports@0.2.0; 6 | include wasi:sockets/imports@0.2.0; 7 | include wasi:random/imports@0.2.0; 8 | include wasi:io/imports@0.2.0; 9 | 10 | import environment; 11 | import exit; 12 | import stdin; 13 | import stdout; 14 | import stderr; 15 | import terminal-input; 16 | import terminal-output; 17 | import terminal-stdin; 18 | import terminal-stdout; 19 | import terminal-stderr; 20 | } 21 | -------------------------------------------------------------------------------- /wit/deps/cli/run.wit: -------------------------------------------------------------------------------- 1 | interface run { 2 | /// Run the program. 3 | run: func() -> result; 4 | } 5 | -------------------------------------------------------------------------------- /wit/deps/cli/stdio.wit: -------------------------------------------------------------------------------- 1 | interface stdin { 2 | use wasi:io/streams@0.2.0.{input-stream}; 3 | 4 | get-stdin: func() -> input-stream; 5 | } 6 | 7 | interface stdout { 8 | use wasi:io/streams@0.2.0.{output-stream}; 9 | 10 | get-stdout: func() -> output-stream; 11 | } 12 | 13 | interface stderr { 14 | use wasi:io/streams@0.2.0.{output-stream}; 15 | 16 | get-stderr: func() -> output-stream; 17 | } 18 | -------------------------------------------------------------------------------- /wit/deps/cli/terminal.wit: -------------------------------------------------------------------------------- 1 | /// Terminal input. 2 | /// 3 | /// In the future, this may include functions for disabling echoing, 4 | /// disabling input buffering so that keyboard events are sent through 5 | /// immediately, querying supported features, and so on. 6 | interface terminal-input { 7 | /// The input side of a terminal. 8 | resource terminal-input; 9 | } 10 | 11 | /// Terminal output. 12 | /// 13 | /// In the future, this may include functions for querying the terminal 14 | /// size, being notified of terminal size changes, querying supported 15 | /// features, and so on. 16 | interface terminal-output { 17 | /// The output side of a terminal. 18 | resource terminal-output; 19 | } 20 | 21 | /// An interface providing an optional `terminal-input` for stdin as a 22 | /// link-time authority. 23 | interface terminal-stdin { 24 | use terminal-input.{terminal-input}; 25 | 26 | /// If stdin is connected to a terminal, return a `terminal-input` handle 27 | /// allowing further interaction with it. 28 | get-terminal-stdin: func() -> option; 29 | } 30 | 31 | /// An interface providing an optional `terminal-output` for stdout as a 32 | /// link-time authority. 33 | interface terminal-stdout { 34 | use terminal-output.{terminal-output}; 35 | 36 | /// If stdout is connected to a terminal, return a `terminal-output` handle 37 | /// allowing further interaction with it. 38 | get-terminal-stdout: func() -> option; 39 | } 40 | 41 | /// An interface providing an optional `terminal-output` for stderr as a 42 | /// link-time authority. 43 | interface terminal-stderr { 44 | use terminal-output.{terminal-output}; 45 | 46 | /// If stderr is connected to a terminal, return a `terminal-output` handle 47 | /// allowing further interaction with it. 48 | get-terminal-stderr: func() -> option; 49 | } 50 | -------------------------------------------------------------------------------- /wit/deps/clocks-2023-10-18/monotonic-clock.wit: -------------------------------------------------------------------------------- 1 | /// WASI Monotonic Clock is a clock API intended to let users measure elapsed 2 | /// time. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | /// 7 | /// A monotonic clock is a clock which has an unspecified initial value, and 8 | /// successive reads of the clock will produce non-decreasing values. 9 | /// 10 | /// It is intended for measuring elapsed time. 11 | interface monotonic-clock { 12 | use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; 13 | 14 | /// A timestamp in nanoseconds. 15 | type instant = u64; 16 | 17 | /// Read the current value of the clock. 18 | /// 19 | /// The clock is monotonic, therefore calling this function repeatedly will 20 | /// produce a sequence of non-decreasing values. 21 | now: func() -> instant; 22 | 23 | /// Query the resolution of the clock. 24 | resolution: func() -> instant; 25 | 26 | /// Create a `pollable` which will resolve once the specified time has been 27 | /// reached. 28 | subscribe: func( 29 | when: instant, 30 | absolute: bool 31 | ) -> pollable; 32 | } 33 | -------------------------------------------------------------------------------- /wit/deps/clocks-2023-10-18/timezone.wit: -------------------------------------------------------------------------------- 1 | interface timezone { 2 | use wall-clock.{datetime}; 3 | 4 | /// Return information needed to display the given `datetime`. This includes 5 | /// the UTC offset, the time zone name, and a flag indicating whether 6 | /// daylight saving time is active. 7 | /// 8 | /// If the timezone cannot be determined for the given `datetime`, return a 9 | /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight 10 | /// saving time. 11 | display: func(when: datetime) -> timezone-display; 12 | 13 | /// The same as `display`, but only return the UTC offset. 14 | utc-offset: func(when: datetime) -> s32; 15 | 16 | /// Information useful for displaying the timezone of a specific `datetime`. 17 | /// 18 | /// This information may vary within a single `timezone` to reflect daylight 19 | /// saving time adjustments. 20 | record timezone-display { 21 | /// The number of seconds difference between UTC time and the local 22 | /// time of the timezone. 23 | /// 24 | /// The returned value will always be less than 86400 which is the 25 | /// number of seconds in a day (24*60*60). 26 | /// 27 | /// In implementations that do not expose an actual time zone, this 28 | /// should return 0. 29 | utc-offset: s32, 30 | 31 | /// The abbreviated name of the timezone to display to a user. The name 32 | /// `UTC` indicates Coordinated Universal Time. Otherwise, this should 33 | /// reference local standards for the name of the time zone. 34 | /// 35 | /// In implementations that do not expose an actual time zone, this 36 | /// should be the string `UTC`. 37 | /// 38 | /// In time zones that do not have an applicable name, a formatted 39 | /// representation of the UTC offset may be returned, such as `-04:00`. 40 | name: string, 41 | 42 | /// Whether daylight saving time is active. 43 | /// 44 | /// In implementations that do not expose an actual time zone, this 45 | /// should return false. 46 | in-daylight-saving-time: bool, 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /wit/deps/clocks-2023-10-18/wall-clock.wit: -------------------------------------------------------------------------------- 1 | /// WASI Wall Clock is a clock API intended to let users query the current 2 | /// time. The name "wall" makes an analogy to a "clock on the wall", which 3 | /// is not necessarily monotonic as it may be reset. 4 | /// 5 | /// It is intended to be portable at least between Unix-family platforms and 6 | /// Windows. 7 | /// 8 | /// A wall clock is a clock which measures the date and time according to 9 | /// some external reference. 10 | /// 11 | /// External references may be reset, so this clock is not necessarily 12 | /// monotonic, making it unsuitable for measuring elapsed time. 13 | /// 14 | /// It is intended for reporting the current date and time for humans. 15 | interface wall-clock { 16 | /// A time and date in seconds plus nanoseconds. 17 | record datetime { 18 | seconds: u64, 19 | nanoseconds: u32, 20 | } 21 | 22 | /// Read the current value of the clock. 23 | /// 24 | /// This clock is not monotonic, therefore calling this function repeatedly 25 | /// will not necessarily produce a sequence of non-decreasing values. 26 | /// 27 | /// The returned timestamps represent the number of seconds since 28 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], 29 | /// also known as [Unix Time]. 30 | /// 31 | /// The nanoseconds field of the output is always less than 1000000000. 32 | /// 33 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 34 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time 35 | now: func() -> datetime; 36 | 37 | /// Query the resolution of the clock. 38 | /// 39 | /// The nanoseconds field of the output is always less than 1000000000. 40 | resolution: func() -> datetime; 41 | } 42 | -------------------------------------------------------------------------------- /wit/deps/clocks-2023-10-18/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.0-rc-2023-10-18; 2 | 3 | world imports { 4 | import monotonic-clock; 5 | import wall-clock; 6 | import timezone; 7 | } 8 | -------------------------------------------------------------------------------- /wit/deps/clocks-2023-11-10/monotonic-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.0-rc-2023-11-10; 2 | /// WASI Monotonic Clock is a clock API intended to let users measure elapsed 3 | /// time. 4 | /// 5 | /// It is intended to be portable at least between Unix-family platforms and 6 | /// Windows. 7 | /// 8 | /// A monotonic clock is a clock which has an unspecified initial value, and 9 | /// successive reads of the clock will produce non-decreasing values. 10 | /// 11 | /// It is intended for measuring elapsed time. 12 | interface monotonic-clock { 13 | use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable}; 14 | 15 | /// An instant in time, in nanoseconds. An instant is relative to an 16 | /// unspecified initial value, and can only be compared to instances from 17 | /// the same monotonic-clock. 18 | type instant = u64; 19 | 20 | /// A duration of time, in nanoseconds. 21 | type duration = u64; 22 | 23 | /// Read the current value of the clock. 24 | /// 25 | /// The clock is monotonic, therefore calling this function repeatedly will 26 | /// produce a sequence of non-decreasing values. 27 | now: func() -> instant; 28 | 29 | /// Query the resolution of the clock. Returns the duration of time 30 | /// corresponding to a clock tick. 31 | resolution: func() -> duration; 32 | 33 | /// Create a `pollable` which will resolve once the specified instant 34 | /// occured. 35 | subscribe-instant: func( 36 | when: instant, 37 | ) -> pollable; 38 | 39 | /// Create a `pollable` which will resolve once the given duration has 40 | /// elapsed, starting at the time at which this function was called. 41 | /// occured. 42 | subscribe-duration: func( 43 | when: duration, 44 | ) -> pollable; 45 | } 46 | -------------------------------------------------------------------------------- /wit/deps/clocks-2023-11-10/wall-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.0-rc-2023-11-10; 2 | /// WASI Wall Clock is a clock API intended to let users query the current 3 | /// time. The name "wall" makes an analogy to a "clock on the wall", which 4 | /// is not necessarily monotonic as it may be reset. 5 | /// 6 | /// It is intended to be portable at least between Unix-family platforms and 7 | /// Windows. 8 | /// 9 | /// A wall clock is a clock which measures the date and time according to 10 | /// some external reference. 11 | /// 12 | /// External references may be reset, so this clock is not necessarily 13 | /// monotonic, making it unsuitable for measuring elapsed time. 14 | /// 15 | /// It is intended for reporting the current date and time for humans. 16 | interface wall-clock { 17 | /// A time and date in seconds plus nanoseconds. 18 | record datetime { 19 | seconds: u64, 20 | nanoseconds: u32, 21 | } 22 | 23 | /// Read the current value of the clock. 24 | /// 25 | /// This clock is not monotonic, therefore calling this function repeatedly 26 | /// will not necessarily produce a sequence of non-decreasing values. 27 | /// 28 | /// The returned timestamps represent the number of seconds since 29 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], 30 | /// also known as [Unix Time]. 31 | /// 32 | /// The nanoseconds field of the output is always less than 1000000000. 33 | /// 34 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 35 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time 36 | now: func() -> datetime; 37 | 38 | /// Query the resolution of the clock. 39 | /// 40 | /// The nanoseconds field of the output is always less than 1000000000. 41 | resolution: func() -> datetime; 42 | } 43 | -------------------------------------------------------------------------------- /wit/deps/clocks-2023-11-10/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.0-rc-2023-11-10; 2 | 3 | world imports { 4 | import monotonic-clock; 5 | import wall-clock; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/clocks/monotonic-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.0; 2 | /// WASI Monotonic Clock is a clock API intended to let users measure elapsed 3 | /// time. 4 | /// 5 | /// It is intended to be portable at least between Unix-family platforms and 6 | /// Windows. 7 | /// 8 | /// A monotonic clock is a clock which has an unspecified initial value, and 9 | /// successive reads of the clock will produce non-decreasing values. 10 | /// 11 | /// It is intended for measuring elapsed time. 12 | interface monotonic-clock { 13 | use wasi:io/poll@0.2.0.{pollable}; 14 | 15 | /// An instant in time, in nanoseconds. An instant is relative to an 16 | /// unspecified initial value, and can only be compared to instances from 17 | /// the same monotonic-clock. 18 | type instant = u64; 19 | 20 | /// A duration of time, in nanoseconds. 21 | type duration = u64; 22 | 23 | /// Read the current value of the clock. 24 | /// 25 | /// The clock is monotonic, therefore calling this function repeatedly will 26 | /// produce a sequence of non-decreasing values. 27 | now: func() -> instant; 28 | 29 | /// Query the resolution of the clock. Returns the duration of time 30 | /// corresponding to a clock tick. 31 | resolution: func() -> duration; 32 | 33 | /// Create a `pollable` which will resolve once the specified instant 34 | /// occured. 35 | subscribe-instant: func( 36 | when: instant, 37 | ) -> pollable; 38 | 39 | /// Create a `pollable` which will resolve once the given duration has 40 | /// elapsed, starting at the time at which this function was called. 41 | /// occured. 42 | subscribe-duration: func( 43 | when: duration, 44 | ) -> pollable; 45 | } 46 | -------------------------------------------------------------------------------- /wit/deps/clocks/wall-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.0; 2 | /// WASI Wall Clock is a clock API intended to let users query the current 3 | /// time. The name "wall" makes an analogy to a "clock on the wall", which 4 | /// is not necessarily monotonic as it may be reset. 5 | /// 6 | /// It is intended to be portable at least between Unix-family platforms and 7 | /// Windows. 8 | /// 9 | /// A wall clock is a clock which measures the date and time according to 10 | /// some external reference. 11 | /// 12 | /// External references may be reset, so this clock is not necessarily 13 | /// monotonic, making it unsuitable for measuring elapsed time. 14 | /// 15 | /// It is intended for reporting the current date and time for humans. 16 | interface wall-clock { 17 | /// A time and date in seconds plus nanoseconds. 18 | record datetime { 19 | seconds: u64, 20 | nanoseconds: u32, 21 | } 22 | 23 | /// Read the current value of the clock. 24 | /// 25 | /// This clock is not monotonic, therefore calling this function repeatedly 26 | /// will not necessarily produce a sequence of non-decreasing values. 27 | /// 28 | /// The returned timestamps represent the number of seconds since 29 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], 30 | /// also known as [Unix Time]. 31 | /// 32 | /// The nanoseconds field of the output is always less than 1000000000. 33 | /// 34 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 35 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time 36 | now: func() -> datetime; 37 | 38 | /// Query the resolution of the clock. 39 | /// 40 | /// The nanoseconds field of the output is always less than 1000000000. 41 | resolution: func() -> datetime; 42 | } 43 | -------------------------------------------------------------------------------- /wit/deps/clocks/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.0; 2 | 3 | world imports { 4 | import monotonic-clock; 5 | import wall-clock; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/filesystem-2023-10-18/preopens.wit: -------------------------------------------------------------------------------- 1 | interface preopens { 2 | use types.{descriptor}; 3 | 4 | /// Return the set of preopened directories, and their path. 5 | get-directories: func() -> list>; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/filesystem-2023-10-18/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.0-rc-2023-10-18; 2 | 3 | world imports { 4 | import types; 5 | import preopens; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/filesystem-2023-11-10/preopens.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.0-rc-2023-11-10; 2 | 3 | interface preopens { 4 | use types.{descriptor}; 5 | 6 | /// Return the set of preopened directories, and their path. 7 | get-directories: func() -> list>; 8 | } 9 | -------------------------------------------------------------------------------- /wit/deps/filesystem-2023-11-10/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.0-rc-2023-11-10; 2 | 3 | world imports { 4 | import types; 5 | import preopens; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/filesystem/preopens.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.0; 2 | 3 | interface preopens { 4 | use types.{descriptor}; 5 | 6 | /// Return the set of preopened directories, and their path. 7 | get-directories: func() -> list>; 8 | } 9 | -------------------------------------------------------------------------------- /wit/deps/filesystem/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.0; 2 | 3 | world imports { 4 | import types; 5 | import preopens; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/http-2023-10-18/incoming-handler.wit: -------------------------------------------------------------------------------- 1 | // The `wasi:http/incoming-handler` interface is meant to be exported by 2 | // components and called by the host in response to a new incoming HTTP 3 | // response. 4 | // 5 | // NOTE: in Preview3, this interface will be merged with 6 | // `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface 7 | // that takes a `request` parameter and returns a `response` result. 8 | // 9 | interface incoming-handler { 10 | use types.{incoming-request, response-outparam}; 11 | 12 | // The `handle` function takes an outparam instead of returning its response 13 | // so that the component may stream its response while streaming any other 14 | // request or response bodies. The callee MUST write a response to the 15 | // `response-outparam` and then finish the response before returning. The `handle` 16 | // function is allowed to continue execution after finishing the response's 17 | // output stream. While this post-response execution is taken off the 18 | // critical path, since there is no return value, there is no way to report 19 | // its success or failure. 20 | handle: func( 21 | request: incoming-request, 22 | response-out: response-outparam 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /wit/deps/http-2023-10-18/outgoing-handler.wit: -------------------------------------------------------------------------------- 1 | // The `wasi:http/outgoing-handler` interface is meant to be imported by 2 | // components and implemented by the host. 3 | // 4 | // NOTE: in Preview3, this interface will be merged with 5 | // `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface 6 | // that takes a `request` parameter and returns a `response` result. 7 | // 8 | interface outgoing-handler { 9 | use types.{outgoing-request, request-options, future-incoming-response, error}; 10 | 11 | // The parameter and result types of the `handle` function allow the caller 12 | // to concurrently stream the bodies of the outgoing request and the incoming 13 | // response. 14 | // Consumes the outgoing-request. Gives an error if the outgoing-request 15 | // is invalid or cannot be satisfied by this handler. 16 | handle: func( 17 | request: outgoing-request, 18 | options: option 19 | ) -> result; 20 | } 21 | -------------------------------------------------------------------------------- /wit/deps/http-2023-10-18/proxy.wit: -------------------------------------------------------------------------------- 1 | package wasi:http@0.2.0-rc-2023-10-18; 2 | 3 | // The `wasi:http/proxy` world captures a widely-implementable intersection of 4 | // hosts that includes HTTP forward and reverse proxies. Components targeting 5 | // this world may concurrently stream in and out any number of incoming and 6 | // outgoing HTTP requests. 7 | world proxy { 8 | // HTTP proxies have access to time and randomness. 9 | import wasi:clocks/wall-clock@0.2.0-rc-2023-10-18; 10 | import wasi:clocks/monotonic-clock@0.2.0-rc-2023-10-18; 11 | import wasi:clocks/timezone@0.2.0-rc-2023-10-18; 12 | import wasi:random/random@0.2.0-rc-2023-10-18; 13 | 14 | // Proxies have standard output and error streams which are expected to 15 | // terminate in a developer-facing console provided by the host. 16 | import wasi:cli/stdout@0.2.0-rc-2023-10-18; 17 | import wasi:cli/stderr@0.2.0-rc-2023-10-18; 18 | 19 | // TODO: this is a temporary workaround until component tooling is able to 20 | // gracefully handle the absence of stdin. Hosts must return an eof stream 21 | // for this import, which is what wasi-libc + tooling will do automatically 22 | // when this import is properly removed. 23 | import wasi:cli/stdin@0.2.0-rc-2023-10-18; 24 | 25 | // This is the default handler to use when user code simply wants to make an 26 | // HTTP request (e.g., via `fetch()`). 27 | import outgoing-handler; 28 | 29 | // The host delivers incoming HTTP requests to a component by calling the 30 | // `handle` function of this exported interface. A host may arbitrarily reuse 31 | // or not reuse component instance when delivering incoming HTTP requests and 32 | // thus a component must be able to handle 0..N calls to `handle`. 33 | export incoming-handler; 34 | } 35 | -------------------------------------------------------------------------------- /wit/deps/http-2023-11-10/handler.wit: -------------------------------------------------------------------------------- 1 | /// This interface defines a handler of incoming HTTP Requests. It should 2 | /// be exported by components which can respond to HTTP Requests. 3 | interface incoming-handler { 4 | use types.{incoming-request, response-outparam}; 5 | 6 | /// This function is invoked with an incoming HTTP Request, and a resource 7 | /// `response-outparam` which provides the capability to reply with an HTTP 8 | /// Response. The response is sent by calling the `response-outparam.set` 9 | /// method, which allows execution to continue after the response has been 10 | /// sent. This enables both streaming to the response body, and performing other 11 | /// work. 12 | /// 13 | /// The implementor of this function must write a response to the 14 | /// `response-outparam` before returning, or else the caller will respond 15 | /// with an error on its behalf. 16 | handle: func( 17 | request: incoming-request, 18 | response-out: response-outparam 19 | ); 20 | } 21 | 22 | /// This interface defines a handler of outgoing HTTP Requests. It should be 23 | /// imported by components which wish to make HTTP Requests. 24 | interface outgoing-handler { 25 | use types.{ 26 | outgoing-request, request-options, future-incoming-response, error-code 27 | }; 28 | 29 | /// This function is invoked with an outgoing HTTP Request, and it returns 30 | /// a resource `future-incoming-response` which represents an HTTP Response 31 | /// which may arrive in the future. 32 | /// 33 | /// The `options` argument accepts optional parameters for the HTTP 34 | /// protocol's transport layer. 35 | /// 36 | /// This function may return an error if the `outgoing-request` is invalid 37 | /// or not allowed to be made. Otherwise, protocol errors are reported 38 | /// through the `future-incoming-response`. 39 | handle: func( 40 | request: outgoing-request, 41 | options: option 42 | ) -> result; 43 | } 44 | -------------------------------------------------------------------------------- /wit/deps/http-2023-11-10/proxy.wit: -------------------------------------------------------------------------------- 1 | package wasi:http@0.2.0-rc-2023-11-10; 2 | 3 | /// The `wasi:http/proxy` world captures a widely-implementable intersection of 4 | /// hosts that includes HTTP forward and reverse proxies. Components targeting 5 | /// this world may concurrently stream in and out any number of incoming and 6 | /// outgoing HTTP requests. 7 | world proxy { 8 | /// HTTP proxies have access to time and randomness. 9 | import wasi:clocks/wall-clock@0.2.0-rc-2023-11-10; 10 | import wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10; 11 | import wasi:random/random@0.2.0-rc-2023-11-10; 12 | 13 | /// Proxies have standard output and error streams which are expected to 14 | /// terminate in a developer-facing console provided by the host. 15 | import wasi:cli/stdout@0.2.0-rc-2023-11-10; 16 | import wasi:cli/stderr@0.2.0-rc-2023-11-10; 17 | 18 | /// TODO: this is a temporary workaround until component tooling is able to 19 | /// gracefully handle the absence of stdin. Hosts must return an eof stream 20 | /// for this import, which is what wasi-libc + tooling will do automatically 21 | /// when this import is properly removed. 22 | import wasi:cli/stdin@0.2.0-rc-2023-11-10; 23 | 24 | /// This is the default handler to use when user code simply wants to make an 25 | /// HTTP request (e.g., via `fetch()`). 26 | import outgoing-handler; 27 | 28 | /// The host delivers incoming HTTP requests to a component by calling the 29 | /// `handle` function of this exported interface. A host may arbitrarily reuse 30 | /// or not reuse component instance when delivering incoming HTTP requests and 31 | /// thus a component must be able to handle 0..N calls to `handle`. 32 | export incoming-handler; 33 | } 34 | -------------------------------------------------------------------------------- /wit/deps/http/handler.wit: -------------------------------------------------------------------------------- 1 | /// This interface defines a handler of incoming HTTP Requests. It should 2 | /// be exported by components which can respond to HTTP Requests. 3 | interface incoming-handler { 4 | use types.{incoming-request, response-outparam}; 5 | 6 | /// This function is invoked with an incoming HTTP Request, and a resource 7 | /// `response-outparam` which provides the capability to reply with an HTTP 8 | /// Response. The response is sent by calling the `response-outparam.set` 9 | /// method, which allows execution to continue after the response has been 10 | /// sent. This enables both streaming to the response body, and performing other 11 | /// work. 12 | /// 13 | /// The implementor of this function must write a response to the 14 | /// `response-outparam` before returning, or else the caller will respond 15 | /// with an error on its behalf. 16 | handle: func( 17 | request: incoming-request, 18 | response-out: response-outparam 19 | ); 20 | } 21 | 22 | /// This interface defines a handler of outgoing HTTP Requests. It should be 23 | /// imported by components which wish to make HTTP Requests. 24 | interface outgoing-handler { 25 | use types.{ 26 | outgoing-request, request-options, future-incoming-response, error-code 27 | }; 28 | 29 | /// This function is invoked with an outgoing HTTP Request, and it returns 30 | /// a resource `future-incoming-response` which represents an HTTP Response 31 | /// which may arrive in the future. 32 | /// 33 | /// The `options` argument accepts optional parameters for the HTTP 34 | /// protocol's transport layer. 35 | /// 36 | /// This function may return an error if the `outgoing-request` is invalid 37 | /// or not allowed to be made. Otherwise, protocol errors are reported 38 | /// through the `future-incoming-response`. 39 | handle: func( 40 | request: outgoing-request, 41 | options: option 42 | ) -> result; 43 | } 44 | -------------------------------------------------------------------------------- /wit/deps/http/proxy.wit: -------------------------------------------------------------------------------- 1 | package wasi:http@0.2.0; 2 | 3 | /// The `wasi:http/proxy` world captures a widely-implementable intersection of 4 | /// hosts that includes HTTP forward and reverse proxies. Components targeting 5 | /// this world may concurrently stream in and out any number of incoming and 6 | /// outgoing HTTP requests. 7 | world proxy { 8 | /// HTTP proxies have access to time and randomness. 9 | include wasi:clocks/imports@0.2.0; 10 | import wasi:random/random@0.2.0; 11 | 12 | /// Proxies have standard output and error streams which are expected to 13 | /// terminate in a developer-facing console provided by the host. 14 | import wasi:cli/stdout@0.2.0; 15 | import wasi:cli/stderr@0.2.0; 16 | 17 | /// TODO: this is a temporary workaround until component tooling is able to 18 | /// gracefully handle the absence of stdin. Hosts must return an eof stream 19 | /// for this import, which is what wasi-libc + tooling will do automatically 20 | /// when this import is properly removed. 21 | import wasi:cli/stdin@0.2.0; 22 | 23 | /// This is the default handler to use when user code simply wants to make an 24 | /// HTTP request (e.g., via `fetch()`). 25 | import outgoing-handler; 26 | 27 | /// The host delivers incoming HTTP requests to a component by calling the 28 | /// `handle` function of this exported interface. A host may arbitrarily reuse 29 | /// or not reuse component instance when delivering incoming HTTP requests and 30 | /// thus a component must be able to handle 0..N calls to `handle`. 31 | export incoming-handler; 32 | } 33 | -------------------------------------------------------------------------------- /wit/deps/io-2023-10-18/poll.wit: -------------------------------------------------------------------------------- 1 | /// A poll API intended to let users wait for I/O events on multiple handles 2 | /// at once. 3 | interface poll { 4 | /// A "pollable" handle. 5 | resource pollable; 6 | 7 | /// Poll for completion on a set of pollables. 8 | /// 9 | /// This function takes a list of pollables, which identify I/O sources of 10 | /// interest, and waits until one or more of the events is ready for I/O. 11 | /// 12 | /// The result `list` contains one or more indices of handles in the 13 | /// argument list that is ready for I/O. 14 | /// 15 | /// If the list contains more elements than can be indexed with a `u32` 16 | /// value, this function traps. 17 | /// 18 | /// A timeout can be implemented by adding a pollable from the 19 | /// wasi-clocks API to the list. 20 | /// 21 | /// This function does not return a `result`; polling in itself does not 22 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 23 | /// the pollables has an error, it is indicated by marking the source as 24 | /// being reaedy for I/O. 25 | poll-list: func(in: list>) -> list; 26 | 27 | /// Poll for completion on a single pollable. 28 | /// 29 | /// This function is similar to `poll-list`, but operates on only a single 30 | /// pollable. When it returns, the handle is ready for I/O. 31 | poll-one: func(in: borrow); 32 | } 33 | -------------------------------------------------------------------------------- /wit/deps/io-2023-10-18/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0-rc-2023-10-18; 2 | -------------------------------------------------------------------------------- /wit/deps/io-2023-11-10/error.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0-rc-2023-11-10; 2 | 3 | 4 | interface error { 5 | /// A resource which represents some error information. 6 | /// 7 | /// The only method provided by this resource is `to-debug-string`, 8 | /// which provides some human-readable information about the error. 9 | /// 10 | /// In the `wasi:io` package, this resource is returned through the 11 | /// `wasi:io/streams/stream-error` type. 12 | /// 13 | /// To provide more specific error information, other interfaces may 14 | /// provide functions to further "downcast" this error into more specific 15 | /// error information. For example, `error`s returned in streams derived 16 | /// from filesystem types to be described using the filesystem's own 17 | /// error-code type, using the function 18 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter 19 | /// `borrow` and returns 20 | /// `option`. 21 | /// 22 | /// The set of functions which can "downcast" an `error` into a more 23 | /// concrete type is open. 24 | resource error { 25 | /// Returns a string that is suitable to assist humans in debugging 26 | /// this error. 27 | /// 28 | /// WARNING: The returned string should not be consumed mechanically! 29 | /// It may change across platforms, hosts, or other implementation 30 | /// details. Parsing this string is a major platform-compatibility 31 | /// hazard. 32 | to-debug-string: func() -> string; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wit/deps/io-2023-11-10/poll.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0-rc-2023-11-10; 2 | 3 | /// A poll API intended to let users wait for I/O events on multiple handles 4 | /// at once. 5 | interface poll { 6 | /// `pollable` epresents a single I/O event which may be ready, or not. 7 | resource pollable { 8 | 9 | /// Return the readiness of a pollable. This function never blocks. 10 | /// 11 | /// Returns `true` when the pollable is ready, and `false` otherwise. 12 | ready: func() -> bool; 13 | 14 | /// `block` returns immediately if the pollable is ready, and otherwise 15 | /// blocks until ready. 16 | /// 17 | /// This function is equivalent to calling `poll.poll` on a list 18 | /// containing only this pollable. 19 | block: func(); 20 | } 21 | 22 | /// Poll for completion on a set of pollables. 23 | /// 24 | /// This function takes a list of pollables, which identify I/O sources of 25 | /// interest, and waits until one or more of the events is ready for I/O. 26 | /// 27 | /// The result `list` contains one or more indices of handles in the 28 | /// argument list that is ready for I/O. 29 | /// 30 | /// If the list contains more elements than can be indexed with a `u32` 31 | /// value, this function traps. 32 | /// 33 | /// A timeout can be implemented by adding a pollable from the 34 | /// wasi-clocks API to the list. 35 | /// 36 | /// This function does not return a `result`; polling in itself does not 37 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 38 | /// the pollables has an error, it is indicated by marking the source as 39 | /// being reaedy for I/O. 40 | poll: func(in: list>) -> list; 41 | } 42 | -------------------------------------------------------------------------------- /wit/deps/io-2023-11-10/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0-rc-2023-11-10; 2 | 3 | world imports { 4 | import streams; 5 | import poll; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/io/error.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | 4 | interface error { 5 | /// A resource which represents some error information. 6 | /// 7 | /// The only method provided by this resource is `to-debug-string`, 8 | /// which provides some human-readable information about the error. 9 | /// 10 | /// In the `wasi:io` package, this resource is returned through the 11 | /// `wasi:io/streams/stream-error` type. 12 | /// 13 | /// To provide more specific error information, other interfaces may 14 | /// provide functions to further "downcast" this error into more specific 15 | /// error information. For example, `error`s returned in streams derived 16 | /// from filesystem types to be described using the filesystem's own 17 | /// error-code type, using the function 18 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter 19 | /// `borrow` and returns 20 | /// `option`. 21 | /// 22 | /// The set of functions which can "downcast" an `error` into a more 23 | /// concrete type is open. 24 | resource error { 25 | /// Returns a string that is suitable to assist humans in debugging 26 | /// this error. 27 | /// 28 | /// WARNING: The returned string should not be consumed mechanically! 29 | /// It may change across platforms, hosts, or other implementation 30 | /// details. Parsing this string is a major platform-compatibility 31 | /// hazard. 32 | to-debug-string: func() -> string; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wit/deps/io/poll.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | /// A poll API intended to let users wait for I/O events on multiple handles 4 | /// at once. 5 | interface poll { 6 | /// `pollable` represents a single I/O event which may be ready, or not. 7 | resource pollable { 8 | 9 | /// Return the readiness of a pollable. This function never blocks. 10 | /// 11 | /// Returns `true` when the pollable is ready, and `false` otherwise. 12 | ready: func() -> bool; 13 | 14 | /// `block` returns immediately if the pollable is ready, and otherwise 15 | /// blocks until ready. 16 | /// 17 | /// This function is equivalent to calling `poll.poll` on a list 18 | /// containing only this pollable. 19 | block: func(); 20 | } 21 | 22 | /// Poll for completion on a set of pollables. 23 | /// 24 | /// This function takes a list of pollables, which identify I/O sources of 25 | /// interest, and waits until one or more of the events is ready for I/O. 26 | /// 27 | /// The result `list` contains one or more indices of handles in the 28 | /// argument list that is ready for I/O. 29 | /// 30 | /// If the list contains more elements than can be indexed with a `u32` 31 | /// value, this function traps. 32 | /// 33 | /// A timeout can be implemented by adding a pollable from the 34 | /// wasi-clocks API to the list. 35 | /// 36 | /// This function does not return a `result`; polling in itself does not 37 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 38 | /// the pollables has an error, it is indicated by marking the source as 39 | /// being reaedy for I/O. 40 | poll: func(in: list>) -> list; 41 | } 42 | -------------------------------------------------------------------------------- /wit/deps/io/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.0; 2 | 3 | world imports { 4 | import streams; 5 | import poll; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/random-2023-10-18/insecure-seed.wit: -------------------------------------------------------------------------------- 1 | /// The insecure-seed interface for seeding hash-map DoS resistance. 2 | /// 3 | /// It is intended to be portable at least between Unix-family platforms and 4 | /// Windows. 5 | interface insecure-seed { 6 | /// Return a 128-bit value that may contain a pseudo-random value. 7 | /// 8 | /// The returned value is not required to be computed from a CSPRNG, and may 9 | /// even be entirely deterministic. Host implementations are encouraged to 10 | /// provide pseudo-random values to any program exposed to 11 | /// attacker-controlled content, to enable DoS protection built into many 12 | /// languages' hash-map implementations. 13 | /// 14 | /// This function is intended to only be called once, by a source language 15 | /// to initialize Denial Of Service (DoS) protection in its hash-map 16 | /// implementation. 17 | /// 18 | /// # Expected future evolution 19 | /// 20 | /// This will likely be changed to a value import, to prevent it from being 21 | /// called multiple times and potentially used for purposes other than DoS 22 | /// protection. 23 | insecure-seed: func() -> tuple; 24 | } 25 | -------------------------------------------------------------------------------- /wit/deps/random-2023-10-18/insecure.wit: -------------------------------------------------------------------------------- 1 | /// The insecure interface for insecure pseudo-random numbers. 2 | /// 3 | /// It is intended to be portable at least between Unix-family platforms and 4 | /// Windows. 5 | interface insecure { 6 | /// Return `len` insecure pseudo-random bytes. 7 | /// 8 | /// This function is not cryptographically secure. Do not use it for 9 | /// anything related to security. 10 | /// 11 | /// There are no requirements on the values of the returned bytes, however 12 | /// implementations are encouraged to return evenly distributed values with 13 | /// a long period. 14 | get-insecure-random-bytes: func(len: u64) -> list; 15 | 16 | /// Return an insecure pseudo-random `u64` value. 17 | /// 18 | /// This function returns the same type of pseudo-random data as 19 | /// `get-insecure-random-bytes`, represented as a `u64`. 20 | get-insecure-random-u64: func() -> u64; 21 | } 22 | -------------------------------------------------------------------------------- /wit/deps/random-2023-10-18/random.wit: -------------------------------------------------------------------------------- 1 | /// WASI Random is a random data API. 2 | /// 3 | /// It is intended to be portable at least between Unix-family platforms and 4 | /// Windows. 5 | interface random { 6 | /// Return `len` cryptographically-secure random or pseudo-random bytes. 7 | /// 8 | /// This function must produce data at least as cryptographically secure and 9 | /// fast as an adequately seeded cryptographically-secure pseudo-random 10 | /// number generator (CSPRNG). It must not block, from the perspective of 11 | /// the calling program, under any circumstances, including on the first 12 | /// request and on requests for numbers of bytes. The returned data must 13 | /// always be unpredictable. 14 | /// 15 | /// This function must always return fresh data. Deterministic environments 16 | /// must omit this function, rather than implementing it with deterministic 17 | /// data. 18 | get-random-bytes: func(len: u64) -> list; 19 | 20 | /// Return a cryptographically-secure random or pseudo-random `u64` value. 21 | /// 22 | /// This function returns the same type of data as `get-random-bytes`, 23 | /// represented as a `u64`. 24 | get-random-u64: func() -> u64; 25 | } 26 | -------------------------------------------------------------------------------- /wit/deps/random-2023-10-18/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0-rc-2023-10-18; 2 | 3 | world imports { 4 | import random; 5 | import insecure; 6 | import insecure-seed; 7 | } 8 | -------------------------------------------------------------------------------- /wit/deps/random-2023-11-10/insecure-seed.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0-rc-2023-11-10; 2 | /// The insecure-seed interface for seeding hash-map DoS resistance. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | interface insecure-seed { 7 | /// Return a 128-bit value that may contain a pseudo-random value. 8 | /// 9 | /// The returned value is not required to be computed from a CSPRNG, and may 10 | /// even be entirely deterministic. Host implementations are encouraged to 11 | /// provide pseudo-random values to any program exposed to 12 | /// attacker-controlled content, to enable DoS protection built into many 13 | /// languages' hash-map implementations. 14 | /// 15 | /// This function is intended to only be called once, by a source language 16 | /// to initialize Denial Of Service (DoS) protection in its hash-map 17 | /// implementation. 18 | /// 19 | /// # Expected future evolution 20 | /// 21 | /// This will likely be changed to a value import, to prevent it from being 22 | /// called multiple times and potentially used for purposes other than DoS 23 | /// protection. 24 | insecure-seed: func() -> tuple; 25 | } 26 | -------------------------------------------------------------------------------- /wit/deps/random-2023-11-10/insecure.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0-rc-2023-11-10; 2 | /// The insecure interface for insecure pseudo-random numbers. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | interface insecure { 7 | /// Return `len` insecure pseudo-random bytes. 8 | /// 9 | /// This function is not cryptographically secure. Do not use it for 10 | /// anything related to security. 11 | /// 12 | /// There are no requirements on the values of the returned bytes, however 13 | /// implementations are encouraged to return evenly distributed values with 14 | /// a long period. 15 | get-insecure-random-bytes: func(len: u64) -> list; 16 | 17 | /// Return an insecure pseudo-random `u64` value. 18 | /// 19 | /// This function returns the same type of pseudo-random data as 20 | /// `get-insecure-random-bytes`, represented as a `u64`. 21 | get-insecure-random-u64: func() -> u64; 22 | } 23 | -------------------------------------------------------------------------------- /wit/deps/random-2023-11-10/random.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0-rc-2023-11-10; 2 | /// WASI Random is a random data API. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | interface random { 7 | /// Return `len` cryptographically-secure random or pseudo-random bytes. 8 | /// 9 | /// This function must produce data at least as cryptographically secure and 10 | /// fast as an adequately seeded cryptographically-secure pseudo-random 11 | /// number generator (CSPRNG). It must not block, from the perspective of 12 | /// the calling program, under any circumstances, including on the first 13 | /// request and on requests for numbers of bytes. The returned data must 14 | /// always be unpredictable. 15 | /// 16 | /// This function must always return fresh data. Deterministic environments 17 | /// must omit this function, rather than implementing it with deterministic 18 | /// data. 19 | get-random-bytes: func(len: u64) -> list; 20 | 21 | /// Return a cryptographically-secure random or pseudo-random `u64` value. 22 | /// 23 | /// This function returns the same type of data as `get-random-bytes`, 24 | /// represented as a `u64`. 25 | get-random-u64: func() -> u64; 26 | } 27 | -------------------------------------------------------------------------------- /wit/deps/random-2023-11-10/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0-rc-2023-11-10; 2 | 3 | world imports { 4 | import random; 5 | import insecure; 6 | import insecure-seed; 7 | } 8 | -------------------------------------------------------------------------------- /wit/deps/random/insecure-seed.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0; 2 | /// The insecure-seed interface for seeding hash-map DoS resistance. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | interface insecure-seed { 7 | /// Return a 128-bit value that may contain a pseudo-random value. 8 | /// 9 | /// The returned value is not required to be computed from a CSPRNG, and may 10 | /// even be entirely deterministic. Host implementations are encouraged to 11 | /// provide pseudo-random values to any program exposed to 12 | /// attacker-controlled content, to enable DoS protection built into many 13 | /// languages' hash-map implementations. 14 | /// 15 | /// This function is intended to only be called once, by a source language 16 | /// to initialize Denial Of Service (DoS) protection in its hash-map 17 | /// implementation. 18 | /// 19 | /// # Expected future evolution 20 | /// 21 | /// This will likely be changed to a value import, to prevent it from being 22 | /// called multiple times and potentially used for purposes other than DoS 23 | /// protection. 24 | insecure-seed: func() -> tuple; 25 | } 26 | -------------------------------------------------------------------------------- /wit/deps/random/insecure.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0; 2 | /// The insecure interface for insecure pseudo-random numbers. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | interface insecure { 7 | /// Return `len` insecure pseudo-random bytes. 8 | /// 9 | /// This function is not cryptographically secure. Do not use it for 10 | /// anything related to security. 11 | /// 12 | /// There are no requirements on the values of the returned bytes, however 13 | /// implementations are encouraged to return evenly distributed values with 14 | /// a long period. 15 | get-insecure-random-bytes: func(len: u64) -> list; 16 | 17 | /// Return an insecure pseudo-random `u64` value. 18 | /// 19 | /// This function returns the same type of pseudo-random data as 20 | /// `get-insecure-random-bytes`, represented as a `u64`. 21 | get-insecure-random-u64: func() -> u64; 22 | } 23 | -------------------------------------------------------------------------------- /wit/deps/random/random.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0; 2 | /// WASI Random is a random data API. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | interface random { 7 | /// Return `len` cryptographically-secure random or pseudo-random bytes. 8 | /// 9 | /// This function must produce data at least as cryptographically secure and 10 | /// fast as an adequately seeded cryptographically-secure pseudo-random 11 | /// number generator (CSPRNG). It must not block, from the perspective of 12 | /// the calling program, under any circumstances, including on the first 13 | /// request and on requests for numbers of bytes. The returned data must 14 | /// always be unpredictable. 15 | /// 16 | /// This function must always return fresh data. Deterministic environments 17 | /// must omit this function, rather than implementing it with deterministic 18 | /// data. 19 | get-random-bytes: func(len: u64) -> list; 20 | 21 | /// Return a cryptographically-secure random or pseudo-random `u64` value. 22 | /// 23 | /// This function returns the same type of data as `get-random-bytes`, 24 | /// represented as a `u64`. 25 | get-random-u64: func() -> u64; 26 | } 27 | -------------------------------------------------------------------------------- /wit/deps/random/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.0; 2 | 3 | world imports { 4 | import random; 5 | import insecure; 6 | import insecure-seed; 7 | } 8 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-10-18/instance-network.wit: -------------------------------------------------------------------------------- 1 | 2 | /// This interface provides a value-export of the default network handle.. 3 | interface instance-network { 4 | use network.{network}; 5 | 6 | /// Get a handle to the default network. 7 | instance-network: func() -> network; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-10-18/ip-name-lookup.wit: -------------------------------------------------------------------------------- 1 | 2 | interface ip-name-lookup { 3 | use wasi:io/poll@0.2.0-rc-2023-10-18.{pollable}; 4 | use network.{network, error-code, ip-address, ip-address-family}; 5 | 6 | 7 | /// Resolve an internet host name to a list of IP addresses. 8 | /// 9 | /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. 10 | /// 11 | /// # Parameters 12 | /// - `name`: The name to look up. IP addresses are not allowed. Unicode domain names are automatically converted 13 | /// to ASCII using IDNA encoding. 14 | /// - `address-family`: If provided, limit the results to addresses of this specific address family. 15 | /// - `include-unavailable`: When set to true, this function will also return addresses of which the runtime 16 | /// thinks (or knows) can't be connected to at the moment. For example, this will return IPv6 addresses on 17 | /// systems without an active IPv6 interface. Notes: 18 | /// - Even when no public IPv6 interfaces are present or active, names like "localhost" can still resolve to an IPv6 address. 19 | /// - Whatever is "available" or "unavailable" is volatile and can change everytime a network cable is unplugged. 20 | /// 21 | /// This function never blocks. It either immediately fails or immediately returns successfully with a `resolve-address-stream` 22 | /// that can be used to (asynchronously) fetch the results. 23 | /// 24 | /// At the moment, the stream never completes successfully with 0 items. Ie. the first call 25 | /// to `resolve-next-address` never returns `ok(none)`. This may change in the future. 26 | /// 27 | /// # Typical errors 28 | /// - `invalid-argument`: `name` is a syntactically invalid domain name. 29 | /// - `invalid-argument`: `name` is an IP address. 30 | /// - `not-supported`: The specified `address-family` is not supported. (EAI_FAMILY) 31 | /// 32 | /// # References: 33 | /// - 34 | /// - 35 | /// - 36 | /// - 37 | resolve-addresses: func(network: borrow, name: string, address-family: option, include-unavailable: bool) -> result; 38 | 39 | resource resolve-address-stream { 40 | /// Returns the next address from the resolver. 41 | /// 42 | /// This function should be called multiple times. On each call, it will 43 | /// return the next address in connection order preference. If all 44 | /// addresses have been exhausted, this function returns `none`. 45 | /// 46 | /// This function never returns IPv4-mapped IPv6 addresses. 47 | /// 48 | /// # Typical errors 49 | /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) 50 | /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) 51 | /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) 52 | /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) 53 | resolve-next-address: func() -> result, error-code>; 54 | 55 | /// Create a `pollable` which will resolve once the stream is ready for I/O. 56 | /// 57 | /// Note: this function is here for WASI Preview2 only. 58 | /// It's planned to be removed when `future` is natively supported in Preview3. 59 | subscribe: func() -> pollable; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-10-18/tcp-create-socket.wit: -------------------------------------------------------------------------------- 1 | 2 | interface tcp-create-socket { 3 | use network.{network, error-code, ip-address-family}; 4 | use tcp.{tcp-socket}; 5 | 6 | /// Create a new TCP socket. 7 | /// 8 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. 9 | /// 10 | /// This function does not require a network capability handle. This is considered to be safe because 11 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`listen`/`connect` 12 | /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 13 | /// 14 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 15 | /// 16 | /// # Typical errors 17 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 18 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 19 | /// 20 | /// # References 21 | /// - 22 | /// - 23 | /// - 24 | /// - 25 | create-tcp-socket: func(address-family: ip-address-family) -> result; 26 | } 27 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-10-18/udp-create-socket.wit: -------------------------------------------------------------------------------- 1 | 2 | interface udp-create-socket { 3 | use network.{network, error-code, ip-address-family}; 4 | use udp.{udp-socket}; 5 | 6 | /// Create a new UDP socket. 7 | /// 8 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. 9 | /// 10 | /// This function does not require a network capability handle. This is considered to be safe because 11 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` is called, 12 | /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 13 | /// 14 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 15 | /// 16 | /// # Typical errors 17 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 18 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 19 | /// 20 | /// # References: 21 | /// - 22 | /// - 23 | /// - 24 | /// - 25 | create-udp-socket: func(address-family: ip-address-family) -> result; 26 | } 27 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-10-18/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:sockets@0.2.0-rc-2023-10-18; 2 | 3 | world imports { 4 | import instance-network; 5 | import network; 6 | import udp; 7 | import udp-create-socket; 8 | import tcp; 9 | import tcp-create-socket; 10 | import ip-name-lookup; 11 | } 12 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-11-10/instance-network.wit: -------------------------------------------------------------------------------- 1 | 2 | /// This interface provides a value-export of the default network handle.. 3 | interface instance-network { 4 | use network.{network}; 5 | 6 | /// Get a handle to the default network. 7 | instance-network: func() -> network; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-11-10/ip-name-lookup.wit: -------------------------------------------------------------------------------- 1 | 2 | interface ip-name-lookup { 3 | use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable}; 4 | use network.{network, error-code, ip-address}; 5 | 6 | 7 | /// Resolve an internet host name to a list of IP addresses. 8 | /// 9 | /// Unicode domain names are automatically converted to ASCII using IDNA encoding. 10 | /// If the input is an IP address string, the address is parsed and returned 11 | /// as-is without making any external requests. 12 | /// 13 | /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. 14 | /// 15 | /// This function never blocks. It either immediately fails or immediately 16 | /// returns successfully with a `resolve-address-stream` that can be used 17 | /// to (asynchronously) fetch the results. 18 | /// 19 | /// # Typical errors 20 | /// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address. 21 | /// 22 | /// # References: 23 | /// - 24 | /// - 25 | /// - 26 | /// - 27 | resolve-addresses: func(network: borrow, name: string) -> result; 28 | 29 | resource resolve-address-stream { 30 | /// Returns the next address from the resolver. 31 | /// 32 | /// This function should be called multiple times. On each call, it will 33 | /// return the next address in connection order preference. If all 34 | /// addresses have been exhausted, this function returns `none`. 35 | /// 36 | /// This function never returns IPv4-mapped IPv6 addresses. 37 | /// 38 | /// # Typical errors 39 | /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) 40 | /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) 41 | /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) 42 | /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) 43 | resolve-next-address: func() -> result, error-code>; 44 | 45 | /// Create a `pollable` which will resolve once the stream is ready for I/O. 46 | /// 47 | /// Note: this function is here for WASI Preview2 only. 48 | /// It's planned to be removed when `future` is natively supported in Preview3. 49 | subscribe: func() -> pollable; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-11-10/tcp-create-socket.wit: -------------------------------------------------------------------------------- 1 | 2 | interface tcp-create-socket { 3 | use network.{network, error-code, ip-address-family}; 4 | use tcp.{tcp-socket}; 5 | 6 | /// Create a new TCP socket. 7 | /// 8 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. 9 | /// 10 | /// This function does not require a network capability handle. This is considered to be safe because 11 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`listen`/`connect` 12 | /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 13 | /// 14 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 15 | /// 16 | /// # Typical errors 17 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 18 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 19 | /// 20 | /// # References 21 | /// - 22 | /// - 23 | /// - 24 | /// - 25 | create-tcp-socket: func(address-family: ip-address-family) -> result; 26 | } 27 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-11-10/udp-create-socket.wit: -------------------------------------------------------------------------------- 1 | 2 | interface udp-create-socket { 3 | use network.{network, error-code, ip-address-family}; 4 | use udp.{udp-socket}; 5 | 6 | /// Create a new UDP socket. 7 | /// 8 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. 9 | /// 10 | /// This function does not require a network capability handle. This is considered to be safe because 11 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, 12 | /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 13 | /// 14 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 15 | /// 16 | /// # Typical errors 17 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 18 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 19 | /// 20 | /// # References: 21 | /// - 22 | /// - 23 | /// - 24 | /// - 25 | create-udp-socket: func(address-family: ip-address-family) -> result; 26 | } 27 | -------------------------------------------------------------------------------- /wit/deps/sockets-2023-11-10/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:sockets@0.2.0-rc-2023-11-10; 2 | 3 | world imports { 4 | import instance-network; 5 | import network; 6 | import udp; 7 | import udp-create-socket; 8 | import tcp; 9 | import tcp-create-socket; 10 | import ip-name-lookup; 11 | } 12 | -------------------------------------------------------------------------------- /wit/deps/sockets/instance-network.wit: -------------------------------------------------------------------------------- 1 | 2 | /// This interface provides a value-export of the default network handle.. 3 | interface instance-network { 4 | use network.{network}; 5 | 6 | /// Get a handle to the default network. 7 | instance-network: func() -> network; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /wit/deps/sockets/ip-name-lookup.wit: -------------------------------------------------------------------------------- 1 | 2 | interface ip-name-lookup { 3 | use wasi:io/poll@0.2.0.{pollable}; 4 | use network.{network, error-code, ip-address}; 5 | 6 | 7 | /// Resolve an internet host name to a list of IP addresses. 8 | /// 9 | /// Unicode domain names are automatically converted to ASCII using IDNA encoding. 10 | /// If the input is an IP address string, the address is parsed and returned 11 | /// as-is without making any external requests. 12 | /// 13 | /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. 14 | /// 15 | /// This function never blocks. It either immediately fails or immediately 16 | /// returns successfully with a `resolve-address-stream` that can be used 17 | /// to (asynchronously) fetch the results. 18 | /// 19 | /// # Typical errors 20 | /// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address. 21 | /// 22 | /// # References: 23 | /// - 24 | /// - 25 | /// - 26 | /// - 27 | resolve-addresses: func(network: borrow, name: string) -> result; 28 | 29 | resource resolve-address-stream { 30 | /// Returns the next address from the resolver. 31 | /// 32 | /// This function should be called multiple times. On each call, it will 33 | /// return the next address in connection order preference. If all 34 | /// addresses have been exhausted, this function returns `none`. 35 | /// 36 | /// This function never returns IPv4-mapped IPv6 addresses. 37 | /// 38 | /// # Typical errors 39 | /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) 40 | /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) 41 | /// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) 42 | /// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) 43 | resolve-next-address: func() -> result, error-code>; 44 | 45 | /// Create a `pollable` which will resolve once the stream is ready for I/O. 46 | /// 47 | /// Note: this function is here for WASI Preview2 only. 48 | /// It's planned to be removed when `future` is natively supported in Preview3. 49 | subscribe: func() -> pollable; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /wit/deps/sockets/tcp-create-socket.wit: -------------------------------------------------------------------------------- 1 | 2 | interface tcp-create-socket { 3 | use network.{network, error-code, ip-address-family}; 4 | use tcp.{tcp-socket}; 5 | 6 | /// Create a new TCP socket. 7 | /// 8 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. 9 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 10 | /// 11 | /// This function does not require a network capability handle. This is considered to be safe because 12 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` 13 | /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 14 | /// 15 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 16 | /// 17 | /// # Typical errors 18 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 19 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 20 | /// 21 | /// # References 22 | /// - 23 | /// - 24 | /// - 25 | /// - 26 | create-tcp-socket: func(address-family: ip-address-family) -> result; 27 | } 28 | -------------------------------------------------------------------------------- /wit/deps/sockets/udp-create-socket.wit: -------------------------------------------------------------------------------- 1 | 2 | interface udp-create-socket { 3 | use network.{network, error-code, ip-address-family}; 4 | use udp.{udp-socket}; 5 | 6 | /// Create a new UDP socket. 7 | /// 8 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. 9 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 10 | /// 11 | /// This function does not require a network capability handle. This is considered to be safe because 12 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, 13 | /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 14 | /// 15 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 16 | /// 17 | /// # Typical errors 18 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 19 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 20 | /// 21 | /// # References: 22 | /// - 23 | /// - 24 | /// - 25 | /// - 26 | create-udp-socket: func(address-family: ip-address-family) -> result; 27 | } 28 | -------------------------------------------------------------------------------- /wit/deps/sockets/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:sockets@0.2.0; 2 | 3 | world imports { 4 | import instance-network; 5 | import network; 6 | import udp; 7 | import udp-create-socket; 8 | import tcp; 9 | import tcp-create-socket; 10 | import ip-name-lookup; 11 | } 12 | -------------------------------------------------------------------------------- /wit/deps/spin/key-value.wit: -------------------------------------------------------------------------------- 1 | interface key-value { 2 | /// An open key-value store 3 | resource store { 4 | /// Open the store with the specified label. 5 | /// 6 | /// `label` must refer to a store allowed in the spin.toml manifest. 7 | /// 8 | /// `error::no-such-store` will be raised if the `label` is not recognized. 9 | open: static func(label: string) -> result; 10 | 11 | /// Get the value associated with the specified `key` 12 | /// 13 | /// Returns `ok(none)` if the key does not exist. 14 | get: func(key: string) -> result>, error>; 15 | 16 | /// Set the `value` associated with the specified `key` overwriting any existing value. 17 | set: func(key: string, value: list) -> result<_, error>; 18 | 19 | /// Delete the tuple with the specified `key` 20 | /// 21 | /// No error is raised if a tuple did not previously exist for `key`. 22 | delete: func(key: string) -> result<_, error>; 23 | 24 | /// Return whether a tuple exists for the specified `key` 25 | exists: func(key: string) -> result; 26 | 27 | /// Return a list of all the keys 28 | get-keys: func() -> result, error>; 29 | } 30 | 31 | /// The set of errors which may be raised by functions in this interface 32 | variant error { 33 | /// Too many stores have been opened simultaneously. Closing one or more 34 | /// stores prior to retrying may address this. 35 | store-table-full, 36 | 37 | /// The host does not recognize the store label requested. 38 | no-such-store, 39 | 40 | /// The requesting component does not have access to the specified store 41 | /// (which may or may not exist). 42 | access-denied, 43 | 44 | /// Some implementation-specific error has occurred (e.g. I/O) 45 | other(string) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /wit/deps/spin/llm.wit: -------------------------------------------------------------------------------- 1 | // A WASI interface dedicated to performing inferencing for Large Language Models. 2 | interface llm { 3 | /// A Large Language Model. 4 | type inferencing-model = string; 5 | 6 | /// Inference request parameters 7 | record inferencing-params { 8 | /// The maximum tokens that should be inferred. 9 | /// 10 | /// Note: the backing implementation may return less tokens. 11 | max-tokens: u32, 12 | /// The amount the model should avoid repeating tokens. 13 | repeat-penalty: float32, 14 | /// The number of tokens the model should apply the repeat penalty to. 15 | repeat-penalty-last-n-token-count: u32, 16 | /// The randomness with which the next token is selected. 17 | temperature: float32, 18 | /// The number of possible next tokens the model will choose from. 19 | top-k: u32, 20 | /// The probability total of next tokens the model will choose from. 21 | top-p: float32 22 | } 23 | 24 | /// The set of errors which may be raised by functions in this interface 25 | variant error { 26 | model-not-supported, 27 | runtime-error(string), 28 | invalid-input(string) 29 | } 30 | 31 | /// An inferencing result 32 | record inferencing-result { 33 | /// The text generated by the model 34 | // TODO: this should be a stream 35 | text: string, 36 | /// Usage information about the inferencing request 37 | usage: inferencing-usage 38 | } 39 | 40 | /// Usage information related to the inferencing result 41 | record inferencing-usage { 42 | /// Number of tokens in the prompt 43 | prompt-token-count: u32, 44 | /// Number of tokens generated by the inferencing operation 45 | generated-token-count: u32 46 | } 47 | 48 | /// Perform inferencing using the provided model and prompt with the given optional params 49 | infer: func(model: inferencing-model, prompt: string, params: option) -> result; 50 | 51 | /// The model used for generating embeddings 52 | type embedding-model = string; 53 | 54 | /// Generate embeddings for the supplied list of text 55 | generate-embeddings: func(model: embedding-model, text: list) -> result; 56 | 57 | /// Result of generating embeddings 58 | record embeddings-result { 59 | /// The embeddings generated by the request 60 | embeddings: list>, 61 | /// Usage related to the embeddings generation request 62 | usage: embeddings-usage 63 | } 64 | 65 | /// Usage related to an embeddings generation request 66 | record embeddings-usage { 67 | /// Number of tokens in the prompt 68 | prompt-token-count: u32, 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /wit/deps/spin/mqtt.wit: -------------------------------------------------------------------------------- 1 | interface mqtt { 2 | /// Errors related to interacting with Mqtt 3 | variant error { 4 | /// An invalid address string 5 | invalid-address, 6 | /// There are too many open connections 7 | too-many-connections, 8 | /// Connection failure e.g. address not allowed. 9 | connection-failed(string), 10 | /// Some other error occurred 11 | other(string), 12 | } 13 | 14 | /// QoS for publishing Mqtt messages 15 | enum qos { 16 | at-most-once, 17 | at-least-once, 18 | exactly-once, 19 | } 20 | 21 | resource connection { 22 | /// Open a connection to the Mqtt instance at `address`. 23 | open: static func(address: string, username: string, password: string, keep-alive-interval-in-secs: u64) -> result; 24 | 25 | /// Publish an Mqtt message to the specified `topic`. 26 | publish: func(topic: string, payload: payload, qos: qos) -> result<_, error>; 27 | } 28 | 29 | /// The message payload. 30 | type payload = list; 31 | } 32 | -------------------------------------------------------------------------------- /wit/deps/spin/mysql.wit: -------------------------------------------------------------------------------- 1 | interface mysql { 2 | use rdbms-types.{parameter-value, row-set, error}; 3 | 4 | /// A connection to a MySQL database. 5 | resource connection { 6 | /// Open a connection to the MySQL instance at `address`. 7 | open: static func(address: string) -> result; 8 | 9 | /// query the database: select 10 | query: func(statement: string, params: list) -> result; 11 | 12 | /// execute command to the database: insert, update, delete 13 | execute: func(statement: string, params: list) -> result<_, error>; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /wit/deps/spin/postgres.wit: -------------------------------------------------------------------------------- 1 | interface postgres { 2 | use rdbms-types.{parameter-value, row-set, error}; 3 | 4 | /// A connection to a postgres database. 5 | resource connection { 6 | /// Open a connection to the Postgres instance at `address`. 7 | open: static func(address: string) -> result; 8 | 9 | /// Query the database. 10 | query: func(statement: string, params: list) -> result; 11 | 12 | /// Execute command to the database. 13 | execute: func(statement: string, params: list) -> result; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /wit/deps/spin/rdbms-types.wit: -------------------------------------------------------------------------------- 1 | interface rdbms-types { 2 | /// Errors related to interacting with a database. 3 | variant error { 4 | connection-failed(string), 5 | bad-parameter(string), 6 | query-failed(string), 7 | value-conversion-failed(string), 8 | other(string) 9 | } 10 | 11 | /// Data types for a database column 12 | enum db-data-type { 13 | boolean, 14 | int8, 15 | int16, 16 | int32, 17 | int64, 18 | uint8, 19 | uint16, 20 | uint32, 21 | uint64, 22 | floating32, 23 | floating64, 24 | str, 25 | binary, 26 | other, 27 | } 28 | 29 | /// Database values 30 | variant db-value { 31 | boolean(bool), 32 | int8(s8), 33 | int16(s16), 34 | int32(s32), 35 | int64(s64), 36 | uint8(u8), 37 | uint16(u16), 38 | uint32(u32), 39 | uint64(u64), 40 | floating32(float32), 41 | floating64(float64), 42 | str(string), 43 | binary(list), 44 | db-null, 45 | unsupported, 46 | } 47 | 48 | /// Values used in parameterized queries 49 | variant parameter-value { 50 | boolean(bool), 51 | int8(s8), 52 | int16(s16), 53 | int32(s32), 54 | int64(s64), 55 | uint8(u8), 56 | uint16(u16), 57 | uint32(u32), 58 | uint64(u64), 59 | floating32(float32), 60 | floating64(float64), 61 | str(string), 62 | binary(list), 63 | db-null, 64 | } 65 | 66 | /// A database column 67 | record column { 68 | name: string, 69 | data-type: db-data-type, 70 | } 71 | 72 | /// A database row 73 | type row = list; 74 | 75 | /// A set of database rows 76 | record row-set { 77 | columns: list, 78 | rows: list, 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /wit/deps/spin/redis.wit: -------------------------------------------------------------------------------- 1 | interface redis { 2 | /// Errors related to interacting with Redis 3 | variant error { 4 | /// An invalid address string 5 | invalid-address, 6 | /// There are too many open connections 7 | too-many-connections, 8 | /// A retrieved value was not of the correct type 9 | type-error, 10 | /// Some other error occurred 11 | other(string), 12 | } 13 | 14 | resource connection { 15 | /// Open a connection to the Redis instance at `address`. 16 | open: static func(address: string) -> result; 17 | 18 | /// Publish a Redis message to the specified channel. 19 | publish: func(channel: string, payload: payload) -> result<_, error>; 20 | 21 | /// Get the value of a key. 22 | get: func(key: string) -> result, error>; 23 | 24 | /// Set key to value. 25 | /// 26 | /// If key already holds a value, it is overwritten. 27 | set: func(key: string, value: payload) -> result<_, error>; 28 | 29 | /// Increments the number stored at key by one. 30 | /// 31 | /// If the key does not exist, it is set to 0 before performing the operation. 32 | /// An `error::type-error` is returned if the key contains a value of the wrong type 33 | /// or contains a string that can not be represented as integer. 34 | incr: func(key: string) -> result; 35 | 36 | /// Removes the specified keys. 37 | /// 38 | /// A key is ignored if it does not exist. Returns the number of keys deleted. 39 | del: func(keys: list) -> result; 40 | 41 | /// Add the specified `values` to the set named `key`, returning the number of newly-added values. 42 | sadd: func(key: string, values: list) -> result; 43 | 44 | /// Retrieve the contents of the set named `key`. 45 | smembers: func(key: string) -> result, error>; 46 | 47 | /// Remove the specified `values` from the set named `key`, returning the number of newly-removed values. 48 | srem: func(key: string, values: list) -> result; 49 | 50 | /// Execute an arbitrary Redis command and receive the result. 51 | execute: func(command: string, arguments: list) -> result, error>; 52 | } 53 | 54 | /// The message payload. 55 | type payload = list; 56 | 57 | /// A parameter type for the general-purpose `execute` function. 58 | variant redis-parameter { 59 | int64(s64), 60 | binary(payload) 61 | } 62 | 63 | /// A return type for the general-purpose `execute` function. 64 | variant redis-result { 65 | nil, 66 | status(string), 67 | int64(s64), 68 | binary(payload) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /wit/deps/spin/sqlite.wit: -------------------------------------------------------------------------------- 1 | interface sqlite { 2 | /// A handle to an open sqlite instance 3 | resource connection { 4 | /// Open a connection to a named database instance. 5 | /// 6 | /// If `database` is "default", the default instance is opened. 7 | /// 8 | /// `error::no-such-database` will be raised if the `name` is not recognized. 9 | open: static func(database: string) -> result; 10 | 11 | /// Execute a statement returning back data if there is any 12 | execute: func(statement: string, parameters: list) -> result; 13 | } 14 | 15 | /// The set of errors which may be raised by functions in this interface 16 | variant error { 17 | /// The host does not recognize the database name requested. 18 | no-such-database, 19 | /// The requesting component does not have access to the specified database (which may or may not exist). 20 | access-denied, 21 | /// The provided connection is not valid 22 | invalid-connection, 23 | /// The database has reached its capacity 24 | database-full, 25 | /// Some implementation-specific error has occurred (e.g. I/O) 26 | io(string) 27 | } 28 | 29 | /// A result of a query 30 | record query-result { 31 | /// The names of the columns retrieved in the query 32 | columns: list, 33 | /// the row results each containing the values for all the columns for a given row 34 | rows: list, 35 | } 36 | 37 | /// A set of values for each of the columns in a query-result 38 | record row-result { 39 | values: list 40 | } 41 | 42 | /// A single column's result from a database query 43 | variant value { 44 | integer(s64), 45 | real(float64), 46 | text(string), 47 | blob(list), 48 | null 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /wit/deps/spin/variables.wit: -------------------------------------------------------------------------------- 1 | interface variables { 2 | /// Get an application variable value for the current component. 3 | /// 4 | /// The name must match one defined in in the component manifest. 5 | get: func(name: string) -> result; 6 | 7 | /// The set of errors which may be raised by functions in this interface. 8 | variant error { 9 | /// The provided variable name is invalid. 10 | invalid-name(string), 11 | /// The provided variable is undefined. 12 | undefined(string), 13 | /// A variables provider specific error has occurred. 14 | provider(string), 15 | /// Some implementation-specific error has occurred. 16 | other(string), 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /wit/deps/spin/world.wit: -------------------------------------------------------------------------------- 1 | package fermyon:spin@2.0.0; 2 | 3 | /// The full world of a guest targeting an http-trigger 4 | world http-trigger { 5 | include platform; 6 | export wasi:http/incoming-handler@0.2.0; 7 | } 8 | 9 | /// Like `http-trigger`, but using WASI 0.2.0-rc-2023-10-18 10 | world http-trigger-rc20231018 { 11 | include platform-rc20231018; 12 | export wasi:http/incoming-handler@0.2.0-rc-2023-10-18; 13 | } 14 | 15 | /// The imports needed for a guest to run on a Spin host 16 | world platform { 17 | include wasi:cli/imports@0.2.0; 18 | import wasi:http/outgoing-handler@0.2.0; 19 | import llm; 20 | import redis; 21 | import mqtt; 22 | import postgres; 23 | import mysql; 24 | import sqlite; 25 | import key-value; 26 | import variables; 27 | } 28 | 29 | /// Like `platform`, but using WASI 0.2.0-rc-2023-10-18 30 | world platform-rc20231018 { 31 | include wasi:cli/reactor@0.2.0-rc-2023-10-18; 32 | import wasi:http/outgoing-handler@0.2.0-rc-2023-10-18; 33 | import llm; 34 | import redis; 35 | import mqtt; 36 | import postgres; 37 | import mysql; 38 | import sqlite; 39 | import key-value; 40 | import variables; 41 | } 42 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/config.wit: -------------------------------------------------------------------------------- 1 | interface config { 2 | // Get a configuration value for the current component. 3 | // The config key must match one defined in in the component manifest. 4 | get-config: func(key: string) -> result; 5 | 6 | variant error { 7 | provider(string), 8 | invalid-key(string), 9 | invalid-schema(string), 10 | other(string), 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/http-types.wit: -------------------------------------------------------------------------------- 1 | interface http-types { 2 | type http-status = u16; 3 | 4 | type body = list; 5 | 6 | type headers = list>; 7 | 8 | type params = list>; 9 | 10 | type uri = string; 11 | 12 | enum method { 13 | get, 14 | post, 15 | put, 16 | delete, 17 | patch, 18 | head, 19 | options, 20 | } 21 | 22 | record request { 23 | method: method, 24 | uri: uri, 25 | headers: headers, 26 | params: params, 27 | body: option, 28 | } 29 | 30 | record response { 31 | status: http-status, 32 | headers: option, 33 | body: option, 34 | } 35 | 36 | enum http-error { 37 | success, 38 | destination-not-allowed, 39 | invalid-url, 40 | request-error, 41 | runtime-error, 42 | too-many-requests, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/http.wit: -------------------------------------------------------------------------------- 1 | interface http { 2 | use http-types.{request, response, http-error}; 3 | 4 | send-request: func(req: request) -> result; 5 | } 6 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/inbound-http.wit: -------------------------------------------------------------------------------- 1 | interface inbound-http { 2 | use http-types.{request, response}; 3 | 4 | handle-request: func(req: request) -> response; 5 | } 6 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/inbound-redis.wit: -------------------------------------------------------------------------------- 1 | interface inbound-redis { 2 | use redis-types.{payload, error}; 3 | 4 | // The entrypoint for a Redis handler. 5 | handle-message: func(message: payload) -> result<_, error>; 6 | } 7 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/key-value.wit: -------------------------------------------------------------------------------- 1 | interface key-value { 2 | // A handle to an open key-value store 3 | type store = u32; 4 | 5 | // The set of errors which may be raised by functions in this interface 6 | variant error { 7 | // Too many stores have been opened simultaneously. Closing one or more 8 | // stores prior to retrying may address this. 9 | store-table-full, 10 | 11 | // The host does not recognize the store name requested. Defining and 12 | // configuring a store with that name in a runtime configuration file 13 | // may address this. 14 | no-such-store, 15 | 16 | // The requesting component does not have access to the specified store 17 | // (which may or may not exist). 18 | access-denied, 19 | 20 | // The store handle provided is not recognized, i.e. it was either never 21 | // opened or has been closed. 22 | invalid-store, 23 | 24 | // No key-value tuple exists for the specified key in the specified 25 | // store. 26 | no-such-key, 27 | 28 | // Some implementation-specific error has occurred (e.g. I/O) 29 | io(string) 30 | } 31 | 32 | // Open the store with the specified name. 33 | // 34 | // If `name` is "default", the default store is opened. Otherwise, 35 | // `name` must refer to a store defined and configured in a runtime 36 | // configuration file supplied with the application. 37 | // 38 | // `error::no-such-store` will be raised if the `name` is not recognized. 39 | open: func(name: string) -> result; 40 | 41 | // Get the value associated with the specified `key` from the specified 42 | // `store`. 43 | // 44 | // `error::invalid-store` will be raised if `store` is not a valid handle 45 | // to an open store, and `error::no-such-key` will be raised if there is no 46 | // tuple for `key` in `store`. 47 | get: func(store: store, key: string) -> result, error>; 48 | 49 | // Set the `value` associated with the specified `key` in the specified 50 | // `store`, overwriting any existing value. 51 | // 52 | // `error::invalid-store` will be raised if `store` is not a valid handle 53 | // to an open store. 54 | set: func(store: store, key: string, value: list) -> result<_, error>; 55 | 56 | // Delete the tuple with the specified `key` from the specified `store`. 57 | // 58 | // `error::invalid-store` will be raised if `store` is not a valid handle 59 | // to an open store. No error is raised if a tuple did not previously 60 | // exist for `key`. 61 | delete: func(store: store, key: string) -> result<_, error>; 62 | 63 | // Return whether a tuple exists for the specified `key` in the specified 64 | // `store`. 65 | // 66 | // `error::invalid-store` will be raised if `store` is not a valid handle 67 | // to an open store. 68 | exists: func(store: store, key: string) -> result; 69 | 70 | // Return a list of all the keys in the specified `store`. 71 | // 72 | // `error::invalid-store` will be raised if `store` is not a valid handle 73 | // to an open store. 74 | get-keys: func(store: store) -> result, error>; 75 | 76 | // Close the specified `store`. 77 | // 78 | // This has no effect if `store` is not a valid handle to an open store. 79 | close: func(store: store); 80 | } 81 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/llm.wit: -------------------------------------------------------------------------------- 1 | // A WASI interface dedicated to performing inferencing for Large Language Models. 2 | interface llm { 3 | /// A Large Language Model. 4 | type inferencing-model = string; 5 | 6 | /// Inference request parameters 7 | record inferencing-params { 8 | /// The maximum tokens that should be inferred. 9 | /// 10 | /// Note: the backing implementation may return less tokens. 11 | max-tokens: u32, 12 | /// The amount the model should avoid repeating tokens. 13 | repeat-penalty: float32, 14 | /// The number of tokens the model should apply the repeat penalty to. 15 | repeat-penalty-last-n-token-count: u32, 16 | /// The randomness with which the next token is selected. 17 | temperature: float32, 18 | /// The number of possible next tokens the model will choose from. 19 | top-k: u32, 20 | /// The probability total of next tokens the model will choose from. 21 | top-p: float32 22 | } 23 | 24 | /// The set of errors which may be raised by functions in this interface 25 | variant error { 26 | model-not-supported, 27 | runtime-error(string), 28 | invalid-input(string) 29 | } 30 | 31 | /// An inferencing result 32 | record inferencing-result { 33 | /// The text generated by the model 34 | // TODO: this should be a stream 35 | text: string, 36 | /// Usage information about the inferencing request 37 | usage: inferencing-usage 38 | } 39 | 40 | /// Usage information related to the inferencing result 41 | record inferencing-usage { 42 | /// Number of tokens in the prompt 43 | prompt-token-count: u32, 44 | /// Number of tokens generated by the inferencing operation 45 | generated-token-count: u32 46 | } 47 | 48 | /// Perform inferencing using the provided model and prompt with the given optional params 49 | infer: func(model: inferencing-model, prompt: string, params: option) -> result; 50 | 51 | /// The model used for generating embeddings 52 | type embedding-model = string; 53 | 54 | /// Generate embeddings for the supplied list of text 55 | generate-embeddings: func(model: embedding-model, text: list) -> result; 56 | 57 | /// Result of generating embeddings 58 | record embeddings-result { 59 | /// The embeddings generated by the request 60 | embeddings: list>, 61 | /// Usage related to the embeddings generation request 62 | usage: embeddings-usage 63 | } 64 | 65 | /// Usage related to an embeddings generation request 66 | record embeddings-usage { 67 | /// Number of tokens in the prompt 68 | prompt-token-count: u32, 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/mysql.wit: -------------------------------------------------------------------------------- 1 | interface mysql { 2 | use rdbms-types.{parameter-value, row-set}; 3 | 4 | // General purpose error. 5 | variant mysql-error { 6 | success, 7 | connection-failed(string), 8 | bad-parameter(string), 9 | query-failed(string), 10 | value-conversion-failed(string), 11 | other-error(string) 12 | } 13 | 14 | // query the database: select 15 | query: func(address: string, statement: string, params: list) -> result; 16 | 17 | // execute command to the database: insert, update, delete 18 | execute: func(address: string, statement: string, params: list) -> result<_, mysql-error>; 19 | } 20 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/postgres.wit: -------------------------------------------------------------------------------- 1 | interface postgres { 2 | use rdbms-types.{parameter-value, row-set}; 3 | 4 | // General purpose error. 5 | variant pg-error { 6 | success, 7 | connection-failed(string), 8 | bad-parameter(string), 9 | query-failed(string), 10 | value-conversion-failed(string), 11 | other-error(string) 12 | } 13 | 14 | // query the database: select 15 | query: func(address: string, statement: string, params: list) -> result; 16 | 17 | // execute command to the database: insert, update, delete 18 | execute: func(address: string, statement: string, params: list) -> result; 19 | } 20 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/rdbms-types.wit: -------------------------------------------------------------------------------- 1 | interface rdbms-types { 2 | enum db-data-type { 3 | boolean, 4 | int8, 5 | int16, 6 | int32, 7 | int64, 8 | uint8, 9 | uint16, 10 | uint32, 11 | uint64, 12 | floating32, 13 | floating64, 14 | str, 15 | binary, 16 | other, 17 | } 18 | 19 | variant db-value { 20 | boolean(bool), 21 | int8(s8), 22 | int16(s16), 23 | int32(s32), 24 | int64(s64), 25 | uint8(u8), 26 | uint16(u16), 27 | uint32(u32), 28 | uint64(u64), 29 | floating32(float32), 30 | floating64(float64), 31 | str(string), 32 | binary(list), 33 | db-null, 34 | unsupported, 35 | } 36 | 37 | variant parameter-value { 38 | boolean(bool), 39 | int8(s8), 40 | int16(s16), 41 | int32(s32), 42 | int64(s64), 43 | uint8(u8), 44 | uint16(u16), 45 | uint32(u32), 46 | uint64(u64), 47 | floating32(float32), 48 | floating64(float64), 49 | str(string), 50 | binary(list), 51 | db-null, 52 | } 53 | 54 | record column { 55 | name: string, 56 | data-type: db-data-type, 57 | } 58 | 59 | type row = list; 60 | 61 | record row-set { 62 | columns: list, 63 | rows: list, 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/redis-types.wit: -------------------------------------------------------------------------------- 1 | interface redis-types { 2 | // General purpose error. 3 | enum error { 4 | success, 5 | error, 6 | } 7 | 8 | /// The message payload. 9 | type payload = list; 10 | 11 | /// A parameter type for the general-purpose `execute` function. 12 | variant redis-parameter { 13 | int64(s64), 14 | binary(payload) 15 | } 16 | 17 | /// A return type for the general-purpose `execute` function. 18 | variant redis-result { 19 | nil, 20 | status(string), 21 | int64(s64), 22 | binary(payload) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/redis.wit: -------------------------------------------------------------------------------- 1 | interface redis { 2 | use redis-types.{payload, redis-parameter, redis-result, error}; 3 | 4 | // Publish a Redis message to the specificed channel and return an error, if any. 5 | publish: func(address: string, channel: string, payload: payload) -> result<_, error>; 6 | 7 | // Get the value of a key. 8 | get: func(address: string, key: string) -> result; 9 | 10 | // Set key to value. If key alreads holds a value, it is overwritten. 11 | set: func(address: string, key: string, value: payload) -> result<_, error>; 12 | 13 | // Increments the number stored at key by one. If the key does not exist, it is set to 0 before performing the operation. 14 | // An error is returned if the key contains a value of the wrong type or contains a string that can not be represented as integer. 15 | incr: func(address: string, key: string) -> result; 16 | 17 | // Removes the specified keys. A key is ignored if it does not exist. 18 | del: func(address: string, keys: list) -> result; 19 | 20 | // Add the specified `values` to the set named `key`, returning the number of newly-added values. 21 | sadd: func(address: string, key: string, values: list) -> result; 22 | 23 | // Retrieve the contents of the set named `key`. 24 | smembers: func(address: string, key: string) -> result, error>; 25 | 26 | // Remove the specified `values` from the set named `key`, returning the number of newly-removed values. 27 | srem: func(address: string, key: string, values: list) -> result; 28 | 29 | // Execute an arbitrary Redis command and receive the result. 30 | execute: func(address: string, command: string, arguments: list) -> result, error>; 31 | } 32 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/sqlite.wit: -------------------------------------------------------------------------------- 1 | interface sqlite { 2 | // A handle to an open sqlite instance 3 | type connection = u32; 4 | 5 | // The set of errors which may be raised by functions in this interface 6 | variant error { 7 | // The host does not recognize the database name requested. 8 | no-such-database, 9 | // The requesting component does not have access to the specified database (which may or may not exist). 10 | access-denied, 11 | // The provided connection is not valid 12 | invalid-connection, 13 | // The database has reached its capacity 14 | database-full, 15 | // Some implementation-specific error has occurred (e.g. I/O) 16 | io(string) 17 | } 18 | 19 | // Open a connection to a named database instance. 20 | // 21 | // If `database` is "default", the default instance is opened. 22 | // 23 | // `error::no-such-database` will be raised if the `name` is not recognized. 24 | open: func(database: string) -> result; 25 | 26 | // Execute a statement returning back data if there is any 27 | execute: func(conn: connection, statement: string, parameters: list) -> result; 28 | 29 | // Close the specified `connection`. 30 | close: func(conn: connection); 31 | 32 | // A result of a query 33 | record query-result { 34 | // The names of the columns retrieved in the query 35 | columns: list, 36 | // the row results each containing the values for all the columns for a given row 37 | rows: list, 38 | } 39 | 40 | // A set of values for each of the columns in a query-result 41 | record row-result { 42 | values: list 43 | } 44 | 45 | variant value { 46 | integer(s64), 47 | real(float64), 48 | text(string), 49 | blob(list), 50 | null 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /wit/deps/spin@unversioned/world.wit: -------------------------------------------------------------------------------- 1 | package fermyon:spin; 2 | 3 | world host { 4 | include platform; 5 | 6 | export inbound-http; 7 | export inbound-redis; 8 | } 9 | 10 | world redis-trigger { 11 | include platform; 12 | export inbound-redis; 13 | } 14 | 15 | world http-trigger { 16 | include platform; 17 | export inbound-http; 18 | } 19 | 20 | world platform { 21 | import config; 22 | import http; 23 | import postgres; 24 | import mysql; 25 | import sqlite; 26 | import redis; 27 | import key-value; 28 | import llm; 29 | } 30 | -------------------------------------------------------------------------------- /wit/world.wit: -------------------------------------------------------------------------------- 1 | package moonbit:spin; 2 | 3 | /// The full world of a guest targeting an http-trigger 4 | world http-trigger { 5 | include fermyon:spin/platform@2.0.0; 6 | export wasi:http/incoming-handler@0.2.0; 7 | } --------------------------------------------------------------------------------