Skip to content

Merge/master into next#740

Draft
raymondk wants to merge 44 commits into
nextfrom
merge/master-into-next
Draft

Merge/master into next#740
raymondk wants to merge 44 commits into
nextfrom
merge/master-into-next

Conversation

@raymondk

Copy link
Copy Markdown
Contributor

No description provided.

lwshang and others added 30 commits December 10, 2025 17:54
GItHub releases will include prebuilt `candid_ui.wasm` so that tools
like `icp-cli` can integrate.

A test release can be found
[here](https://github.com/dfinity/candid/releases/tag/test_release_candid_ui_2).
Changed imports generated by
`candid_parser::bindings::typescript::compile` from `@dfinity/*` to
`@icp-sdk/core/*`
We use rangemap in ic-agent for canister ranges. It has a feature to
implement the required trait even if the upstream type doesn't, but it
blocks implementing Debug and a couple other annoyances so it'd be nice
for ic_principal to implement it directly.
Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
# Summary

- Use `target_family = "wasm"` for platform detection to cover both
wasm32 and wasm64; skip recursion check on wasm (sandboxed), use
stack-based check on native platforms and a conservative depth limit on
other niche platforms
- Apply recursion guard to all recursive functions on deserialization
path: type environment operations (`TypeEnv::is_empty`, `trace_type`,
`rec_find_type`, `as_func`, `as_service`), value type annotation
(`IDLValue::annotate_type`), and subtype checking (`subtype_()`,
`equal()`)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Unblocks #702

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This makes the `BoundedVec` type, thus far used in the [management
canister
types](https://sourcegraph.com/github.com/dfinity/ic/-/blob/rs/types/management_canister_types/src/bounded_vec.rs?L14),
available for public use.

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
### Solution
- Add `TypeDoc`, `FieldDoc`, and `TypeDocs` types to carry doc metadata
alongside the type graph
- Extend `CandidType` derive to extract Rust doc comments via new
`_ty_doc()` hook; store per-TypeId in thread-local DOC_ENV
- Update pretty-printer to render docs above type definitions, record
fields, and variant members

### Details
- Docs flow through `TypeContainer` which maps Rust TypeId docs to final
Candid export names
- Tuples with field docs fall back to explicit numeric field syntax

### Meta
- This is needed for my work on Immutable Object Storage. I currently
have some hacks to add doc comments to .did files, but everyone would
benefit if this was fixed properly.

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
**Overview**
Performance improvement

**Requirements**
Preserve existing wire compatibility and keep record decoding behavior
unchanged.

**Solution**
Encode and decode Nat and Int values through native LEB128 when they fit
in machine integers so common small numbers avoid bigint work.

**Considerations**
I expect performance improvement and full forward and backward
compatibility

Ref. #710

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
**Overview**
Reduce per-record allocation churn during Candid record decoding.

**Requirements**
Preserve existing wire compatibility and keep record decoding behavior
unchanged.

**Solution**
Track expected and wire record fields by type plus index instead of
cloning field queues for each decoded record. Add a compatibility test
covering backward and forward compatible record vectors.

**Considerations**
This keeps the wire format unchanged and is intended to remain fully
compatible with existing Candid data. Series-level benchmark context is
tracked in #710.

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
**Overview**
Reduce repeated per-element type work when decoding primitive vectors.

**Requirements**
Preserve vector decoding semantics, including compatibility with extra
trailing arguments.

**Solution**
Add an exact-primitive fast path for vector elements so deserialization
can skip repeated type unrolling and checks when expected and wire
element types already match. Add a compatibility test covering
extra-args behavior.

**Considerations**
The optimization is limited to exact primitive matches and leaves the
general decode path unchanged. Series-level benchmark context is tracked
in #710.

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
**Overview**
Reduce parser work on tokenizer paths that do not capture trivia.

**Requirements**
Keep comment and doc-comment behavior unchanged when trivia capture is
enabled.

**Solution**
Skip comment and line-tracking bookkeeping when the tokenizer runs
without trivia capture. This trims successful DID and argument parsing
on the hot path without changing the trivia-enabled path.

**Considerations**
Parser behavior with trivia capture is unchanged, and the parser test
suite still passes. Series-level benchmark context is tracked in #710.

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
**Overview**
Reduce duplicate whole-file work during DID typechecking.

**Requirements**
Preserve parser validation semantics while improving large DID load
performance.

**Solution**
Validate deferred parser semantics from the built type environment
instead of rebuilding every declaration a second time in `check_decs`.

**Considerations**
This keeps the validation flow intact while removing redundant
reconstruction work, and the parser test suite still passes.
Series-level benchmark context is tracked in #710.

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
## Summary

On little-endian targets (including wasm32), `Vec<i16/u32/f64/etc.>`
encoding now writes the backing memory directly instead of iterating
element-by-element through the Serializer trait.

- Added `try_write_raw_elements` default method to `Compound` trait
- `ValueSerializer::Compound` implements it with direct byte write
- `[T]::idl_serialize` detects fixed-width primitives via `TypeId` on
`#[cfg(target_endian = "little")]`
- `Vec<T>` and `[T; N]` delegate to the optimized slice path
- Excludes `usize`/`isize` (platform-dependent size)

## Benchmark (canbench, wasm32)

| Metric | Before | After | Change |
|--------|--------|-------|--------|
| vec_int16 Encoding | 123.7M inst | 8.4M inst | **14.7x faster
(-93.2%)** |
| vec_int16 Total | 817.9M inst | 704.7M inst | -13.8% |

No regressions on any of the 9 benchmarks.

## Compatibility

Wire format is **unchanged** — produces byte-identical output.
Round-trip compatibility test added.

Relates to #710

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary

Pre-compute the total decoding cost for primitive vectors at the vector
level instead of calling `add_cost` per element. Also sets
`primitive_vec_fast_path` once before `visit_seq` rather than saving and
restoring it on every element.

- Added `primitive_byte_cost` helper
- Pre-computed `len * (3 + byte_cost)` in `deserialize_seq` for
primitive vectors
- Removed per-element `add_cost` from `primitive_impl!` and
`deserialize_bool` fast paths
- Moved `add_cost(3)` into non-primitive branch in `next_element_seed`

## Benchmark (canbench, wasm32)

| Metric | Before | After | Change |
|--------|--------|-------|--------|
| vec_int16 Decoding | 694.2M inst | 409.0M inst | **41.1% faster** |
| vec_int16 Total | 817.9M inst | 532.7M inst | -34.9% |

No regressions on any of the 9 benchmarks.

## Compatibility

Wire format and cost accounting semantics are **unchanged**. The total
cost charged is identical — it's just computed once upfront instead of
incrementally.

Relates to #710
## Summary

Decode SLEB128-encoded `Int` values into `i64` first, only falling back
to `BigInt` for values that exceed 64-bit range. Mirrors the existing
`Nat::decode` fast path from an earlier commit in this series.

- Fast path: accumulates SLEB128 bytes into `i64` with proper sign
extension
- Fallback: converts accumulated `i64` to `BigInt` and continues with
`BigInt` arithmetic
- Most real-world `Int` values fit in `i64`, avoiding heap allocation
entirely

## Benchmark (canbench, wasm32)

| Metric | Before | After | Change |
|--------|--------|-------|--------|
| option_list Decoding | 26.2M inst | 23.2M inst | **-11.7%** |
| variant_list Decoding | 25.1M inst | 22.1M inst | **-11.9%** |
| option_list Heap | 2 pages | 1 page | **-50%** |
| variant_list Heap | 2 pages | 1 page | **-50%** |

No regressions on any of the 9 benchmarks.

## Compatibility

Wire format is **unchanged**. Additional edge-case values added to the
round-trip compatibility test (Int(0), Int(i64::MAX), large positive
Int).

Relates to #710

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary

Adds three new canbench benchmarks to complement the existing
`vec_int16`:

- **`vec_nat`** — 262K `Nat` elements (variable-length LEB128 encoding).
Exercises the `Nat::encode`/`decode` paths and the serde visitor
round-trip for bignum types.
- **`vec_nat32`** — 2M `u32` elements (fixed-width 4 bytes). Tests
fixed-width primitive vector performance.
- **`vec_nat64`** — 2M `u64` elements (fixed-width 8 bytes). Tests the
largest fixed-width primitive vector.

### Baseline results (master, `ba72cf4`)

| Benchmark | Encoding | Decoding | Total | Heap |
|-----------|----------|----------|-------|------|
| vec_nat | 1.10B | 1.49B | 2.59B | 172 pages |
| vec_nat32 | 136.28M | 1.06B | 1.20B | 518 pages |
| vec_nat64 | 161.45M | 1.06B | 1.22B | 1031 pages |

These baselines make the impact of the performance work in
`sat-perf-improvements` directly measurable:

| Benchmark | Metric | Master | Optimized | Change |
|-----------|--------|--------|-----------|--------|
| **vec_nat** | Encoding | 1.10B | 66.54M | **-93.9% (16.5x)** |
| **vec_nat** | Decoding | 1.49B | 917.08M | **-38.5%** |
| **vec_nat** | Total | 2.59B | 983.62M | **-62.0%** |
| **vec_nat32** | Encoding | 136.28M | 16.79M | **-87.7% (8.1x)** |
| **vec_nat32** | Decoding | 1.06B | 406.87M | **-61.6%** |
| **vec_nat32** | Total | 1.20B | 423.67M | **-64.7%** |
| **vec_nat64** | Encoding | 161.45M | 33.57M | **-79.2% (4.8x)** |
| **vec_nat64** | Decoding | 1.06B | 411.07M | **-61.2%** |
| **vec_nat64** | Total | 1.22B | 444.64M | **-63.6%** |

Relates to #710

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This release also includes some performance improvements that are not
shown in the changelog.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary

- Fix decoding failure when a trailing/extra argument is a primitive
vector (`vec int8/16/32/64`, `vec nat8/16/32/64`, `vec float32/64`, `vec
bool`)
- The fast-path optimization (#712) skipped setting
`expect_type`/`wire_type` per element; `deserialize_ignored_any` then
misidentified the element type and corrupted the byte stream
- Fix: always set element types before calling `seed.deserialize`,
skipping only the `add_cost(3)` call in the fast path
- Release candid 0.10.26

## Test plan

- [ ] New regression test `primitive_vector_is_extra_args` in
`tests/compatibility_vectors.rs` covers the exact failure scenario
- [ ] All existing `compatibility_vectors` tests continue to pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…721)

**Overview**

Four decode-side optimizations, all behavior-preserving:

1. Nat/Int deserialization bypass: for values fitting u64/i64, read
LEB128 directly and call visitor.visit_u64/i64, avoiding the
BigUint/BigInt → bytes → BigUint round-trip (saves 3 allocations per
value).

2. BigNum vector fast path: batch cost tracking and skip per-element
type cloning/checking for Vec<Nat>, Vec<Int>, and Vec<Int> with Nat wire
type, mirroring the existing primitive vec fast path.

3. PrimitiveVecAccess with IntoDeserializer: on LE platforms, decode
primitive vectors via a lightweight SeqAccess that reads directly from
the input byte slice using serde's IntoDeserializer, bypassing the full
Deserializer and Cursor overhead.

4. Borrowed string deserialization: use visit_borrowed_str instead of
copying bytes, enabling zero-copy for &str targets.

Benchmark improvements (decode, vs previous optimized baseline):
  vec_nat:      910M → 300M  (-67%)
  vec_nat32:    406M → 247M  (-39%)
  vec_nat64:    411M → 255M  (-38%)
  vec_int16:    411M → 251M  (-39%)
  btreemap:    13.3B → 11.2B (-16%)
  option_list:   23M →  18M  (-20%)
  variant_list:  21M →  17M  (-21%)

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
### Motivation
- Remove external `binary_parser` dependency for hot deserialization
paths.

### Solution
- Inline LEB128 u64/i64, length, and bool reading directly in
`Deserializer`.
- Add `text_fast_path` flag to skip type checks when key types are known
during map deserialization.
- Apply fast path to map keys/values and bignum handling.

### Meta
- Removed unused `BoolValue` import.

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
### Motivation
- Existing benchmarks miss critical decode paths; issue #603 notes zero
coverage of service subtype checking.

### Solution
- Add 8 benchmarks covering production patterns: fully-populated NNS
neurons, schema evolution (field skipping), vec of services (exercises
check_subtype), Ok/Err result variants, wide records (34+ fields), large
enums (21 arms), double optionals, and multi-arg encoding/decoding.

### Details
- Enable `value` feature on candid dependency for IDLValue/IDLArgs APIs.
- Each benchmark reports separate encode/decode timings via bench_scope.

Relates to #603

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
## Summary
- Add a `publish.yml` workflow for publishing crates to crates.io via
trusted publishing (OIDC)
- Supports selective publishing of `ic_principal`,
`candid`/`candid_derive` (always together), and `candid_parser`
- Publishes in dependency order to avoid unmet dependency errors

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sasa-tomic and others added 12 commits April 8, 2026 16:17
…0.27 (#725)

## Release

- `candid` 0.10.27
- `candid_parser` 0.3.1
- `didc` 0.6.1

## Summary

- The compatibility check previously stopped at the **first**
incompatibility, forcing users into a fix-and-retry loop. Now it
collects all breaking changes and renders them as a grouped,
hierarchical report. The number of reported errors is bounded only by
the interface size (no artificial cap); recursion depth is bounded by
the existing stack/depth guard (~512 levels).
- Error messages are clearer: "missing in new interface" instead of "is
only in expected type"; "function annotation changed from query to
update" instead of "Function mode mismatch".
- New public API: `subtype_check_all()`, `Incompatibility`,
`format_report()` in `candid`; `service_compatibility_report()` in
`candid_parser`.



### Before (stops at first error)

```
Method budget_check_v1: func (BudgetCheckRequest) -> (BudgetCheckResult) query
  is not a subtype of func (BudgetCheckRequest/1) -> (BudgetCheckResult/1) query
```

### After (all errors, grouped by method)

```
Error: 7 incompatible changes found:

  - method "config" is expected by the old interface but missing in the new one
  method "audit":
    - function annotation changed from query to update
    return type:
      record field log: nat is not a subtype of text
      record field count: text is not a subtype of nat
  method "balance":
    return type: text is not a subtype of nat
  method "transfer":
    input type:
      record field amount: nat is not a subtype of text
    return type:
      record field ok: text is not a subtype of bool
      record field balance: text is not a subtype of nat
```

## Changes

| File | What |
|------|------|
| `rust/candid/src/types/subtype.rs` | `Incompatibility` struct,
`subtype_check_all()`, `format_report()`, internal `subtype_collect_()`
|
| `rust/candid_parser/src/utils.rs` | `service_compatibility_report()` |
| `tools/didc/src/main.rs` | `didc check` uses new report |
| `tools/ui/src/didjs/lib.rs` | Web UI uses new report |
| `rust/candid_parser/tests/compatibility.rs` | **29 new tests** |

## Test plan

- [x] 8 tests: backward-compatible changes (add opt field, add method,
widen nat→int in input, etc.) must NOT be flagged
- [x] 6 tests: backward-incompatible changes (remove method, change
type, add required field, etc.) must be caught
- [x] 6 tests: multiple errors are ALL collected (multiple methods,
multiple fields, both input+return)
- [x] 3 tests: error message quality (mentions method names, types,
clear wording)
- [x] 3 tests: hierarchical report formatting (grouping, inlining, empty
for compatible)
- [x] 3 tests: variant/edge cases
- [x] All 175 existing tests continue to pass

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Pin GitHub Actions to commit SHAs

GitHub Actions referenced by tag (e.g. `actions/checkout@v4`) use a
mutable pointer — the tag owner can move it to a different commit at any
time, including a malicious one. This is the attack vector used in the
tj-actions/changed-files incident (CVE-2025-30066).

Pinning to a full 40-character commit SHA makes the reference immutable.
The `# tag` comment preserves human readability so reviewers can tell
which version is pinned.

Important: a SHA can also originate from a forked repository. A
malicious actor can fork an action, push a compromised commit to the
fork, and the SHA will resolve — but it won't exist in the upstream
canonical repo. Each SHA in this PR was verified against the action's
canonical repository (not a fork).

### Changes

- `actions/checkout@v4` ->
`actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1`
  - Version: v4.3.1 | Latest: v6.0.2 | Release age: 88d
- Commit:
actions/checkout@34e1148

- `actions/setup-python@v4` ->
`actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4.9.1`
  - Version: v4.9.1 | Latest: v6.2.0 | Release age: 76d
- Commit:
actions/setup-python@7f4fc3e

- `actions/cache@v4` ->
`actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0`
  - Version: v4.3.0 | Latest: v5.0.4 | Release age: 20d
- Commit:
actions/cache@0057852

- `thollander/actions-comment-pull-request@v2` ->
`thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6
# v2.5.0`
  - Version: v2.5.0 | Latest: v3.0.1 | Release age: 522d
- Commit:
thollander/actions-comment-pull-request@fabd468

- `cachix/install-nix-action@v12` ->
`cachix/install-nix-action@07da2520eebede906fbeefa9dd0a2b635323909d #
v12`
  - Version: v12 | Latest: v31.10.3 | Release age: 12d
- Commit:
cachix/install-nix-action@07da252

- `actions/checkout@v3` ->
`actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0`
  - Version: v3.6.0 | Latest: v6.0.2 | Release age: 88d
- Commit:
actions/checkout@f43a0e5

- `EmbarkStudios/cargo-deny-action@v1` ->
`EmbarkStudios/cargo-deny-action@3f4a782664881cf5725d0ffd23969fcce89fd868
# v1.6.3`
  - Version: v1.6.3 | Latest: v2.0.15 | Release age: 90d
- Commit:
EmbarkStudios/cargo-deny-action@3f4a782

- `actions/checkout@v6` ->
`actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2`
  - Version: v6.0.2 | Latest: v6.0.2 | Release age: 88d
- Commit:
actions/checkout@de0fac2

- `actions-rust-lang/setup-rust-toolchain@v1` ->
`actions-rust-lang/setup-rust-toolchain@150fca883cd4034361b621bd4e6a9d34e5143606
# v1.15.4`
  - Version: v1.15.4 | Latest: v1.15.4 | Release age: 24d
- Commit:
actions-rust-lang/setup-rust-toolchain@150fca8

- `rust-lang/crates-io-auth-action@v1` ->
`rust-lang/crates-io-auth-action@b7e9a28eded4986ec6b1fa40eeee8f8f165559ec
# v1`
  - Version: v1 | Latest: v1.0.4 | Release age: 15d
- Commit:
rust-lang/crates-io-auth-action@b7e9a28

- `actions-rs/cargo@v1` ->
`actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # v1.0.3`
  - Version: v1.0.3 | Latest: v1.0.1 | Release age: 2397d
- Commit:
actions-rs/cargo@844f368

- `actions/upload-artifact@v4` ->
`actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 #
v4.6.2`
  - Version: v4.6.2 | Latest: v3.2.2 | Release age: 22d
- Commit:
actions/upload-artifact@ea165f8

- `actions/download-artifact@v4` ->
`actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 #
v4.3.0`
  - Version: v4.3.0 | Latest: v3.1.0-node20 | Release age: 22d
- Commit:
actions/download-artifact@d3f86a1
- Warnings: 1 security advisory(ies) found, Action has 1 known
advisory(ies)

- `svenstaro/upload-release-action@v2` ->
`svenstaro/upload-release-action@29e53e917877a24fad85510ded594ab3c9ca12de
# 2.11.5`
  - Version: 2.11.5 | Latest: 2.11.5 | Release age: 22d
- Commit:
svenstaro/upload-release-action@29e53e9

- `actions/setup-node@v4` ->
`actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0`
  - Version: v4.4.0 | Latest: v6.3.0 | Release age: 35d
- Commit:
actions/setup-node@49933ea

- `pnpm/action-setup@v3` ->
`pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3`
  - Version: v3 | Latest: v5.0.0 | Release age: 22d
- Commit:
pnpm/action-setup@a3252b7


### Files modified

- `.github/workflows/bench.yml`
- `.github/workflows/coq.yml`
- `.github/workflows/license.yml`
- `.github/workflows/publish.yml`
- `.github/workflows/release.yml`
- `.github/workflows/rust.yml`
- `.github/workflows/tools.yml`

### Security warnings

- 1 security advisory(ies) found
- Action has 1 known advisory(ies)

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
…ding (#728)

## Summary

- Replace `panic!("float32 not supported in Motoko")` with
`str("Float32")` in the Motoko binding generator.
- Add a `float.did` test fixture covering `float32`/`float64` round-trip
methods.

## Why

Motoko added `Float32` in version 1.4.0
([caffeinelabs/motoko#5906](caffeinelabs/motoko#5906)),
updating both the import and export IDL mappings. The spec
(`design/IDL-Motoko.md`) is being updated in a companion PR. This brings
`didc bind --target mo` in line with what `moc` already does when
importing `.did` files directly.

Concretely, any `.did` file using `float32` (e.g. the IC management
canister interface) would previously cause `didc bind --target mo` to
panic at runtime.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
## Summary
- Fix LEB128/SLEB128 fast path silently truncating `Nat`/`Int` values
near the `u64`/`i64` boundary during decoding (ecc0c45)
- Fix `Int::decode` truncating large magnitudes due to fast-path leakage
(d08b8da)
- Bump `candid` 0.10.27 → 0.10.28 and `candid_derive` to match
- Cut `candid_parser` 0.3.2, which moves the previously unreleased
Motoko `Float32` binding fix into a dated release
- Update `CHANGELOG.md` with a 2026-05-20 entry covering both crates

## Test plan
- [x] `cargo check -p candid -p candid_derive -p candid_parser`
- [x] Reviewer to confirm changelog wording / release scope
- [ ] Publish to crates.io after merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
….29 (#732)

## Fix: `text_fast_path` leaks into nested maps with non-text keys

### Problem

Decoding a `BTreeMap<String, V>` where `V` is an enum containing a
`BTreeMap<K, V2>` with a non-`String` key type fails with a subtyping
error:

Type mismatch at de.rs:1380

The error fires in `deserialize_enum` when `expect_type` is not a
`TypeInner::Variant`, even though the wire type correctly encodes the
key as a
Candid variant.

### Root cause

`deserialize_map` has a fast path for `BTreeMap<String, V>`: when the
key type
is `Text`, it sets `self.text_fast_path = true` on the deserializer
**globally**
before entering `visitor.visit_map(...)`. This flag is then visible to
any code
that runs inside the visitor — including `next_key_seed` of a **nested**
inner
map.

`next_key_seed` for `Style::Map` checked `self.de.text_fast_path` to
decide
whether to skip updating `expect_type`/`wire_type` for the key:

```rust
if !self.de.text_fast_path {          // ← reads global flag, not this map's flag
    self.de.expect_type = expect.0.clone();
    self.de.wire_type   = wire.0.clone();
} 
```

When the inner map has non-text keys (e.g. an enum), the outer map's
text_fast_path = true causes next_key_seed to skip the type update. The
deserializer then calls deserialize_enum with a stale expect_type
(whatever
was left over from the enclosing context — a vec type, a record, etc.),
which is not TypeInner::Variant, triggering the crash.

### Fix

Add key_text_fast: bool to Style::Map so that each map compound carries
its
own fast-path decision, independent of any enclosing map's state.
next_key_seed now:

1. uses style.key_text_fast (not the global flag) to decide whether the
per-entry add_cost(4) was pre-paid, and
2. sets self.de.text_fast_path = key_text_fast immediately before
calling the
key deserializer, so deserialize_str's fast path is engaged only when
this map's key is actually Text.

No changes to next_value_seed are required: after next_key_seed sets
text_fast_path correctly, next_value_seed's any_fast check (which reads
self.de.text_fast_path) naturally reflects the current map's key type.

### Regression test

test_nested_map_non_text_key in tests/serde.rs encodes and round-trips:

```rust
BTreeMap<String, Value>
    "fun" => Value::Fun(BTreeMap<MapKey, u32>)  // inner map with enum key
    "lit" => Value::Lit(String)
```

This test panicked with "Type mismatch" before the fix and passes after.

---------

Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Make the candid ui deployable with icp-cli
Update the candid ui cansiter to use the new TS libraries.
Update after: This is to be updated after
#735 is merged

There's a been a "temporary hack" since 2022 - I spot checked canisters
and they seem to have the standard "candid:service" metadata, eg:
```
# bitcoin minter
icp canister metadata -n ic  mqygn-kiaaa-aaaar-qaadq-cai "candid:service"
```
…ie (#737)

Don't merge before #736

This bumps the cdk to a more recent version so we can use environment
variables and adds asset certification.

Next steps will be to:
- use environment variable to figure out the canister id on the
frontend.
- Update the vite config so the frontend can be iterated on without the
canister (if possible)
Brings master's ~45 commits (releases up to candid 0.10.29 / candid_parser
0.3.2 / didc 0.6.1 / ic_principal 0.1.3, decode/encode perf work, the
icp-cli/Vite UI rewrite, doc-comment preservation #707, collect-all subtype
errors #725) onto the next branch while preserving next's breaking v-next
features: ArgType return/arg name collection (#684), TypeKey named-type keys
(#590, re-applied on next), the pretty-printing combinator (#668), and the
JS/TS idlService/idlInitArgs exports (#665).

Conflict resolution:
- 16 .d.ts/.js/.mo/.rs goldenfiles regenerated from merged bindings
  (UPDATE_GOLDENFILES=1) — output now carries BOTH master's @icp-sdk/core
  imports AND next's idlService/idlInitArgs exports.
- Cargo.lock / bench Cargo.lock regenerated; crate versions take master's.
- 7 source files hand-merged: master's subtype-error rewrite (#725) re-threaded
  over next's ArgType signatures; doc-comment emission folded into next's
  pretty-printing combinator; doc-comment fields kept alongside TypeKey/ArgType
  types and the @icp-sdk TypeScript imports.
- candid_parser/typing.rs (auto-merged but semantically broken): master's new
  validate_type recursion guard adapted to TypeKey-keyed env and ArgType args.

Verified: cargo check/test pass under default, --no-default-features, and
--features all; clippy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@raymondk raymondk requested a review from a team as a code owner June 19, 2026 01:10
@zeropath-ai

zeropath-ai Bot commented Jun 19, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to bab84c6.

Security Overview
Detected Code Changes

The diff is too large to display a summary of code changes.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Name Max Mem (Kb) Encode Decode
blob 4_224 4_207_540 ($\textcolor{red}{0.02\%}$) 2_118_978 ($\textcolor{red}{0.03\%}$)
btreemap 75_456 529_877_496 ($\textcolor{green}{-88.67\%}$) 10_166_251_585 ($\textcolor{green}{-32.48\%}$)
double_option (new) 128 1_314_207 18_289_832
large_variant (new) 320 1_032_169 19_052_293
multi_arg (new) 64 550_384 6_202_873
nns 192 1_618_545 ($\textcolor{red}{5.26\%}$) 3_226_090 ($\textcolor{red}{4.63\%}$)
nns_list_neurons (new) 1_152 6_562_306 145_983_869
nns_list_proposal 1_216 ($\textcolor{red}{11.76\%}$) 6_578_795 ($\textcolor{red}{2.97\%}$) 34_255_898 ($\textcolor{green}{-14.46\%}$)
option_list 128 726_498 ($\textcolor{green}{-90.81\%}$) 15_264_128 ($\textcolor{green}{-36.74\%}$)
result_variant (new) 192 1_375_762 15_109_368
subtype_decode (new) 512 2_660_866 45_646_650
text 6_336 4_204_172 ($\textcolor{red}{0.02\%}$) 7_877_160 ($\textcolor{red}{0.00\%}$)
variant_list 128 722_013 ($\textcolor{green}{-90.87\%}$) 14_625_246 ($\textcolor{green}{-35.67\%}$)
vec_int16 12_480 ($\textcolor{green}{-25.29\%}$) 8_404_581 ($\textcolor{green}{-93.21\%}$) 249_583_138 ($\textcolor{green}{-75.21\%}$)
vec_nat (new) 11_008 66_046_656 276_026_428
vec_nat32 (new) 24_768 16_793_189 243_291_963
vec_nat64 (new) 49_344 33_570_389 251_680_845
vec_service (new) 64 682_071 90_490_883
wide_record (new) 1_152 3_255_978 41_497_077
  • Parser cost: 15_277_663 ($\textcolor{green}{-2.97\%}$)
  • Extra args: 2_060_654 ($\textcolor{green}{-15.75\%}$)
Click to see raw report
---------------------------------------------------

Benchmark: blob
  total:
    instructions: 6.33 M (0.03%) (change within noise threshold)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 4.21 M (0.02%) (change within noise threshold)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 2.12 M (0.03%) (change within noise threshold)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: btreemap
  total:
    instructions: 10.70 B (improved by 45.80%)
    heap_increase: 1179 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 529.88 M (improved by 88.67%)
    heap_increase: 159 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 10.17 B (improved by 32.48%)
    heap_increase: 1020 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: double_option (new)
  total:
    instructions: 19.61 M (new)
    heap_increase: 2 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 1.31 M (new)
    heap_increase: 0 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 18.29 M (new)
    heap_increase: 2 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: extra_args
  total:
    instructions: 2.06 M (improved by 15.75%)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: large_variant (new)
  total:
    instructions: 20.09 M (new)
    heap_increase: 5 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 1.03 M (new)
    heap_increase: 2 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 19.05 M (new)
    heap_increase: 3 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: multi_arg (new)
  total:
    instructions: 6.76 M (new)
    heap_increase: 1 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 550.38 K (new)
    heap_increase: 1 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 6.20 M (new)
    heap_increase: 0 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: nns
  total:
    instructions: 20.95 M (-1.17%) (change within noise threshold)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

  0. Parsing (scope):
    calls: 1 (no change)
    instructions: 15.28 M (improved by 2.97%)
    heap_increase: 3 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 1.62 M (regressed by 5.26%)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 3.23 M (regressed by 4.63%)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: nns_list_neurons (new)
  total:
    instructions: 152.55 M (new)
    heap_increase: 18 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 6.56 M (new)
    heap_increase: 18 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 145.98 M (new)
    heap_increase: 0 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: nns_list_proposal
  total:
    instructions: 40.84 M (improved by 12.06%)
    heap_increase: 19 pages (regressed by 11.76%)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 6.58 M (regressed by 2.97%)
    heap_increase: 5 pages (regressed by 66.67%)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 34.26 M (improved by 14.46%)
    heap_increase: 14 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: option_list
  total:
    instructions: 15.99 M (improved by 50.08%)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 726.50 K (improved by 90.81%)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 15.26 M (improved by 36.74%)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: result_variant (new)
  total:
    instructions: 16.49 M (new)
    heap_increase: 3 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 1.38 M (new)
    heap_increase: 1 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 15.11 M (new)
    heap_increase: 2 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: subtype_decode (new)
  total:
    instructions: 48.31 M (new)
    heap_increase: 8 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 2.66 M (new)
    heap_increase: 8 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 45.65 M (new)
    heap_increase: 0 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: text
  total:
    instructions: 12.08 M (0.01%) (change within noise threshold)
    heap_increase: 99 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 4.20 M (0.02%) (change within noise threshold)
    heap_increase: 66 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 7.88 M (0.00%) (change within noise threshold)
    heap_increase: 33 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: variant_list
  total:
    instructions: 15.35 M (improved by 49.91%)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 722.01 K (improved by 90.87%)
    heap_increase: 0 pages (no change)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 14.63 M (improved by 35.67%)
    heap_increase: 2 pages (no change)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_int16
  total:
    instructions: 257.99 M (improved by 77.18%)
    heap_increase: 195 pages (improved by 25.29%)
    stable_memory_increase: 0 pages (no change)

  1. Encoding (scope):
    calls: 1 (no change)
    instructions: 8.40 M (improved by 93.21%)
    heap_increase: 130 pages (improved by 50.19%)
    stable_memory_increase: 0 pages (no change)

  2. Decoding (scope):
    calls: 1 (no change)
    instructions: 249.58 M (improved by 75.21%)
    heap_increase: 65 pages (regressed from 0)
    stable_memory_increase: 0 pages (no change)

---------------------------------------------------

Benchmark: vec_nat (new)
  total:
    instructions: 342.08 M (new)
    heap_increase: 172 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 66.05 M (new)
    heap_increase: 33 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 276.03 M (new)
    heap_increase: 139 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: vec_nat32 (new)
  total:
    instructions: 260.09 M (new)
    heap_increase: 387 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 16.79 M (new)
    heap_increase: 258 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 243.29 M (new)
    heap_increase: 129 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: vec_nat64 (new)
  total:
    instructions: 285.25 M (new)
    heap_increase: 771 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 33.57 M (new)
    heap_increase: 514 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 251.68 M (new)
    heap_increase: 257 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: vec_service (new)
  total:
    instructions: 91.18 M (new)
    heap_increase: 1 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 682.07 K (new)
    heap_increase: 1 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 90.49 M (new)
    heap_increase: 0 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Benchmark: wide_record (new)
  total:
    instructions: 44.76 M (new)
    heap_increase: 18 pages (new)
    stable_memory_increase: 0 pages (new)

  1. Encoding (scope):
    calls: 1 (new)
    instructions: 3.26 M (new)
    heap_increase: 18 pages (new)
    stable_memory_increase: 0 pages (new)

  2. Decoding (scope):
    calls: 1 (new)
    instructions: 41.50 M (new)
    heap_increase: 0 pages (new)
    stable_memory_increase: 0 pages (new)

---------------------------------------------------

Summary:
  instructions:
    status:   Improvements and new benchmarks 🟢➕
    counts:   [total 20 | regressed 0 | improved 6 | new 11 | unchanged 3]
    change:   [max +1.69K | p75 -247.41K | median -5.60M | p25 -16.05M | min -9.04B]
    change %: [max +0.03% | p75 -1.17% | median -15.75% | p25 -49.91% | min -77.18%]

  heap_increase:
    status:   Regressions, improvements, and new benchmarks 🔴🟢➕
    counts:   [total 20 | regressed 1 | improved 1 | new 11 | unchanged 7]
    change:   [max +2 | p75 0 | median 0 | p25 0 | min -66]
    change %: [max +11.76% | p75 0.00% | median 0.00% | p25 0.00% | min -25.29%]

  stable_memory_increase:
    status:   New benchmarks added ➕
    counts:   [total 20 | regressed 0 | improved 0 | new 11 | unchanged 9]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------

Only significant changes:
| status | name                           | calls |     ins |  ins Δ% |    HI |   HI Δ% | SMI |  SMI Δ% |
|--------|--------------------------------|-------|---------|---------|-------|---------|-----|---------|
|   +    | nns::1. Encoding               |     1 |   1.62M |  +5.26% |     0 |   0.00% |   0 |   0.00% |
|   +    | nns::2. Decoding               |     1 |   3.23M |  +4.63% |     0 |   0.00% |   0 |   0.00% |
|   +    | nns_list_proposal::1. Encoding |     1 |   6.58M |  +2.97% |     5 | +66.67% |   0 |   0.00% |
|   -    | nns::0. Parsing                |     1 |  15.28M |  -2.97% |     3 |   0.00% |   0 |   0.00% |
|  +/-   | nns_list_proposal              |       |  40.84M | -12.06% |    19 | +11.76% |   0 |   0.00% |
|   -    | nns_list_proposal::2. Decoding |     1 |  34.26M | -14.46% |    14 |   0.00% |   0 |   0.00% |
|   -    | extra_args                     |       |   2.06M | -15.75% |     0 |   0.00% |   0 |   0.00% |
|   -    | btreemap::2. Decoding          |     1 |  10.17B | -32.48% | 1.02K |   0.00% |   0 |   0.00% |
|   -    | variant_list::2. Decoding      |     1 |  14.63M | -35.67% |     2 |   0.00% |   0 |   0.00% |
|   -    | option_list::2. Decoding       |     1 |  15.26M | -36.74% |     2 |   0.00% |   0 |   0.00% |
|   -    | btreemap                       |       |  10.70B | -45.80% | 1.18K |   0.00% |   0 |   0.00% |
|   -    | variant_list                   |       |  15.35M | -49.91% |     2 |   0.00% |   0 |   0.00% |
|   -    | option_list                    |       |  15.99M | -50.08% |     2 |   0.00% |   0 |   0.00% |
|  +/-   | vec_int16::2. Decoding         |     1 | 249.58M | -75.21% |    65 |   +inf% |   0 |   0.00% |
|   -    | vec_int16                      |       | 257.99M | -77.18% |   195 | -25.29% |   0 |   0.00% |
|   -    | btreemap::1. Encoding          |     1 | 529.88M | -88.67% |   159 |   0.00% |   0 |   0.00% |
|   -    | option_list::1. Encoding       |     1 | 726.50K | -90.81% |     0 |   0.00% |   0 |   0.00% |
|   -    | variant_list::1. Encoding      |     1 | 722.01K | -90.87% |     0 |   0.00% |   0 |   0.00% |
|   -    | vec_int16::1. Encoding         |     1 |   8.40M | -93.21% |   130 | -50.19% |   0 |   0.00% |
|  new   | double_option                  |       |  19.61M |         |     2 |         |   0 |         |
|  new   | double_option::1. Encoding     |     1 |   1.31M |         |     0 |         |   0 |         |
|  new   | double_option::2. Decoding     |     1 |  18.29M |         |     2 |         |   0 |         |
|  new   | large_variant                  |       |  20.09M |         |     5 |         |   0 |         |
|  new   | large_variant::1. Encoding     |     1 |   1.03M |         |     2 |         |   0 |         |
|  new   | large_variant::2. Decoding     |     1 |  19.05M |         |     3 |         |   0 |         |
|  ...   | ... 2 rows omitted ...         |       |         |         |       |         |     |         |
|  new   | multi_arg::2. Decoding         |     1 |   6.20M |         |     0 |         |   0 |         |
|  new   | nns_list_neurons               |       | 152.55M |         |    18 |         |   0 |         |
|  new   | nns_list_neurons::1. Encoding  |     1 |   6.56M |         |    18 |         |   0 |         |
|  new   | nns_list_neurons::2. Decoding  |     1 | 145.98M |         |     0 |         |   0 |         |
|  new   | result_variant                 |       |  16.49M |         |     3 |         |   0 |         |
|  new   | result_variant::1. Encoding    |     1 |   1.38M |         |     1 |         |   0 |         |
|  new   | result_variant::2. Decoding    |     1 |  15.11M |         |     2 |         |   0 |         |
|  new   | subtype_decode                 |       |  48.31M |         |     8 |         |   0 |         |
|  new   | subtype_decode::1. Encoding    |     1 |   2.66M |         |     8 |         |   0 |         |
|  new   | subtype_decode::2. Decoding    |     1 |  45.65M |         |     0 |         |   0 |         |
|  new   | vec_nat                        |       | 342.08M |         |   172 |         |   0 |         |
|  new   | vec_nat32                      |       | 260.09M |         |   387 |         |   0 |         |
|  new   | vec_nat32::1. Encoding         |     1 |  16.79M |         |   258 |         |   0 |         |
|  new   | vec_nat32::2. Decoding         |     1 | 243.29M |         |   129 |         |   0 |         |
|  new   | vec_nat64                      |       | 285.25M |         |   771 |         |   0 |         |
|  new   | vec_nat64::1. Encoding         |     1 |  33.57M |         |   514 |         |   0 |         |
|  new   | vec_nat64::2. Decoding         |     1 | 251.68M |         |   257 |         |   0 |         |
|  new   | vec_nat::1. Encoding           |     1 |  66.05M |         |    33 |         |   0 |         |
|  new   | vec_nat::2. Decoding           |     1 | 276.03M |         |   139 |         |   0 |         |
|  new   | vec_service                    |       |  91.18M |         |     1 |         |   0 |         |
|  new   | vec_service::1. Encoding       |     1 | 682.07K |         |     1 |         |   0 |         |
|  new   | vec_service::2. Decoding       |     1 |  90.49M |         |     0 |         |   0 |         |
|  new   | wide_record                    |       |  44.76M |         |    18 |         |   0 |         |
|  new   | wide_record::1. Encoding       |     1 |   3.26M |         |    18 |         |   0 |         |
|  new   | wide_record::2. Decoding       |     1 |  41.50M |         |     0 |         |   0 |         |

ins = instructions, HI = heap_increase, SMI = stable_memory_increase, Δ% = percent change

---------------------------------------------------
Successfully persisted results to canbench_results.yml

@raymondk raymondk marked this pull request as draft June 23, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.