Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion quest/m3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,3 @@ generic std gap is planned here even when moq never calls it.
- [rust2-ts with no ts.toml](/quest/m3/ts-configless.md) - a crate's whole `pub` API translates with no config and no bound items
- [Buf on a deque of bytes](/quest/m3/ts-vecdeque-buf.md) - `bytes`' `Buf` for a deque of bytes translates
- [std's panic messages hold std's capacity](/quest/m3/ts-panic-payload-capacity.md) - a hook reads native's `String` capacity from std's own formatted panics
- [A B-tree drops as std's does](/quest/m3/ts-btree-drop-order.md) - keys and values drop node by node, in std's order
16 changes: 0 additions & 16 deletions quest/m3/ts-btree-drop-order.md

This file was deleted.

9 changes: 5 additions & 4 deletions ts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1025,10 +1025,11 @@ they need.
where JS fails to allocate a byte `Vec`'s or `VecDeque`'s `Uint8Array` (decided with the
maintainer on 2026-11-03). A `LinkedList` is nodes linked both ways, as std's are,
so `append` is O(1) and `split_off` walks from the nearer end; each node is the place
`iter_mut` and `front_mut` lend of an item JS copies. Dropping a whole map or set drops its entries in the
runtime's order, keys' for a B-tree, not std's node by node: std leaves that order
undocumented ([#272](https://github.com/moq-dev/rust2/pull/272)). Maintainer's decision
on 2026-10-30; a map's `IntoIter` still drops in std's order.
`iter_mut` and `front_mut` lend of an item JS copies. Dropping a whole hash map or set drops its entries in the
runtime's order, not hashbrown's: std leaves that order undocumented
([#272](https://github.com/moq-dev/rust2/pull/272)). Maintainer's decision on 2026-10-30.
A whole B-tree drops as std's `drop_tree` does, node by node in postorder, and its
`IntoIter` in key order, as std's does.
- A slice's `sort` and `sort_unstable` are std's driftsort and ipnsort, ported to the
runtime with the choices std makes by the element's size on wasm32 and whether it is
`Freeze` and `Copy`, so each calls the comparator in std's order and leaves equal
Expand Down
37 changes: 37 additions & 0 deletions ts/fixtures/lang/collections/expected/collections.Tagged.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Generated by rust2-ts. Do not edit.

import * as rs from "./rs.ts";

/**
* A B-tree value, or a set's key, that logs its tag as it drops, ordered by it. A clone's
* tag is 1000 past the original's.
*/
export class Tagged {
_0: rs.u16;
_1: rs.RefCell<rs.Vec<rs.u16>>;

constructor(_0: rs.u16, _1: rs.RefCell<rs.Vec<rs.u16>>) {
this._0 = _0;
this._1 = _1;
}

[Symbol.dispose](): void {
drop$ops_Drop(this);
}
}

export function drop$ops_Drop(self: Tagged): void {
const _5: rs.RefCell<rs.Vec<rs.u16>> = rs.refCellBorrowMut(self._1);
_5.value.items.push(self._0);
rs.refMutRelease(_5);
}

export function clone$Clone(self: Tagged): Tagged {
return new Tagged(rs.u16Add(self._0, 1000), self._1);
}

export function cmp$cmp_Ord(self: Tagged, other: Tagged): rs.Ordering {
return rs.cmp(self._0, other._0);
}

//# sourceMappingURL=collections.Tagged.ts.map
207 changes: 192 additions & 15 deletions ts/fixtures/lang/collections/expected/collections.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated by rust2-ts. Do not edit.

import * as rs from "./rs.ts";
import { copy$Option_collections_Tally, copy$array_collections_Quirky, copy$array_tuple2_u8_u16, copy$array_tuple2_u8_u8, copy$array_u8, copy$collections_Bumped, copy$collections_Quirky, copy$collections_Tally, copy$collections_Wrap_u8, copy$tuple2_u8_collections_Tally, copy$tuple2_u8_u16, copy$tuple2_u8_u8, drop$Option_tuple2_collections_Logged_collections_Logged, drop$ops_Range_collections_Logged, drop$tuple2_collections_Logged_collections_Logged, drop$tuple2_ops_Bound_collections_Logged_ops_Bound_collections_Logged, drop$tuple2_sync_Arc_collections_Picky_u8 } from "./lib.ts";
import { copy$Option_collections_Tally, copy$array_collections_Quirky, copy$array_tuple2_u8_u16, copy$array_tuple2_u8_u8, copy$array_u8, copy$collections_Bumped, copy$collections_Quirky, copy$collections_Tally, copy$collections_Wrap_u8, copy$tuple2_u8_collections_Tally, copy$tuple2_u8_u16, copy$tuple2_u8_u8, drop$Option_tuple2_collections_Logged_collections_Logged, drop$Option_tuple2_u16_collections_Tagged, drop$collections_BTreeMap_u16_collections_Tagged, drop$ops_Range_collections_Logged, drop$tuple2_collections_Logged_collections_Logged, drop$tuple2_ops_Bound_collections_Logged_ops_Bound_collections_Logged, drop$tuple2_sync_Arc_collections_Picky_u8 } from "./lib.ts";
import type * as Boxed from "./collections.Boxed.ts";
import * as Bumped from "./collections.Bumped.ts";
import * as ByRef from "./collections.ByRef.ts";
Expand All @@ -23,6 +23,7 @@ import * as Probe from "./collections.Probe.ts";
import * as Quirky from "./collections.Quirky.ts";
import * as Rank from "./collections.Rank.ts";
import * as Right from "./collections.Right.ts";
import * as Tagged from "./collections.Tagged.ts";
import * as Tally from "./collections.Tally.ts";
import * as Window from "./collections.Window.ts";
import * as Wrap from "./collections.Wrap.ts";
Expand Down Expand Up @@ -5926,36 +5927,34 @@ export function btreeExtracts(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec):
rs.byteVecPush(out, _302 === undefined ? 1 : 0);
drop$Option_tuple2_collections_Logged_collections_Logged(_302);
rs.drop(it4);
rs.iterForEach(rs.btreeIter(map2, rs.drop, rs.drop), (a0: [Logged.Logged, Logged.Logged]): undefined => {
drop$tuple2_collections_Logged_collections_Logged(a0);
}, true);
rs.btreeDrop(map2, rs.drop, rs.drop);
const bytes: rs.BTreeMap<rs.u16, rs.u8> = rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, rs.u8>;
const window: (a0: rs.u16, a1: rs.u16) => Window.Window = (lo2: rs.u16, hi2: rs.u16): Window.Window => {
return { lo: lo2, hi: hi2, log };
};
const _315: Window.Window = window(0, 9);
rs.iterForEach(rs.btreeExtractIfMut(bytes, rs.boundsOf(_315, Window.startBound$ops_RangeBounds_u16, Window.endBound$ops_RangeBounds_u16), (_26: rs.u16, _310: rs.Place<rs.u8>): boolean => {
const _314: Window.Window = window(0, 9);
rs.iterForEach(rs.btreeExtractIfMut(bytes, rs.boundsOf(_314, Window.startBound$ops_RangeBounds_u16, Window.endBound$ops_RangeBounds_u16), (_26: rs.u16, _310: rs.Place<rs.u8>): boolean => {
return true;
}), (_a02: [rs.u16, rs.u8]): undefined => {
}), (_a0: [rs.u16, rs.u8]): undefined => {
undefined;
});
rs.btreeInsert(bytes, 1, 1);
rs.btreeRemove(bytes, 1);
const _326: Window.Window = window(0, 9);
rs.iterForEach(rs.btreeExtractIfMut(bytes, rs.boundsOf(_326, Window.startBound$ops_RangeBounds_u16, Window.endBound$ops_RangeBounds_u16), (_27: rs.u16, _311: rs.Place<rs.u8>): boolean => {
const _325: Window.Window = window(0, 9);
rs.iterForEach(rs.btreeExtractIfMut(bytes, rs.boundsOf(_325, Window.startBound$ops_RangeBounds_u16, Window.endBound$ops_RangeBounds_u16), (_27: rs.u16, _311: rs.Place<rs.u8>): boolean => {
return true;
}), (_a03: [rs.u16, rs.u8]): undefined => {
}), (_a02: [rs.u16, rs.u8]): undefined => {
undefined;
});
const _331: rs.Iter<[rs.u16, rs.u8]> = rs.iterMap(new rs.Range(0, n), (k3: rs.u16): [rs.u16, rs.u8] => {
const _330: rs.Iter<[rs.u16, rs.u8]> = rs.iterMap(new rs.Range(0, n), (k3: rs.u16): [rs.u16, rs.u8] => {
return [k3, k3 & 0xff] as [rs.u16, rs.u8];
});
rs.btreeExtend(bytes, _331);
const _336: Window.Window = window(rs.u16Div(lo, 2), rs.u16Div(hi, 2));
const _343: (a0: rs.u16, a1: rs.Place<rs.u8>) => boolean = (k4: rs.u16, _314: rs.Place<rs.u8>): boolean => {
rs.btreeExtend(bytes, _330);
const _335: Window.Window = window(rs.u16Div(lo, 2), rs.u16Div(hi, 2));
const _342: (a0: rs.u16, a1: rs.Place<rs.u8>) => boolean = (k4: rs.u16, _315: rs.Place<rs.u8>): boolean => {
return rs.u16Rem(k4, every) === 0;
};
rs.iterExtendBytes(out, rs.iterMap(rs.iterSlice(rs.iterToVec(rs.btreeExtractIfMut(bytes, rs.boundsOf(_336, Window.startBound$ops_RangeBounds_u16, Window.endBound$ops_RangeBounds_u16), _343), "next", 4).items), (_210: [rs.u16, rs.u8]): rs.u8 => {
rs.iterExtendBytes(out, rs.iterMap(rs.iterSlice(rs.iterToVec(rs.btreeExtractIfMut(bytes, rs.boundsOf(_335, Window.startBound$ops_RangeBounds_u16, Window.endBound$ops_RangeBounds_u16), _342), "next", 4).items), (_210: [rs.u16, rs.u8]): rs.u8 => {
return _210[1];
}), undefined, true);
rs.iterExtendBytes(out, rs.iterFlatMap(rs.iterSlice(rs.refCellReplace(log, new rs.Vec()).items), (e: rs.u16): Uint8Array => {
Expand Down Expand Up @@ -6451,4 +6450,182 @@ export function btreeBorrows(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec):
put(out, part25);
}

/**
* Whole B-trees whose entries log as they drop, which std drops node by node, each node's
* entries in order after its children's: maps built by random, ascending, and descending
* inserts and by `collect`, emptied in part by removals that merge nodes, cleared, assigned
* over, retained, split, cloned, and nested, sets, and `IntoIter`, which drops what it still
* holds in key order. The first byte sets how many entries, up to 297 so trees reach height
* 2, and the rest seed the keys. Each drop is logged, with a mark between the steps.
*/
export function btreeDrops(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void {
let _201!: rs.u16;
const log: rs.RefCell<rs.Vec<rs.u16>> = new rs.RefCell(new rs.Vec());
const tag: (a0: rs.u16) => Tagged.Tagged = (k4: rs.u16): Tagged.Tagged => {
return new Tagged.Tagged(k4, log);
};
const mark: (a0: rs.u16) => undefined = (m: rs.u16): undefined => {
const _55: rs.RefCell<rs.Vec<rs.u16>> = rs.refCellBorrowMut(log);
_55.value.items.push(61440 | m);
rs.refMutRelease(_55);
};
const n: rs.u16 = rs.u16Div(rs.u16Mul(option_unwrapOr$1fr498u(rs.byteSliceFirst(data), 0) as rs.u16, 7), 6);
let state: rs.u32 = (rs.iterFold(rs.iterSlice(rs.byteSliceView(data)), 2654435769, (s: rs.u32, _32: rs.u8): rs.u32 => {
return (rs.intRotateLeft(s, 5, 32, false) ^ _32 as rs.u32) >>> 0;
}) | 1) >>> 0;
const key: () => rs.u16 = (): rs.u16 => {
state = (state ^ ((state << 13) >>> 0)) >>> 0;
state = (state ^ (state >>> 17)) >>> 0;
state = (state ^ ((state << 5) >>> 0)) >>> 0;
return rs.u32Rem(state, 400) & 0xffff;
};
const random: (a0: rs.u16) => rs.BTreeMap<rs.u16, Tagged.Tagged> = (count: rs.u16): rs.BTreeMap<rs.u16, Tagged.Tagged> => {
const map8: rs.BTreeMap<rs.u16, Tagged.Tagged> = rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, Tagged.Tagged>;
let iterStart9: rs.u16 = 0;
const iterEnd9: rs.u16 = count;
while (true) {
if (!(iterStart9++ < iterEnd9)) {
return map8;
}
const k5: rs.u16 = key();
const _133: Tagged.Tagged = tag(k5);
rs.drop(rs.btreeInsert(map8, k5, _133));
}
};
const _26: rs.u8 = rs.u8Rem(kind, 10);
if (_26 === 0) {
const map: rs.BTreeMap<rs.u16, Tagged.Tagged> = random(n);
mark(0);
rs.btreeDrop(map, undefined, rs.drop);
} else if (_26 === 1) {
rs.btreeDrop(rs.iterFold(new rs.Range(0, n), rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, Tagged.Tagged>, (map9: rs.BTreeMap<rs.u16, Tagged.Tagged>, k8: rs.u16): rs.BTreeMap<rs.u16, Tagged.Tagged> => {
const _65: Tagged.Tagged = tag(k8);
rs.drop(rs.btreeInsert(map9, k8, _65));
return map9;
}), undefined, rs.drop);
mark(0);
rs.btreeDrop(rs.iterFold(rs.iterRev(new rs.Range(0, n)), rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, Tagged.Tagged>, (map10: rs.BTreeMap<rs.u16, Tagged.Tagged>, k9: rs.u16): rs.BTreeMap<rs.u16, Tagged.Tagged> => {
const _66: Tagged.Tagged = tag(k9);
rs.drop(rs.btreeInsert(map10, k9, _66));
return map10;
}), undefined, rs.drop);
} else if (_26 === 2) {
const _57: rs.Iter<[rs.u16, Tagged.Tagged]> = rs.iterMap(rs.vecIntoIter(rs.iterToVec(rs.iterMap(new rs.Range(0, n), (_22: rs.u16): rs.u16 => {
return key();
}), undefined, 2, true)), (k7: rs.u16): [rs.u16, Tagged.Tagged] => {
return [k7, tag(k7)] as [rs.u16, Tagged.Tagged];
});
const map2: rs.BTreeMap<rs.u16, Tagged.Tagged> = rs.btreeCollect(rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, Tagged.Tagged>, rs.iterToVec(_57, undefined, 12, true).items, 12, true, undefined, undefined, rs.drop);
mark(0);
rs.btreeDrop(map2, undefined, rs.drop);
} else if (_26 === 3) {
const map3: rs.BTreeMap<rs.u16, Tagged.Tagged> = random(n);
let iterStart: rs.u16 = 0;
const iterEnd: rs.u16 = n;
while (iterStart++ < iterEnd) {
const k: rs.u16 = key();
if (rs.u16Rem(k, 3) !== 0) {
rs.drop(rs.btreeRemove(map3, k));
}
}
const _85: rs.u16 = rs.u16Div(n, 8);
let iterStart2: rs.u16 = 0;
const iterEnd2: rs.u16 = _85;
while (iterStart2++ < iterEnd2) {
drop$Option_tuple2_u16_collections_Tagged(rs.btreePop(map3));
drop$Option_tuple2_u16_collections_Tagged(rs.btreePop(map3, true));
}
mark(0);
rs.btreeDrop(map3, undefined, rs.drop);
} else if (_26 === 4) {
const set: rs.BTreeSet<Tagged.Tagged> = rs.btreeNew(Tagged.cmp$cmp_Ord) as rs.BTreeSet<Tagged.Tagged>;
let iterStart3: rs.u16 = 0;
const iterEnd3: rs.u16 = n;
while (iterStart3++ < iterEnd3) {
const part2 = key();
const _111: Tagged.Tagged = tag(part2);
rs.btreeAdd(set, _111, rs.drop);
}
const _118: rs.u16 = rs.u16Div(n, 2);
let iterStart4: rs.u16 = 0;
const iterEnd4: rs.u16 = _118;
while (iterStart4++ < iterEnd4) {
const part3 = key();
const _127: Tagged.Tagged = tag(part3);
rs.btreeDelete(set, _127, rs.drop);
_127[Symbol.dispose]();
}
mark(0);
rs.btreeDrop(set, rs.drop);
} else if (_26 === 5) {
const map4: rs.BTreeMap<rs.u16, rs.BTreeMap<rs.u16, Tagged.Tagged>> = rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, rs.BTreeMap<rs.u16, Tagged.Tagged>>;
let iterStart5: rs.u16 = 0;
const iterEnd5: rs.u16 = n;
while (iterStart5++ < iterEnd5) {
const _146: [rs.u16, rs.u16] = [rs.u16Rem(key(), 24), key()];
const k2: rs.u16 = _146[0];
const j: rs.u16 = _146[1];
rs.drop(rs.btreeInsert(rs.entryOrInsertWith(rs.entry(map4, k2), (): rs.BTreeMap<rs.u16, Tagged.Tagged> => {
return rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, Tagged.Tagged>;
}), j, tag(j)));
}
mark(0);
rs.btreeDrop(map4, undefined, drop$collections_BTreeMap_u16_collections_Tagged);
} else if (_26 === 6) {
const iter6: rs.Iter<[rs.u16, Tagged.Tagged]> = rs.btreeIter(random(n), undefined, rs.drop);
let iterStart6: rs.usize = 0;
const iterEnd6: rs.usize = data.length;
while (iterStart6++ < iterEnd6) {
drop$Option_tuple2_u16_collections_Tagged(rs.iterToOption(iter6.next()));
drop$Option_tuple2_u16_collections_Tagged(rs.iterToOption(iter6.nextBack()));
}
mark(0);
rs.drop(iter6);
} else if (_26 === 7) {
let map5: rs.BTreeMap<rs.u16, Tagged.Tagged> = random(n);
mark(0);
rs.btreeClear(map5, undefined, rs.drop);
mark(1);
let iterStart7: rs.u16 = 0;
const iterEnd7: rs.u16 = n;
while ((_201 = iterStart7++) < iterEnd7) {
const k3: rs.u16 = _201;
rs.drop(rs.btreeInsert(map5, k3, tag(k3)));
}
const _210: rs.BTreeMap<rs.u16, Tagged.Tagged> = rs.btreeNew(rs.cmp) as rs.BTreeMap<rs.u16, Tagged.Tagged>;
rs.btreeDrop(map5, undefined, rs.drop);
map5 = _210;
const part = rs.btreeLen(map5) & 0xffff;
mark(part);
rs.btreeDrop(map5, undefined, rs.drop);
} else if (_26 === 8) {
const map6: rs.BTreeMap<rs.u16, Tagged.Tagged> = random(n);
rs.btreeRetain(map6, (k6: rs.u16, _35: Tagged.Tagged): boolean => {
return rs.u16Rem(k6, 5) !== 0;
}, undefined, rs.drop);
mark(0);
const high: rs.BTreeMap<rs.u16, Tagged.Tagged> = rs.btreeSplitOff(map6, 200);
rs.btreeDrop(map6, undefined, rs.drop);
mark(1);
rs.btreeDrop(high, undefined, rs.drop);
} else {
const map7: rs.BTreeMap<rs.u16, Tagged.Tagged> = random(n);
const _239: rs.u16 = rs.u16Div(n, 2);
let iterStart8: rs.u16 = 0;
const iterEnd8: rs.u16 = _239;
while (iterStart8++ < iterEnd8) {
const _249: rs.u16 = key();
rs.drop(rs.btreeRemove(map7, _249));
}
mark(0);
const copy: rs.BTreeMap<rs.u16, Tagged.Tagged> = rs.btreeClone(map7, undefined, Tagged.clone$Clone);
rs.btreeDrop(map7, undefined, rs.drop);
mark(1);
rs.btreeDrop(copy, undefined, rs.drop);
}
rs.iterExtendBytes(out, rs.iterFlatMap(rs.iterSlice(rs.refCellReplace(log, new rs.Vec()).items), (e: rs.u16): Uint8Array => {
return rs.u16ToBeBytes(e);
}, (value: Uint8Array) => rs.iterSlice(value), true, 2), undefined, true);
}

//# sourceMappingURL=collections.ts.map
Loading