Skip to content

feat(ts): translate Vec<u8> and [u8] edits and sorts - #214

Merged
kixelated merged 6 commits into
mainfrom
quest/m3/ts-byte-edits
Oct 29, 2026
Merged

kixelated merged 6 commits into
mainfrom
quest/m3/ts-byte-edits

Conversation

@kixelated

@kixelated kixelated commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

rust2-ts refused retain, retain_mut, dedup, dedup_by, dedup_by_key, insert, remove, and swap_remove on a Vec<u8>, and last, reverse, swap, and the six sorts on a [u8]: the mappings in library.rs skipped u8 elements, which are an rt.ByteVec or rt.ByteSlice rather than an array, and nothing mapped them instead. Found by #204. No moq consumer: rust2 aims to support all of std.

Approach

  • Every !is_u8 skip in library.rs now has a byte counterpart. Those were all of them; the other Vec and slice mappings already handled bytes.
  • Vec<u8>: new rt.byteVecInsert, Remove, SwapRemove, Retain, RetainMut, Dedup, DedupByMut, and DedupByKeyMut, which edit the Uint8Array in place (copyWithin for the shifts). The representation is unchanged.
  • [u8]: rt.byteSliceLast and rt.byteSliceSwap, beside byteSliceFirst. reverse and the sorts without a closure call the typed array's own reverse and sort on byteSliceView. A typed array sorts by value, and equal bytes can't be told apart, so stability doesn't matter. The closure sorts run rt.sliceSort* over the view, which now take any indexable.
  • retain_mut, dedup_by, and dedup_by_key give their closure a &mut, and a byte is a value JS copies, so it has to be passed as an rt.Place. place_call now lists those three for Vec, and the mapping picks a *Mut variant that passes an AtIndex whenever the element needs_place. That fixes Vec<u16> and other copied elements too, which were refused for the same reason. One problem, one mechanism, so it's in this PR.
  • vecRetain, vecDedupBy, and the byte versions share two index-based helpers, retainAt and dedupAt, so the logic exists once.
  • ("slice", "reverse") is now elements(s).reverse() for every element type, and rt.sliceReverse is deleted.

Tests: a new edits::bytes case in the lang fixture checks against native wasm32 (50k random cases; 495,916 in total with the exhaustive short ones):

  • each method on every short prefix of the input (empty, one byte, two bytes) and on the whole input;
  • a subslice that starts past offset 0 of its storage (v[1..]'s sort, reverse, swap, and last);
  • out-of-bounds panics from insert, remove, swap_remove, swap, and a subslice range;
  • stable sort_by_key with tied keys, and unstable sorts only by keys or comparators with no ties, so std's order is the only valid one;
  • closures that log their arguments and change bytes through their places;
  • u16 versions of retain_mut, dedup_by, and dedup_by_key.

As a mutation check, breaking byteVecDedupByMut's argument order and byteVecSwapRemove made the differential report 263 differences. There are no unwind tests.

reject used <[u8]>::sort as its example of an unsupported call. It now uses rotate_left, which is still unsupported, so line numbers don't shift.

Census

moq-net: 3089 → 3087 refusals (the two <[u8]>::last calls in zlib-rs inflate.rs). model and kio are unchanged.

Impact

  • Output: the methods above now translate on Vec<u8> and [u8], and retain_mut, dedup_by, and dedup_by_key translate on a Vec of any element JS copies.
  • Runtime additions: rt.byteSliceLast, rt.byteSliceSwap, rt.byteVecInsert, rt.byteVecRemove, rt.byteVecSwapRemove, rt.byteVecRetain, rt.byteVecRetainMut, rt.byteVecDedup, rt.byteVecDedupByMut, rt.byteVecDedupByKeyMut, rt.vecRetainMut, rt.vecDedupByMut, and rt.vecDedupByKeyMut. rt.sliceSort, rt.sliceSortBy, and rt.sliceSortByKey accept any indexable.
  • Breaking: rt.sliceReverse is removed. There's a MIGRATE.md entry.
  • The codec's output is unchanged (its snapshot passes), so no bench run.

Alternatives

  • Running every byte method over a byteSliceView: for last and swap that builds a view on each call, which costs several times a ByteSlice. So those got dedicated functions like first; only the O(n) methods use the view.
  • Lending places only for bytes: Vec<u16>::retain_mut would still be refused for the same reason.

Follow-ups

None new. u8::rotate_left and [u8]::rotate_left are still unsupported; the reject fixture records the second.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 4 commits October 28, 2026 21:22
Quest-Claim: 3c0f810a2cea45eb
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… finish the quest

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	ts/fixtures/lang/expected/harness.ts
@kixelated kixelated changed the title Edits of byte vectors and slices feat(ts): translate Vec<u8> and [u8] edits and sorts Oct 29, 2026
@kixelated
kixelated marked this pull request as ready for review October 29, 2026 07:40
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T09:31:17.464364Z c8a468b New commits
🔒 Security Review ✅ Completed 2026-10-29T09:33:16.329324Z c8a468b New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed commit: 28d7467

No actionable bugs found in the changed mappings and runtime paths. Reusing index-based retain/dedup helpers while lending copied elements through AtIndex is a reasonable shared fix for bytes and other scalar elements. The byte-specific paths preserve slice offsets and vector length/capacity boundaries; direct numeric typed-array sorting avoids unnecessary comparator machinery. The added differential cases cover mutation callbacks, dedup argument order, empty inputs, subslices and bounds failures.

Verification: static diff, runtime helpers, lowering/place-call handling and generated fixture inspection only. No tests, differential or mutation runs, builds or benchmarks performed; reported results were not independently reproduced. Unwind behavior was not validated.

(Written by OpenAI)

# Conflicts:
#	ts/fixtures/lang/expected/harness.ts
#	ts/fixtures/lang/src/harness.rs
#	ts/fixtures/reject/census.md
@kixelated
kixelated merged commit 7d20e9c into main Oct 29, 2026
1 check passed
@kixelated
kixelated deleted the quest/m3/ts-byte-edits branch October 29, 2026 10:02
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.

1 participant