1358: Update C API to use new API r=MarkMcCaskey a=MarkMcCaskey
# Review
- [ ] Add a short description of the the change to the CHANGELOG.md file
Co-authored-by: Mark McCaskey <mark@wasmer.io>
Co-authored-by: Mark McCaskey <5770194+MarkMcCaskey@users.noreply.github.com>
1331: feat(interface-types) Implement the `record` instructions r=Hywan a=Hywan
### Description
This PR implements the `record` WIT type, along with the `record.lift` and `record.lower` instructions.
With my current understanding of the draft/specification, here is how it works. Let's say we want to represent a Rust struct like the following:
```rust
struct S {
x: String,
y: i32
}
```
First declare a WIT type, such as:
```wat
(@interface type (record (field string) (field i32)))
```
The `record` type is supported by the binary encoder, the WAT encoder, the binary decoder, and the WAT decoder. A new `TypeKind` node has been introduced in the AST to differentiate a function type (`(@interface type (func (param …) (result …)))`) of a record type (see above).
Second, the `record.lower` transforms a host value (here Rust value, `S`) into a WIT value. In our implementation, a record value is defined as:
```rust
InterfaceValue::Record(Vec<InterfaceValue>)
```
Multiple mechanisms are used to type check a record value based on a record type. The code of the `record.lower` is pretty straightforward.
Because transforming a host value into a WIT value isn't obvious, a `Serializer` has been implemented, based on [`serde`](https://serde.rs/). This feature is behind the `serde` flag, which is turned on by default.
Serde is only used to cross the host/Wasm boundary, but it's not used to represent the value in memory or anything. It's only a shortcut to transform a host value into a WIT value, and vice versa.
Use the following code to transform `S` into a WIT value:
```rust
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct S {
x: String,
y: i32,
}
let host_value = S { x: "hello".to_string(), y: 42 };
let wit_value = to_interface_value(&host_value).unwrap();
assert_eq!(
wit_value,
InterfaceValue::Record(vec![
InterfaceValue::String("hello".to_string()),
InterfaceValue::I32(42),
])
);
```
Third, the `record.lift` instruction does the opposite of `record.lower`: It transforms WIT values into a host value. To also facilitate the user experience, this PR contains a `Deserializer` implementation, still based on `serde`, with the `from_interface_values` function. It looks like this:
```rust
let wit_values = vec![
InterfaceValue::Record(vec![
InterfaceValue::String("hello".to_string()),
InterfaceValue::I32(42),
])
];
let host_value = from_interface_values::<S>(&wit_values).unwrap();
assert_eq!(
host_value,
S { x: "hello".to_string(), y: 42 },
);
```
With the `Serializer` and `Deserializer`, it's super easy for the user to send or receive values from WIT.
The `record.lift` and `record.lower` instructions are kind of basic. The `record.lift` instruction has a little trick to reduce vector allocations, but there is a documentation for that.
#### Opened questions
Records of dimension 1 do not raise any issue. With `record.lift`, all values on the stack (the WIT interpreter stack) are popped, and are used as record field values. Something like:
```
[stack]
i32(1)
i64(2),
string("hello")
record.lift <record_type>
```
generates
```
[stack]
record { i32(1), i64(2), string("hello") }
```
But it's not clear what happens with record of dimension > 1, for instance for a type like `record (field i32) (record (field i32) (field i32)) (field string)`, it is assumed (in this PR) that the stack must be like this:
```
[stack]
i32(1)
i32(2)
i32(3)
string("hello")
record.lift <record_type>
```
to generate:
```
[stack]
record { i32(1), record { i32(2), i32(3) }, string("hello") }
```
If we want the stack to contain an intermediate record, we should have something like this:
```
[stack]
i32(1)
i32(2)
i32(3)
record.lift <record_type_2>
string("hello")
record.lift <record_type_1>
```
But it would imply that `record_type_1` is defined as `record (field i32) (record (type record_type_2)) (field i32)`.
A sub-record defined by another record type isn't support, as it is not specified in the draft. I believe my assumption is fine enough for a first implementation of records in WIT.
### To do
- [x] Encode and decode record type (`(@interface type (record string i32))`):
- [x] Binary encoder/decoder
- [x] WAT encoder/decoder
- [x] Implement the `record.lift` instruction
- [x] Implement the `record.lower` instruction
- [x] Test
- [x] Documentation
- [x] Surprise!
- [x] Serialize a Rust value to WIT values (useful for `record`s)
- [x] Deserialize WIT values to a Rust value (useful for `record`s)
Co-authored-by: Ivan Enderlin <ivan.enderlin@hoa-project.net>
1350: update blake3 to 0.3.1 r=syrusakbary a=oconnor663
Version 0.3.0 caused problems because it required a C compiler with
AVX-512 support, which broke Android x86 cross-compilation. Version
0.3.1 automatically falls back to a pure Rust build when the C compiler
either doesn't exist or doesn't support the flags we need.
Co-authored-by: Jack O'Connor <oconnor663@gmail.com>
Version 0.3.0 caused problems because it required a C compiler with
AVX-512 support, which broke Android x86 cross-compilation. Version
0.3.1 automatically falls back to a pure Rust build when the C compiler
either doesn't exist or doesn't support the flags we need.
1313: Add types and methods to provide updated API r=MarkMcCaskey a=MarkMcCaskey
Improving the API in a number of ways.
<details><summary>Current status </summary>
- [x] Get exports from Instance
- [x] Func
- [x] Documented
- [x] Tested
- [x] DynFunc
- [x] Documented
- [x] Tested
- [x] Memory
- [x] Documented
- [x] Tested
- [x] Table
- [x] Documented
- [ ] Tested ; fully testing this now will be difficult, blocked on Table API being completed
- [x] Global
- [x] Documented
- [x] Tested
- [x] Field syntax (fairly non-trivial)
- [x] Get imports from Module
- [ ] Maybe update this to be an iterator instead of a Vec (side note, we may want to have a way to access specific types of imports too)
- [x] Documented
- [x] Tested
- [x] Get exports from Module
- [x] Documented
- [x] Tested
- [x] Get custom section from Module
- [x] Figure out correct solution
- [x] Ship separate PR that updates custom section code
- [x] Documented
- [x] Tested
- [ ] Updated Memory API
- [x] Added conversion methods to bytes/pages with From
- [ ] Documented
- [ ] Tested
- [ ] Table APIs ; blocked on `wrap` being not linear time update (this update should also make it possible to retrieve a `Func` from `vm::Anyfunc`)
- [ ] Table set (implemented needs to be checked)
- [ ] Documented with examples
- [x] Implemented
- [ ] Table grow (implemented needs to be checked)
- [ ] Documented with examples
- [x] Implemented
- [ ] Table get
- [x] Structure implemented
- [ ] Documented
- [ ] Tested
- [ ] Module APIs (probably separate)
- [x] Update import object macro to handle a lack of trailing commas as well
- [x] Add line in changelog about it
- [x] Tested
</details>
# Review
- [ ] Add a short description of the the change to the CHANGELOG.md file
Co-authored-by: Mark McCaskey <mark@wasmer.io>
Co-authored-by: Mark McCaskey <5770194+MarkMcCaskey@users.noreply.github.com>
1288: Update some dependencies manually, removing duplicate deps r=MarkMcCaskey a=MarkMcCaskey
Removes all duplicate deps (as seen by `cargo +stable tree -d`). Primarily by updating `wasm-debug` but also by through updating some other dependencies.
Co-authored-by: Mark McCaskey <mark@wasmer.io>