diff --git a/quest/m3/README.md b/quest/m3/README.md
index 9563b9e0f..067a0eeb8 100644
--- a/quest/m3/README.md
+++ b/quest/m3/README.md
@@ -35,7 +35,6 @@ generic std gap is planned here even when moq never calls it.
- [A reversed zip's per-pair cost](/quest/m3/ts-zip-rev-overhead.md) - a reversed by-index zip costs per pair what a forward one does, or the gap is explained
- [Whole writes into a lazy cell or thread-local key](/quest/m3/ts-lazy-writes.md) - a whole write through a `&mut` to a `LazyCell`, `LazyLock`, or `LocalKey` keeps its state
- [Type errors at the Rust that made them](/quest/m3/ts-span-precision.md) - a `tsc` error on output names the tail expression or call argument that made it
-- [An Option of numbers in the result slot](/quest/m3/ts-option-slot.md) - `varint_opt`'s `Option` comes back through the slot with no object per call
- [Fresh writes through a zip, a copy, and a repeat](/quest/m3/ts-fresh-shapes.md) - zipping a `Vec<[T; N]>`, reading a `T` out of `Zip::next`, and `copied` or `vec![x; n]` over a `Copy` type translate
- [Python's wake on the loop's own thread](/quest/m3/ffi-python-wake.md) - a wake on the event loop's thread resumes the future with no socket pair
- [Python's call cost](/quest/m3/ffi-python-calls.md) - a call on an object costs what BoltFFI's does, or the gap is explained
diff --git a/quest/m3/ts-option-slot.md b/quest/m3/ts-option-slot.md
deleted file mode 100644
index 8c51ebf72..000000000
--- a/quest/m3/ts-option-slot.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# [S] An Option of numbers in the result slot
-
-## Goal
-
-A translated function that returns an `Option` of numbers alone, as `Decoder::varint_opt`'s
-`Result, E>`, makes no object per call, with every differential test passing
-and no workload on `just ts bench` meaningfully slower in any engine.
-
-## Plan
-
-Left by [#385](https://github.com/moq-dev/rust2/pull/385), which returns a `Result` of
-numbers alone through #160's slot: the slot can't carry an `Option`, so `varint_opt` still
-makes an `rt.Ok` per call. moq-net calls it 8 times against 249 for `varint`, so this is
-low value; take it when a profile or a new caller shows it matters, or with other work on
-the slot.
-
-Public API: the translator's output.
diff --git a/ts/MIGRATE.md b/ts/MIGRATE.md
index 51eaa7607..f1342a181 100644
--- a/ts/MIGRATE.md
+++ b/ts/MIGRATE.md
@@ -49,8 +49,9 @@
whose object its body never makes as its `data`, `start`, and `length`:
`read(buf, form)` is `read(buf.data, buf.start, buf.length, form)`. A caller takes
which from the output. One that returns a `Result` of byte slices
- and scalars, or of numbers alone, returns its error or `undefined`, and leaves the `Ok`'s parts in a
- slot `lib.ts` exports, named for the payload type, such as `out$ref_slice_u8`. If the
+ and scalars, or of numbers alone, an `Option` of one counting as a number, such as
+ `Result , E>`, returns its error or `undefined`, and leaves the `Ok`'s parts in a
+ slot `lib.ts` exports, named for the payload type, such as `out$ref_slice_u8` or `out$Option_u64`. If the
`Ok`'s first part is a number, it returns that, or `undefined` for an error, and leaves
the rest, or the error as `err`, in the slot, such as `out$tuple2_u64_ref_slice_u8`. A root still takes an `rt.ByteSlice` and returns
the `Result`.
diff --git a/ts/README.md b/ts/README.md
index 9739ef5b5..c71a9e812 100644
--- a/ts/README.md
+++ b/ts/README.md
@@ -803,7 +803,8 @@ they need.
the geometric mean, and frame decode at 0.61, 0.56, 0.70, and 0.61, with the A/A route
within 0.04 and encode no slower. A tuple or `Result` of numbers alone is held so only
where it meets a slot below, and its object, such as an `rt.Ok`, counts as made at each
- read that makes it. A return is still a `ByteSlice` but for the `Result`s below.
+ read that makes it. An `Option` of a number is one part, that or `undefined`, as its JS
+ value is. A return is still a `ByteSlice` but for the `Result`s below.
- A function only translated code calls takes each `&[u8]` or `&[u8; N]` parameter as
three, its `data`, `start`, and `length`, which its body holds as that local's parts:
not a root, which the outside calls, a closure, or an `async fn`. One whose object the
@@ -819,8 +820,8 @@ they need.
1.01-1.05 over two runs, with the A/A route within 0.05, Firefox and Bun within their
noise, and Node's varint decode at 1.11-1.15.
- A function of the crate's that only translated code calls and that returns a `Result`
- of byte slices and scalars, or of numbers alone, such as `Result<(u64, &[u8]), E>` or
- `Result`, whose error is one JS
+ of byte slices and scalars, or of numbers alone, such as `Result<(u64, &[u8]), E>`,
+ `Result`, or `Result, E>`, whose error is one JS
value that is never `undefined`, writes the `Ok`'s parts into a module-level slot and returns the error or
`undefined`. The slot is shared by every function returning that payload type, in
`lib.ts` and named for the type as the shims are, as `out$ref_slice_u8` or `out$u64`, so
diff --git a/ts/fixtures/codec/expected/coding/decode.Decoder.ts b/ts/fixtures/codec/expected/coding/decode.Decoder.ts
index 33bf00936..e697df418 100644
--- a/ts/fixtures/codec/expected/coding/decode.Decoder.ts
+++ b/ts/fixtures/codec/expected/coding/decode.Decoder.ts
@@ -1,7 +1,7 @@
// Generated by rust2-ts. Do not edit.
import * as rt from "../rt.ts";
-import { out$bool, out$ref_slice_u8, out$tuple2_u64_ref_slice_u8, out$u16, out$u64, out$u8 } from "../lib.ts";
+import { out$Option_u64, out$bool, out$ref_slice_u8, out$tuple2_u64_ref_slice_u8, out$u16, out$u64, out$u8 } from "../lib.ts";
import * as DecodeError from "../coding/decode.DecodeError.ts";
import { read } from "../coding/varint.ts";
import type * as Form from "../coding/varint.Form.ts";
@@ -190,13 +190,14 @@ export function varint(self: Decoder): rt.u64 | undefined {
}
/** Read an optional varint: 0 is `None`, and `n + 1` is `Some(n)`. */
-export function varintOpt(self: Decoder): rt.Result {
+export function varintOpt(self: Decoder): DecodeError.DecodeError | undefined {
const part: rt.u64 | undefined = varint(self);
const err: DecodeError.DecodeError | undefined = part === undefined ? out$u64.err as DecodeError.DecodeError : undefined;
if (err === undefined) {
- return rt.Ok(rt.u64CheckedSub(part as rt.u64, 1));
+ out$Option_u64.p = rt.u64CheckedSub(part as rt.u64, 1);
+ return undefined;
}
- return rt.Err(err as DecodeError.DecodeError);
+ return err as DecodeError.DecodeError;
}
/** Read a varint length, then that many raw bytes. */
diff --git a/ts/fixtures/codec/expected/harness.ts b/ts/fixtures/codec/expected/harness.ts
index 69bdb3d9f..71c827d4f 100644
--- a/ts/fixtures/codec/expected/harness.ts
+++ b/ts/fixtures/codec/expected/harness.ts
@@ -1,7 +1,7 @@
// Generated by rust2-ts. Do not edit.
import * as rt from "./rt.ts";
-import { out$bool, out$ref_slice_u8, out$u16, out$u64, out$u8, out$usize } from "./lib.ts";
+import { out$Option_u64, out$bool, out$ref_slice_u8, out$u16, out$u64, out$u8, out$usize } from "./lib.ts";
import * as DecodeError from "./coding/decode.DecodeError.ts";
import * as Decoder from "./coding/decode.Decoder.ts";
import * as EncodeError from "./coding/encode.EncodeError.ts";
@@ -224,41 +224,42 @@ export function decodeScript(dataData: Uint8Array, dataStart: number, dataLen: n
export function decodeStep(r: Decoder.Decoder, step: rt.u8, out: rt.ByteVec): rt.Result {
const _5: rt.u8 = rt.u8Rem(step, 10);
if (_5 === 0) {
- const part11: rt.u8 | undefined = Decoder.u8(r);
- const err7: DecodeError.DecodeError | undefined = part11 === undefined ? out$u8.err as DecodeError.DecodeError : undefined;
+ const part12: rt.u8 | undefined = Decoder.u8(r);
+ const err8: DecodeError.DecodeError | undefined = part12 === undefined ? out$u8.err as DecodeError.DecodeError : undefined;
+ if (err8 === undefined) {
+ rt.byteVecPush(out, part12 as rt.u8);
+ } else {
+ return rt.Err(err8 as DecodeError.DecodeError);
+ }
+ } else if (_5 === 1) {
+ const part11: rt.u16 | undefined = Decoder.u16(r);
+ const err7: DecodeError.DecodeError | undefined = part11 === undefined ? out$u16.err as DecodeError.DecodeError : undefined;
if (err7 === undefined) {
- rt.byteVecPush(out, part11 as rt.u8);
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u16ToBeBytes(part11 as rt.u16)));
} else {
return rt.Err(err7 as DecodeError.DecodeError);
}
- } else if (_5 === 1) {
- const part10: rt.u16 | undefined = Decoder.u16(r);
- const err6: DecodeError.DecodeError | undefined = part10 === undefined ? out$u16.err as DecodeError.DecodeError : undefined;
+ } else if (_5 === 2) {
+ const err6: DecodeError.DecodeError | undefined = Decoder.bool(r);
+ const part10: boolean = out$bool.p;
if (err6 === undefined) {
- rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u16ToBeBytes(part10 as rt.u16)));
+ rt.byteVecPush(out, part10 ? 1 : 0);
} else {
return rt.Err(err6 as DecodeError.DecodeError);
}
- } else if (_5 === 2) {
- const err5: DecodeError.DecodeError | undefined = Decoder.bool(r);
- const part9: boolean = out$bool.p;
+ } else if (_5 === 3) {
+ const part9: rt.u64 | undefined = Decoder.varint(r);
+ const err5: DecodeError.DecodeError | undefined = part9 === undefined ? out$u64.err as DecodeError.DecodeError : undefined;
if (err5 === undefined) {
- rt.byteVecPush(out, part9 ? 1 : 0);
+ putU64(out, part9 as rt.u64);
} else {
return rt.Err(err5 as DecodeError.DecodeError);
}
- } else if (_5 === 3) {
- const part8: rt.u64 | undefined = Decoder.varint(r);
- const err4: DecodeError.DecodeError | undefined = part8 === undefined ? out$u64.err as DecodeError.DecodeError : undefined;
- if (err4 === undefined) {
- putU64(out, part8 as rt.u64);
- } else {
- return rt.Err(err4 as DecodeError.DecodeError);
- }
} else if (_5 === 4) {
- const _31: rt.Result = Decoder.varintOpt(r);
- if (_31.ok) {
- const val5: rt.u64 | undefined = _31.value;
+ const err4: DecodeError.DecodeError | undefined = Decoder.varintOpt(r);
+ const part8: rt.u64 | undefined = out$Option_u64.p;
+ if (err4 === undefined) {
+ const val5: rt.u64 | undefined = part8;
if (val5 === undefined) {
rt.byteVecPush(out, 0);
} else {
@@ -267,7 +268,7 @@ export function decodeStep(r: Decoder.Decoder, step: rt.u8, out: rt.ByteVec): rt
putU64(out, v);
}
} else {
- return _31;
+ return rt.Err(err4 as DecodeError.DecodeError);
}
} else if (_5 === 5) {
const err3: DecodeError.DecodeError | undefined = Decoder.bytes(r);
diff --git a/ts/fixtures/codec/expected/lib.ts b/ts/fixtures/codec/expected/lib.ts
index 689bc6c9e..5edfc263a 100644
--- a/ts/fixtures/codec/expected/lib.ts
+++ b/ts/fixtures/codec/expected/lib.ts
@@ -7,6 +7,8 @@ export function copy$bench_Timestamp(v: Timestamp.Timestamp): Timestamp.Timestam
return { value: v.value, scale: v.scale };
}
+export const out$Option_u64: { p: rt.u64 | undefined } = { p: undefined as never };
+
export const out$bool: { p: boolean } = { p: undefined as never };
export const out$ref_slice_u8: { pData: Uint8Array; pStart: number; pLen: number } = { pData: undefined as never, pStart: undefined as never, pLen: undefined as never };
diff --git a/ts/fixtures/lang/cells/expected/cells.ts b/ts/fixtures/lang/cells/expected/cells.ts
index f052241be..f6bd1a136 100644
--- a/ts/fixtures/lang/cells/expected/cells.ts
+++ b/ts/fixtures/lang/cells/expected/cells.ts
@@ -1,7 +1,7 @@
// Generated by rust2-ts. Do not edit.
import * as rt from "./rt.ts";
-import { out$u64, out$u8 } from "./lib.ts";
+import { out$Option_u8, out$u64, out$u8 } from "./lib.ts";
import { thenSome$0d5am30 } from "./core/bool.ts";
import { unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr } from "./core/option.ts";
import { err$1nbmqmx, map$1ma2nl9 as result_map$1ma2nl9, map$0l5uclx as result_map$0l5uclx, map$14n87rz as result_map$14n87rz, map$0h1vl84 as result_map$0h1vl84, map$03hz3l7 as result_map$03hz3l7, map$0yqi183 as result_map$0yqi183 } from "./core/result.ts";
@@ -153,20 +153,24 @@ export function cellOption(dataData: Uint8Array, dataStart: number, dataLen: num
const _166: rt.u8 = rt.u8Rem(v2, 4);
if (_166 === 0 || _166 === 1) {
result = rt.onceGetOrTryInit(cell, (): rt.Result => {
- return made$Option_u8(make, v2);
+ const err4 = made$Option_u8(make, v2);
+ return err4 !== undefined ? rt.Err(err4 as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None);
} else if (_166 === 2) {
const _174: rt.OnceCell = cell;
result = rt.onceGetOrTryInit(cell, (): rt.Result => {
rt.onceSet(_174, make(v2 ^ 1), rt.None);
- return made$Option_u8(make, v2);
+ const err3 = made$Option_u8(make, v2);
+ return err3 !== undefined ? rt.Err(err3 as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None);
} else {
const _179: rt.OnceCell = cell;
result = rt.onceGetOrTryInit(cell, (): rt.Result => {
- return made$Option_u8(make, option_unwrapOr$0r2bmpr(err$1nbmqmx(result_map$1ma2nl9(rt.onceGetOrTryInit(_179, (): rt.Result => {
- return made$Option_u8(make, v2 ^ 1);
+ const err2 = made$Option_u8(make, option_unwrapOr$0r2bmpr(err$1nbmqmx(result_map$1ma2nl9(rt.onceGetOrTryInit(_179, (): rt.Result => {
+ const err = made$Option_u8(make, v2 ^ 1);
+ return err !== undefined ? rt.Err(err as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None), (_22: rt.u8 | undefined): undefined => {})), v2));
+ return err2 !== undefined ? rt.Err(err2 as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None);
}
if (result.ok) {
@@ -1289,20 +1293,24 @@ export function lockOption(dataData: Uint8Array, dataStart: number, dataLen: num
const _166: rt.u8 = rt.u8Rem(v2, 4);
if (_166 === 0 || _166 === 1) {
result = rt.onceGetOrTryInit(cell, (): rt.Result => {
- return made$Option_u8(make, v2);
+ const err4 = made$Option_u8(make, v2);
+ return err4 !== undefined ? rt.Err(err4 as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None);
} else if (_166 === 2) {
const _174: rt.OnceLock = cell;
result = rt.onceGetOrTryInit(cell, (): rt.Result => {
rt.onceSet(_174, make(v2 ^ 1), rt.None);
- return made$Option_u8(make, v2);
+ const err3 = made$Option_u8(make, v2);
+ return err3 !== undefined ? rt.Err(err3 as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None);
} else {
const _179: rt.OnceLock = cell;
result = rt.onceGetOrTryInit(cell, (): rt.Result => {
- return made$Option_u8(make, option_unwrapOr$0r2bmpr(err$1nbmqmx(result_map$1ma2nl9(rt.onceGetOrTryInit(_179, (): rt.Result => {
- return made$Option_u8(make, v2 ^ 1);
+ const err2 = made$Option_u8(make, option_unwrapOr$0r2bmpr(err$1nbmqmx(result_map$1ma2nl9(rt.onceGetOrTryInit(_179, (): rt.Result => {
+ const err = made$Option_u8(make, v2 ^ 1);
+ return err !== undefined ? rt.Err(err as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None), (_22: rt.u8 | undefined): undefined => {})), v2));
+ return err2 !== undefined ? rt.Err(err2 as rt.u8) : rt.Ok(out$Option_u8.p);
}, undefined, rt.None);
}
if (result.ok) {
@@ -2309,11 +2317,12 @@ export function twin$ref_sync_OnceLock_unit(t: rt.OnceLock):
}
/** What `make` makes of `v`, or `v` back as an error for every third byte. */
-export function made$Option_u8(make: (a0: rt.u8) => rt.u8 | undefined, v: rt.u8): rt.Result {
+export function made$Option_u8(make: (a0: rt.u8) => rt.u8 | undefined, v: rt.u8): rt.u8 | undefined {
if (rt.u8Rem(v, 3) === 0) {
- return rt.Err(v);
+ return v;
}
- return rt.Ok(make(v));
+ out$Option_u8.p = make(v);
+ return undefined;
}
/** What `make` makes of `v`, or `v` back as an error for every third byte. */
diff --git a/ts/fixtures/lang/cells/expected/lib.ts b/ts/fixtures/lang/cells/expected/lib.ts
index 6154dabe5..7b8be34ae 100644
--- a/ts/fixtures/lang/cells/expected/lib.ts
+++ b/ts/fixtures/lang/cells/expected/lib.ts
@@ -3,6 +3,8 @@
import * as rt from "./rt.ts";
import { cells } from "./cells.ts";
+export const out$Option_u8: { p: rt.u8 | undefined } = { p: undefined as never };
+
export const out$u64: { err: unknown } = { err: undefined };
export const out$u8: { err: unknown } = { err: undefined };
diff --git a/ts/fixtures/lang/returns/expected/core/bool.ts b/ts/fixtures/lang/returns/expected/core/bool.ts
index d3dfeb463..1a9e3a0ff 100644
--- a/ts/fixtures/lang/returns/expected/core/bool.ts
+++ b/ts/fixtures/lang/returns/expected/core/bool.ts
@@ -2,6 +2,13 @@
import * as rt from "../rt.ts";
+export function thenSome$0b23a33(self: boolean, t: rt.u16): rt.u16 | undefined {
+ if (!self) {
+ return undefined;
+ }
+ return t;
+}
+
export function then$0w2ymju(self: boolean, f: () => rt.ByteSlice): rt.ByteSlice | undefined {
if (!self) {
return undefined;
diff --git a/ts/fixtures/lang/returns/expected/core/option.ts b/ts/fixtures/lang/returns/expected/core/option.ts
index 01fe14751..639f43d91 100644
--- a/ts/fixtures/lang/returns/expected/core/option.ts
+++ b/ts/fixtures/lang/returns/expected/core/option.ts
@@ -3,6 +3,20 @@
import * as rt from "../rt.ts";
import type * as returns_Error from "../returns.Error.ts";
+export function unwrapOr$06r8g1t(self: rt.i128 | undefined, default_: rt.i128): rt.i128 {
+ if (self === undefined) {
+ return default_;
+ }
+ return self;
+}
+
+export function unwrapOr$1j4op5y(self: rt.u16 | undefined, default_: rt.u16): rt.u16 {
+ if (self === undefined) {
+ return default_;
+ }
+ return self;
+}
+
export function unwrapOr$0r2bmpr(self: rt.u8 | undefined, default_: rt.u8): rt.u8 {
if (self === undefined) {
return default_;
@@ -24,6 +38,20 @@ export function map$1yogfym(self: [rt.u8, rt.ByteSlice] | undefined, f: (a0: [rt
return f(self);
}
+export function map$1cf8u0y(self: rt.u64 | undefined, f: (a0: rt.u64) => rt.u64): rt.u64 | undefined {
+ if (self === undefined) {
+ return undefined;
+ }
+ return f(self);
+}
+
+export function mapOr$1surhce(self: rt.u8 | undefined, default_: rt.u8, f: (a0: rt.u8) => rt.u8): rt.u8 {
+ if (self === undefined) {
+ return default_;
+ }
+ return f(self);
+}
+
export function okOr$1b6nkwr(self: rt.char | undefined, err: rt.u8): rt.Result {
if (self === undefined) {
return rt.Err(err);
@@ -31,14 +59,14 @@ export function okOr$1b6nkwr(self: rt.char | undefined, err: rt.u8): rt.Result {
+export function okOr$12p77jh(self: rt.ByteSlice | undefined, err: returns_Error.Error): rt.Result {
if (self === undefined) {
return rt.Err(err);
}
return rt.Ok(self);
}
-export function okOr$12p77jh(self: rt.ByteSlice | undefined, err: returns_Error.Error): rt.Result {
+export function okOr$0gtm15y(self: rt.ByteSlice | undefined, err: rt.u8 | undefined): rt.Result {
if (self === undefined) {
return rt.Err(err);
}
diff --git a/ts/fixtures/lang/returns/expected/core/result.ts b/ts/fixtures/lang/returns/expected/core/result.ts
index 42c87b508..4544fbf0b 100644
--- a/ts/fixtures/lang/returns/expected/core/result.ts
+++ b/ts/fixtures/lang/returns/expected/core/result.ts
@@ -1,7 +1,17 @@
// Generated by rust2-ts. Do not edit.
import * as rt from "../rt.ts";
-import type * as returns_Error from "../returns.Error.ts";
+import * as returns_Error from "../returns.Error.ts";
+
+export function eq$11dy112(self: rt.Result, other: rt.Result): boolean {
+ if (!((self.ok ? 0 : 1) === (other.ok ? 0 : 1))) {
+ return false;
+ }
+ if (self.ok) {
+ return rt.eqOption(rt.u64Eq)(self.value, (other as { ok: true; value: rt.u64 | undefined }).value);
+ }
+ return returns_Error.eq$cmp_PartialEq(self.error, (other as { ok: false; error: returns_Error.Error }).error);
+}
export function map$1rffkv6(self: rt.Result, _: (a0: rt.u32) => rt.u64): rt.Result {
if (self.ok) {
diff --git a/ts/fixtures/lang/returns/expected/lib.ts b/ts/fixtures/lang/returns/expected/lib.ts
index b14a48df1..6eb5aa5b7 100644
--- a/ts/fixtures/lang/returns/expected/lib.ts
+++ b/ts/fixtures/lang/returns/expected/lib.ts
@@ -1,7 +1,7 @@
// Generated by rust2-ts. Do not edit.
import * as rt from "./rt.ts";
-import { returns } from "./returns.ts";
+import { returns, options } from "./returns.ts";
import * as At from "./returns.At.ts";
import type * as returns_Error from "./returns.Error.ts";
@@ -19,10 +19,44 @@ export class of$returns_At {
}
}
+export const out$Option_bool: { p: boolean | undefined } = { p: undefined as never };
+
+export const out$Option_char: { p: rt.char | undefined } = { p: undefined as never };
+
+export const out$Option_f32: { p: rt.f32 | undefined } = { p: undefined as never };
+
+export const out$Option_f64: { p: rt.f64 | undefined } = { p: undefined as never };
+
+export const out$Option_i128: { p: rt.i128 | undefined } = { p: undefined as never };
+
+export const out$Option_i16: { p: rt.i16 | undefined } = { p: undefined as never };
+
+export const out$Option_i32: { p: rt.i32 | undefined } = { p: undefined as never };
+
+export const out$Option_i64: { p: rt.i64 | undefined } = { p: undefined as never };
+
+export const out$Option_i8: { p: rt.i8 | undefined } = { p: undefined as never };
+
+export const out$Option_u128: { p: rt.u128 | undefined } = { p: undefined as never };
+
+export const out$Option_u16: { p: rt.u16 | undefined } = { p: undefined as never };
+
+export const out$Option_u32: { p: rt.u32 | undefined } = { p: undefined as never };
+
+export const out$Option_u64: { p: rt.u64 | undefined } = { p: undefined as never };
+
+export const out$Option_u8: { p: rt.u8 | undefined } = { p: undefined as never };
+
+export const out$Option_usize: { p: rt.usize | undefined } = { p: undefined as never };
+
export const out$bool: { p: boolean } = { p: undefined as never };
export const out$ref_slice_u8: { pData: Uint8Array; pStart: number; pLen: number } = { pData: undefined as never, pStart: undefined as never, pLen: undefined as never };
+export const out$tuple2_Option_u16_ref_slice_u8: { p_0: rt.u16 | undefined; p_1Data: Uint8Array; p_1Start: number; p_1Len: number } = { p_0: undefined as never, p_1Data: undefined as never, p_1Start: undefined as never, p_1Len: undefined as never };
+
+export const out$tuple2_Option_u8_u64: { p_0: rt.u8 | undefined; p_1: rt.u64 } = { p_0: undefined as never, p_1: undefined as never };
+
export const out$tuple2_f64_char: { err: unknown; p_1: rt.char } = { err: undefined, p_1: undefined as never };
export const out$tuple2_i64_u64: { err: unknown; p_1: rt.u64 } = { err: undefined, p_1: undefined as never };
@@ -33,6 +67,8 @@ export const out$tuple2_u16_ref_slice_u8: { err: unknown; p_1Data: Uint8Array; p
export const out$tuple2_u32_ref_slice_u8: { err: unknown; p_1Data: Uint8Array; p_1Start: number; p_1Len: number } = { err: undefined, p_1Data: undefined as never, p_1Start: undefined as never, p_1Len: undefined as never };
+export const out$tuple2_u64_Option_i128: { err: unknown; p_1: rt.i128 | undefined } = { err: undefined, p_1: undefined as never };
+
export const out$tuple2_u64_ref_slice_u8: { err: unknown; p_1Data: Uint8Array; p_1Start: number; p_1Len: number } = { err: undefined, p_1Data: undefined as never, p_1Start: undefined as never, p_1Len: undefined as never };
export const out$tuple2_u8_ref_slice_u8: { err: unknown; p_1Data: Uint8Array; p_1Start: number; p_1Len: number } = { err: undefined, p_1Data: undefined as never, p_1Start: undefined as never, p_1Len: undefined as never };
@@ -52,7 +88,7 @@ export const out$u8: { err: unknown } = { err: undefined };
* their count, so a case added at the end moves no other.
*/
export function cases(): [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined][] {
- return [["returns::returns", returns as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined]];
+ return [["returns::returns", returns as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined], ["returns::options", options as (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined] as [string, (a0: rt.u8, a1: rt.ByteSlice, a2: rt.ByteVec) => undefined]];
}
//# sourceMappingURL=lib.ts.map
diff --git a/ts/fixtures/lang/returns/expected/returns.Error.ts b/ts/fixtures/lang/returns/expected/returns.Error.ts
index 68fd7edad..2143f2c97 100644
--- a/ts/fixtures/lang/returns/expected/returns.Error.ts
+++ b/ts/fixtures/lang/returns/expected/returns.Error.ts
@@ -2,6 +2,18 @@
import * as rt from "./rt.ts";
+export function eq$cmp_PartialEq(self: Error, other: Error): boolean {
+ if (!({ Short: 0, Bad: 1 }[self.tag] === { Short: 0, Bad: 1 }[other.tag])) {
+ return false;
+ }
+ if (self.tag === "Short") {
+ if (other.tag === "Short") {
+ return self._0 === other._0;
+ }
+ }
+ return true;
+}
+
export type Error = { tag: "Short"; _0: rt.usize } | { tag: "Bad" };
export function code(self: Error): rt.u8 {
diff --git a/ts/fixtures/lang/returns/expected/returns.Opted.ts b/ts/fixtures/lang/returns/expected/returns.Opted.ts
new file mode 100644
index 000000000..c88a874c1
--- /dev/null
+++ b/ts/fixtures/lang/returns/expected/returns.Opted.ts
@@ -0,0 +1,26 @@
+// Generated by rust2-ts. Do not edit.
+
+import { optU64 } from "./returns.ts";
+
+/** A guard whose drop writes the slot after its function's call did. */
+export class Opted {
+ _0Data: Uint8Array;
+ _0Start: number;
+ _0Len: number;
+
+ constructor(_0Data: Uint8Array, _0Start: number, _0Len: number) {
+ this._0Data = _0Data;
+ this._0Start = _0Start;
+ this._0Len = _0Len;
+ }
+
+ [Symbol.dispose](): void {
+ drop$ops_Drop(this);
+ }
+}
+
+export function drop$ops_Drop(self: Opted): void {
+ optU64(self._0Data, self._0Start, self._0Len);
+}
+
+//# sourceMappingURL=returns.Opted.ts.map
diff --git a/ts/fixtures/lang/returns/expected/returns.ts b/ts/fixtures/lang/returns/expected/returns.ts
index 94aef3b09..cedbd653e 100644
--- a/ts/fixtures/lang/returns/expected/returns.ts
+++ b/ts/fixtures/lang/returns/expected/returns.ts
@@ -1,14 +1,15 @@
// Generated by rust2-ts. Do not edit.
import * as rt from "./rt.ts";
-import { of$returns_At, out$bool, out$ref_slice_u8, out$tuple2_f64_char, out$tuple2_i64_u64, out$tuple2_ref_slice_u8_ref_slice_u8, out$tuple2_u16_ref_slice_u8, out$tuple2_u32_ref_slice_u8, out$tuple2_u64_ref_slice_u8, out$tuple2_u8_ref_slice_u8, out$tuple3_ref_slice_u8_ref_array2_u8_ref_slice_u8, out$tuple3_u64_u64_ref_slice_u8, out$u32, out$u64, out$u8 } from "./lib.ts";
-import { then$0w2ymju } from "./core/bool.ts";
-import { unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr, map$0c2keyb as option_map$0c2keyb, map$1yogfym as option_map$1yogfym, okOr$1b6nkwr as option_okOr$1b6nkwr, okOr$0gtm15y as option_okOr$0gtm15y, okOr$12p77jh as option_okOr$12p77jh, okOr$0tezn0w as option_okOr$0tezn0w } from "./core/option.ts";
-import { map$1rffkv6 as result_map$1rffkv6, mapOr$0fbyajt as result_mapOr$0fbyajt, andThen$1yropo4 as result_andThen$1yropo4 } from "./core/result.ts";
+import { of$returns_At, out$Option_bool, out$Option_char, out$Option_f32, out$Option_f64, out$Option_i128, out$Option_i16, out$Option_i32, out$Option_i64, out$Option_i8, out$Option_u128, out$Option_u16, out$Option_u32, out$Option_u64, out$Option_u8, out$Option_usize, out$bool, out$ref_slice_u8, out$tuple2_Option_u16_ref_slice_u8, out$tuple2_Option_u8_u64, out$tuple2_f64_char, out$tuple2_i64_u64, out$tuple2_ref_slice_u8_ref_slice_u8, out$tuple2_u16_ref_slice_u8, out$tuple2_u32_ref_slice_u8, out$tuple2_u64_Option_i128, out$tuple2_u64_ref_slice_u8, out$tuple2_u8_ref_slice_u8, out$tuple3_ref_slice_u8_ref_array2_u8_ref_slice_u8, out$tuple3_u64_u64_ref_slice_u8, out$u32, out$u64, out$u8 } from "./lib.ts";
+import { thenSome$0b23a33, then$0w2ymju } from "./core/bool.ts";
+import { unwrapOr$06r8g1t as option_unwrapOr$06r8g1t, unwrapOr$1j4op5y as option_unwrapOr$1j4op5y, unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr, map$0c2keyb as option_map$0c2keyb, map$1yogfym as option_map$1yogfym, map$1cf8u0y as option_map$1cf8u0y, mapOr$1surhce as option_mapOr$1surhce, okOr$1b6nkwr as option_okOr$1b6nkwr, okOr$12p77jh as option_okOr$12p77jh, okOr$0gtm15y as option_okOr$0gtm15y, okOr$0tezn0w as option_okOr$0tezn0w } from "./core/option.ts";
+import { eq$11dy112 as result_eq$11dy112, map$1rffkv6 as result_map$1rffkv6, mapOr$0fbyajt as result_mapOr$0fbyajt, andThen$1yropo4 as result_andThen$1yropo4 } from "./core/result.ts";
import * as At from "./returns.At.ts";
import * as returns_Error from "./returns.Error.ts";
import * as Guard from "./returns.Guard.ts";
import * as Late from "./returns.Late.ts";
+import * as Opted from "./returns.Opted.ts";
import * as Wrapped from "./returns.Wrapped.ts";
/** A slice alone, with returns from several places. */
@@ -564,7 +565,7 @@ export function numbers(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void
break;
}
}
- rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u64ToBeBytes(sum)));
+ put$returns_Put_u64(sum, out);
}
export function returns(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void {
@@ -799,4 +800,860 @@ export function returns(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void
}
}
+export function optF32(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_f32.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_f32.p = -0.0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_f32.p = NaN;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 4), { tag: "Short", _0: 4 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_f32.p = rt.f32FromBeBytes(rt.byteSliceToArray(_17.value));
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optF64(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_f64.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_f64.p = 0.0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_f64.p = NaN;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 8), { tag: "Short", _0: 8 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_f64.p = rt.f64FromBeBytes(rt.byteSliceToArray(_17.value));
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optI128(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_i128.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_i128.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_i128.p = { hi: -0x80000000, w2: 0, w1: 0, lo: 0 } as rt.i128;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 16), { tag: "Short", _0: 16 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_i128.p = rt.i128FromBeBytes(rt.byteSliceToArray(_17.value));
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optI16(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_i16.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_i16.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_i16.p = -32768;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 2), { tag: "Short", _0: 2 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_i16.p = (((_17.value.data[_17.value.start] << 8) | _17.value.data[_17.value.start + 1]) << 16) >> 16;
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optI32(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_i32.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_i32.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_i32.p = -2147483648;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 4), { tag: "Short", _0: 4 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_i32.p = (_17.value.data[_17.value.start] << 24) | (_17.value.data[_17.value.start + 1] << 16) | (_17.value.data[_17.value.start + 2] << 8) | _17.value.data[_17.value.start + 3];
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optI64(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_i64.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_i64.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_i64.p = { hi: -0x80000000, lo: 0 } as rt.i64;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 8), { tag: "Short", _0: 8 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_i64.p = rt.i64FromBeBytes(rt.byteSliceToArray(_17.value));
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optI8(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_i8.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_i8.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_i8.p = -128;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 1), { tag: "Short", _0: 1 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_i8.p = (_17.value.data[_17.value.start] << 24) >> 24;
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optU128(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_u128.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_u128.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_u128.p = { hi: 0xffffffff, w2: 0xffffffff, w1: 0xffffffff, lo: 0xffffffff } as rt.u128;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 16), { tag: "Short", _0: 16 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_u128.p = rt.u128FromBeBytes(rt.byteSliceToArray(_17.value));
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optU16(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_u16.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_u16.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_u16.p = 65535;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 2), { tag: "Short", _0: 2 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_u16.p = (_17.value.data[_17.value.start] << 8) | _17.value.data[_17.value.start + 1];
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optU32(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_u32.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_u32.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_u32.p = 4294967295;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 4), { tag: "Short", _0: 4 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_u32.p = ((_17.value.data[_17.value.start] << 24) | (_17.value.data[_17.value.start + 1] << 16) | (_17.value.data[_17.value.start + 2] << 8) | _17.value.data[_17.value.start + 3]) >>> 0;
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optU64(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_u64.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_u64.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_u64.p = { hi: 0xffffffff, lo: 0xffffffff } as rt.u64;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 8), { tag: "Short", _0: 8 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_u64.p = rt.u64FromBeBytes(rt.byteSliceToArray(_17.value));
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optU8(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_u8.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_u8.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_u8.p = 255;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 1), { tag: "Short", _0: 1 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_u8.p = _17.value.data[_17.value.start];
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optUsize(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const _11: rt.u8 = rt.u8Rem(dataData[dataStart], 5);
+ if (_11 === 0) {
+ out$Option_usize.p = undefined;
+ return undefined;
+ }
+ if (_11 === 1) {
+ out$Option_usize.p = 0;
+ return undefined;
+ }
+ if (_11 === 2) {
+ return { tag: "Bad" } as returns_Error.Error;
+ }
+ if (_11 === 3) {
+ out$Option_usize.p = 4294967295;
+ return undefined;
+ }
+ const _17: rt.Result = option_okOr$12p77jh(rt.byteSliceGetRange(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1), 0, 4), { tag: "Short", _0: 4 } as returns_Error.Error);
+ if (_17.ok) {
+ out$Option_usize.p = ((_17.value.data[_17.value.start] << 24) | (_17.value.data[_17.value.start + 1] << 16) | (_17.value.data[_17.value.start + 2] << 8) | _17.value.data[_17.value.start + 3]) >>> 0;
+ return undefined;
+ }
+ return (_17 as { ok: false; error: returns_Error.Error }).error;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optBool(data: rt.ByteSlice): returns_Error.Error | undefined {
+ const _2: rt.u8 | undefined = rt.byteSliceFirst(data);
+ if (_2 === undefined) {
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+ }
+ if (!(rt.u8Rem(_2, 3) === 0)) {
+ out$Option_bool.p = rt.u8Rem(_2, 3) === 1;
+ return undefined;
+ }
+ out$Option_bool.p = undefined;
+ return undefined;
+}
+
+export function optChar(dataData: Uint8Array, dataStart: number, dataLen: number): rt.u8 | undefined {
+ const part: rt.u8 | undefined = byte(new rt.ByteSlice(dataData, dataStart, dataLen), 0);
+ const err: rt.u8 | undefined = part === undefined ? out$u8.err as rt.u8 : undefined;
+ if (err === undefined) {
+ out$Option_char.p = rt.charFromU32(rt.u32Add(rt.u32Mul((part as rt.u8) as rt.u32, 435), 55040));
+ return undefined;
+ }
+ return err as rt.u8;
+}
+
+/** `opt_u64`'s result returned as is, and taken apart by `?` and made again. */
+export function optAgain(data: rt.ByteSlice, first: boolean): returns_Error.Error | undefined {
+ if (!first) {
+ const _6: rt.ByteSlice = rt.byteSliceRange(data, rt.min(data.length, 1));
+ const err: returns_Error.Error | undefined = optU64(_6.data, _6.start, _6.length);
+ const part2: rt.u64 | undefined = out$Option_u64.p;
+ if (err === undefined) {
+ out$Option_u64.p = option_map$1cf8u0y(part2, (v: rt.u64): rt.u64 => {
+ return rt.u64Shr(v, 1);
+ });
+ return undefined;
+ }
+ return err as returns_Error.Error;
+ }
+ return optU64(data.data, data.start, data.length);
+}
+
+/** An `Option` beside a number, first and last, and beside a slice. */
+export function optFirst(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ const err: returns_Error.Error | undefined = optU8(dataData, dataStart, dataLen);
+ const part: rt.u8 | undefined = out$Option_u8.p;
+ if (err === undefined) {
+ out$tuple2_Option_u8_u64.p_0 = part;
+ out$tuple2_Option_u8_u64.p_1 = dataLen as rt.u64;
+ return undefined;
+ }
+ return err as returns_Error.Error;
+}
+
+export function optLast(dataData: Uint8Array, dataStart: number, dataLen: number): rt.u64 | undefined {
+ const err: returns_Error.Error | undefined = optI128(dataData, dataStart, dataLen);
+ const part: rt.i128 | undefined = out$Option_i128.p;
+ const _3: rt.u64 = dataLen as rt.u64;
+ if (err === undefined) {
+ out$tuple2_u64_Option_i128.p_1 = part;
+ return _3;
+ }
+ out$tuple2_u64_Option_i128.err = err as returns_Error.Error;
+ return undefined;
+}
+
+export function optRest(dataData: Uint8Array, dataStart: number, dataLen: number): returns_Error.Error | undefined {
+ if (dataLen !== 0) {
+ const b: rt.u8 = dataData[dataStart];
+ out$tuple2_Option_u16_ref_slice_u8.p_0 = thenSome$0b23a33(rt.u8Rem(b, 2) === 0, (((b as rt.u16)) << 8) & 0xffff);
+ out$tuple2_Option_u16_ref_slice_u8.p_1Data = dataData;
+ out$tuple2_Option_u16_ref_slice_u8.p_1Start = dataStart + 1;
+ out$tuple2_Option_u16_ref_slice_u8.p_1Len = dataLen - 1;
+ return undefined;
+ }
+ return { tag: "Short", _0: 1 } as returns_Error.Error;
+}
+
+export function optLate(dataData: Uint8Array, dataStart: number, dataLen: number, other: rt.ByteSlice): returns_Error.Error | undefined {
+ const err: returns_Error.Error | undefined = optU64(dataData, dataStart, dataLen);
+ const part: rt.u64 | undefined = out$Option_u64.p;
+ new Opted.Opted(other.data, other.start, other.length)[Symbol.dispose]();
+ if (err !== undefined) {
+ return err as returns_Error.Error;
+ }
+ out$Option_u64.p = part;
+ return undefined;
+}
+
+export function put$returns_Put_i128(self: rt.i128, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.i128ToBeBytes(self)));
+}
+
+export function put$returns_Put_i16(self: rt.i16, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.i16ToBeBytes(self)));
+}
+
+export function put$returns_Put_i32(self: rt.i32, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.i32ToBeBytes(self)));
+}
+
+export function put$returns_Put_i64(self: rt.i64, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.i64ToBeBytes(self)));
+}
+
+export function put$returns_Put_i8(self: rt.i8, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.i8ToBeBytes(self)));
+}
+
+export function put$returns_Put_u128(self: rt.u128, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u128ToBeBytes(self)));
+}
+
+export function put$returns_Put_u16(self: rt.u16, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u16ToBeBytes(self)));
+}
+
+export function put$returns_Put_u32(self: rt.u32, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u32ToBeBytes(self)));
+}
+
+export function put$returns_Put_u64(self: rt.u64, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u64ToBeBytes(self)));
+}
+
+export function put$returns_Put_u8(self: rt.u8, out: rt.ByteVec): void {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(rt.u8ToBeBytes(self)));
+}
+
+export function put$returns_Put_usize(self: rt.usize, out: rt.ByteVec): void {
+ put$returns_Put_u64(self as rt.u64, out);
+}
+
+export function put$returns_Put_bool(self: boolean, out: rt.ByteVec): void {
+ rt.byteVecPush(out, self ? 1 : 0);
+}
+
+export function put$returns_Put_char(self: rt.char, out: rt.ByteVec): void {
+ put$returns_Put_u32(self as rt.u32, out);
+}
+
+export function put$returns_Put_f32(self: rt.f32, out: rt.ByteVec): void {
+ if (!Number.isNaN(self)) {
+ put$returns_Put_u32(rt.f32ToBits(self), out);
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(127, rt.f32IsSignNegative(self) ? 1 : 0)));
+ }
+}
+
+export function put$returns_Put_f64(self: rt.f64, out: rt.ByteVec): void {
+ if (!Number.isNaN(self)) {
+ put$returns_Put_u64(rt.f64ToBits(self), out);
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(127, rt.f64IsSignNegative(self) ? 1 : 0)));
+ }
+}
+
+/**
+ * Results of `Option`s of numbers: held as parts, kept whole, and read after the slot was
+ * written again.
+ */
+export function options(kind: rt.u8, data: rt.ByteSlice, out: rt.ByteVec): void {
+ let f!: (a0: rt.ByteSlice) => rt.Result;
+ const err: returns_Error.Error | undefined = optU8(data.data, data.start, data.length);
+ const part: rt.u8 | undefined = out$Option_u8.p;
+ if (err === undefined) {
+ if (part === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v: rt.u8 = part;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u8(v, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err as returns_Error.Error))));
+ }
+ const err2: returns_Error.Error | undefined = optU16(data.data, data.start, data.length);
+ const part2: rt.u16 | undefined = out$Option_u16.p;
+ if (err2 === undefined) {
+ if (part2 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v2: rt.u16 = part2;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u16(v2, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err2 as returns_Error.Error))));
+ }
+ const err3: returns_Error.Error | undefined = optU32(data.data, data.start, data.length);
+ const part3: rt.u32 | undefined = out$Option_u32.p;
+ if (err3 === undefined) {
+ if (part3 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v3: rt.u32 = part3;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u32(v3, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err3 as returns_Error.Error))));
+ }
+ const err4: returns_Error.Error | undefined = optU64(data.data, data.start, data.length);
+ const part4: rt.u64 | undefined = out$Option_u64.p;
+ if (err4 === undefined) {
+ if (part4 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v4: rt.u64 = part4;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u64(v4, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err4 as returns_Error.Error))));
+ }
+ const err5: returns_Error.Error | undefined = optU128(data.data, data.start, data.length);
+ const part5: rt.u128 | undefined = out$Option_u128.p;
+ if (err5 === undefined) {
+ if (part5 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v5: rt.u128 = part5;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u128(v5, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err5 as returns_Error.Error))));
+ }
+ const err6: returns_Error.Error | undefined = optUsize(data.data, data.start, data.length);
+ const part6: rt.usize | undefined = out$Option_usize.p;
+ if (err6 === undefined) {
+ if (part6 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v6: rt.usize = part6;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_usize(v6, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err6 as returns_Error.Error))));
+ }
+ const err7: returns_Error.Error | undefined = optI8(data.data, data.start, data.length);
+ const part7: rt.i8 | undefined = out$Option_i8.p;
+ if (err7 === undefined) {
+ if (part7 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v7: rt.i8 = part7;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_i8(v7, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err7 as returns_Error.Error))));
+ }
+ const err8: returns_Error.Error | undefined = optI16(data.data, data.start, data.length);
+ const part8: rt.i16 | undefined = out$Option_i16.p;
+ if (err8 === undefined) {
+ if (part8 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v8: rt.i16 = part8;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_i16(v8, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err8 as returns_Error.Error))));
+ }
+ const err9: returns_Error.Error | undefined = optI32(data.data, data.start, data.length);
+ const part9: rt.i32 | undefined = out$Option_i32.p;
+ if (err9 === undefined) {
+ if (part9 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v9: rt.i32 = part9;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_i32(v9, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err9 as returns_Error.Error))));
+ }
+ const err10: returns_Error.Error | undefined = optI64(data.data, data.start, data.length);
+ const part10: rt.i64 | undefined = out$Option_i64.p;
+ if (err10 === undefined) {
+ if (part10 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v10: rt.i64 = part10;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_i64(v10, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err10 as returns_Error.Error))));
+ }
+ const err11: returns_Error.Error | undefined = optI128(data.data, data.start, data.length);
+ const part11: rt.i128 | undefined = out$Option_i128.p;
+ if (err11 === undefined) {
+ if (part11 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v11: rt.i128 = part11;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_i128(v11, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err11 as returns_Error.Error))));
+ }
+ const err12: returns_Error.Error | undefined = optF32(data.data, data.start, data.length);
+ const part12: rt.f32 | undefined = out$Option_f32.p;
+ if (err12 === undefined) {
+ if (part12 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v12: rt.f32 = part12;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_f32(v12, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err12 as returns_Error.Error))));
+ }
+ const err13: returns_Error.Error | undefined = optF64(data.data, data.start, data.length);
+ const part13: rt.f64 | undefined = out$Option_f64.p;
+ if (err13 === undefined) {
+ if (part13 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v13: rt.f64 = part13;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_f64(v13, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err13 as returns_Error.Error))));
+ }
+ const err14: returns_Error.Error | undefined = optBool(data);
+ const part14: boolean | undefined = out$Option_bool.p;
+ if (err14 === undefined) {
+ if (part14 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v14: boolean = part14;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_bool(v14, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err14 as returns_Error.Error))));
+ }
+ const err15: rt.u8 | undefined = optChar(data.data, data.start, data.length);
+ const part15: rt.char | undefined = out$Option_char.p;
+ if (err15 === undefined) {
+ if (part15 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ put$returns_Put_char(part15, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, err15 as rt.u8)));
+ }
+ const tail: rt.ByteSlice = rt.byteSliceRange(data, rt.min(data.length, 1));
+ const err16: returns_Error.Error | undefined = optAgain(data, rt.u8Rem(kind, 2) === 0);
+ const part17: rt.u64 | undefined = out$Option_u64.p;
+ if (err16 === undefined) {
+ if (part17 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v15: rt.u64 = part17;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u64(v15, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err16 as returns_Error.Error))));
+ }
+ const err17: returns_Error.Error | undefined = optLate(data.data, data.start, data.length, tail);
+ const part18: rt.u64 | undefined = out$Option_u64.p;
+ if (err17 === undefined) {
+ if (part18 === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v16: rt.u64 = part18;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u64(v16, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(err17 as returns_Error.Error))));
+ }
+ const err18: returns_Error.Error | undefined = optFirst(data.data, data.start, data.length);
+ const part19: rt.u8 | undefined = out$tuple2_Option_u8_u64.p_0;
+ const part20: rt.u64 = out$tuple2_Option_u8_u64.p_1;
+ if (err18 === undefined) {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(option_mapOr$1surhce(part19, 170, (n5: rt.u8): rt.u8 => {
+ return n5;
+ }), rt.u64Low(part20) & 0xff)));
+ } else {
+ rt.byteVecPush(out, returns_Error.code(err18 as returns_Error.Error));
+ }
+ const part21: rt.u64 | undefined = optLast(data.data, data.start, data.length);
+ const err19: returns_Error.Error | undefined = part21 === undefined ? out$tuple2_u64_Option_i128.err as returns_Error.Error : undefined;
+ const part22: rt.i128 | undefined = out$tuple2_u64_Option_i128.p_1;
+ if (err19 === undefined) {
+ const len2: rt.u64 = part21 as rt.u64;
+ const n2: rt.i128 | undefined = part22;
+ rt.byteVecPush(out, rt.u64Low(len2) & 0xff);
+ put$returns_Put_i128(option_unwrapOr$06r8g1t(n2, -1), out);
+ } else {
+ rt.byteVecPush(out, returns_Error.code(err19 as returns_Error.Error));
+ }
+ const err20: returns_Error.Error | undefined = optRest(data.data, data.start, data.length);
+ const part23: rt.u16 | undefined = out$tuple2_Option_u16_ref_slice_u8.p_0;
+ const part26: number = out$tuple2_Option_u16_ref_slice_u8.p_1Len;
+ if (err20 === undefined) {
+ const n3: rt.u16 | undefined = part23;
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(n3 !== undefined ? 1 : 0, (option_unwrapOr$1j4op5y(n3, 0) >> 8) & 0xff, part26 & 0xff)));
+ } else {
+ rt.byteVecPush(out, returns_Error.code(err20 as returns_Error.Error));
+ }
+ const err21: returns_Error.Error | undefined = optU64(data.data, data.start, data.length);
+ const part27: rt.u64 | undefined = out$Option_u64.p;
+ const err22: returns_Error.Error | undefined = optU64(tail.data, tail.start, tail.length);
+ const part28: rt.u64 | undefined = out$Option_u64.p;
+ b20: {
+ if (err21 === undefined) {
+ if (err22 === undefined) {
+ if (part27 !== undefined) {
+ if (part28 !== undefined) {
+ put$returns_Put_u64(rt.u64Xor(part27, part28), out);
+ break b20;
+ }
+ }
+ }
+ }
+ const x5: rt.Result = (err21 !== undefined ? rt.Err(err21 as returns_Error.Error) : rt.Ok(part27)) as rt.Result;
+ const y5: rt.Result = (err22 !== undefined ? rt.Err(err22 as returns_Error.Error) : rt.Ok(part28)) as rt.Result;
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(x5.ok ? 1 : 0, y5.ok ? 1 : 0, result_eq$11dy112(x5, y5) ? 1 : 0)));
+ }
+ for (const r of rt.iterToArray(rt.iterMap(new rt.Range(0, 3), (i: rt.usize): rt.Result => {
+ const _3: rt.ByteSlice = rt.byteSliceRange(data, rt.min(data.length, i));
+ const err23 = optU64(_3.data, _3.start, _3.length);
+ return err23 !== undefined ? rt.Err(err23 as returns_Error.Error) : rt.Ok(out$Option_u64.p);
+ }), undefined, 16, true)) {
+ if (r.ok) {
+ if (r.value === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v17: rt.u64 = r.value;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_u64(v17, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(r.error))));
+ }
+ }
+ if (!(rt.u8Rem(kind, 2) === 0)) {
+ f = (d: rt.ByteSlice): rt.Result => {
+ const _32: rt.ByteSlice = rt.byteSliceRange(d, rt.min(d.length, 1));
+ const err25 = optI64(_32.data, _32.start, _32.length);
+ return err25 !== undefined ? rt.Err(err25 as returns_Error.Error) : rt.Ok(out$Option_i64.p);
+ };
+ } else {
+ f = (a0: rt.ByteSlice): rt.Result => {
+ const err24 = optI64(a0.data, a0.start, a0.length);
+ return err24 !== undefined ? rt.Err(err24 as returns_Error.Error) : rt.Ok(out$Option_i64.p);
+ };
+ }
+ const _310: rt.Result = f(data);
+ if (_310.ok) {
+ if (_310.value === undefined) {
+ rt.byteVecPush(out, 0);
+ } else {
+ const v18: rt.i64 = _310.value;
+ rt.byteVecPush(out, 1);
+ put$returns_Put_i64(v18, out);
+ }
+ } else {
+ rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(Uint8Array.of(238, returns_Error.code(_310.error))));
+ }
+ let rest2: rt.ByteSlice = data;
+ let sum: rt.u32 = 0;
+ while (true) {
+ const _325: rt.ByteSlice = rest2;
+ const err26: returns_Error.Error | undefined = optU32(_325.data, _325.start, _325.length);
+ const part31: rt.u32 | undefined = out$Option_u32.p;
+ if (err26 === undefined) {
+ if (part31 !== undefined) {
+ const n4: rt.u32 = part31;
+ sum = rt.u32WrappingAdd(rt.u32WrappingMul(sum, 31), n4);
+ rest2 = rt.byteSliceRange(rest2, rt.max(rt.min(rt.usizeRem(n4 as rt.usize, 5), rest2.length), 1));
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ put$returns_Put_u32(sum, out);
+}
+
//# sourceMappingURL=returns.ts.map
diff --git a/ts/fixtures/lang/returns/src/lib.rs b/ts/fixtures/lang/returns/src/lib.rs
index 6c6d828d3..bc80c1600 100644
--- a/ts/fixtures/lang/returns/src/lib.rs
+++ b/ts/fixtures/lang/returns/src/lib.rs
@@ -15,5 +15,8 @@ use harness::Case;
/// Each case's name and what it runs. The first two bytes, big-endian, pick one modulo
/// their count, so a case added at the end moves no other.
fn cases() -> Vec<(&'static str, Case)> {
- vec![("returns::returns", returns::returns)]
+ vec![
+ ("returns::returns", returns::returns),
+ ("returns::options", returns::options),
+ ]
}
diff --git a/ts/fixtures/lang/returns/src/returns.rs b/ts/fixtures/lang/returns/src/returns.rs
index 17bd25413..1f64d6141 100644
--- a/ts/fixtures/lang/returns/src/returns.rs
+++ b/ts/fixtures/lang/returns/src/returns.rs
@@ -1,5 +1,5 @@
-//! Results of byte slices, or of numbers alone, returned by the crate's own functions,
-//! which hand back an `Ok`'s parts in a slot their caller reads at once.
+//! Results of byte slices, or of numbers alone or in `Option`s, returned by the crate's own
+//! functions, which hand back an `Ok`'s parts in a slot their caller reads at once.
#[derive(Debug, Clone, Copy, PartialEq)]
enum Error {
@@ -311,7 +311,7 @@ fn numbers(kind: u8, data: &[u8], out: &mut Vec) {
sum = sum.wrapping_mul(31).wrapping_add(n as u64);
rest = &rest[n as usize + 1..];
}
- out.extend_from_slice(&sum.to_be_bytes());
+ sum.put(out);
}
pub fn returns(kind: u8, data: &[u8], out: &mut Vec) {
@@ -425,3 +425,222 @@ pub fn returns(kind: u8, data: &[u8], out: &mut Vec) {
}
}
}
+
+/// An `Option` of a number of each width, by the first byte: `None`, `Some` of zero, an
+/// error, `Some` of the type's edge, or `Some` of the bytes after it.
+macro_rules! option {
+ ($($name:ident: $t:ty = $zero:expr, $edge:expr;)*) => {$(
+ fn $name(data: &[u8]) -> Result, Error> {
+ let (&tag, rest) = data.split_first().ok_or(Error::Short(1))?;
+ match tag % 5 {
+ 0 => Ok(None),
+ 1 => Ok(Some($zero)),
+ 2 => Err(Error::Bad),
+ 3 => Ok(Some($edge)),
+ _ => {
+ let bytes = rest.first_chunk().ok_or(Error::Short(size_of::<$t>()))?;
+ Ok(Some(<$t>::from_be_bytes(*bytes)))
+ }
+ }
+ }
+ )*};
+}
+
+option! {
+ opt_u8: u8 = 0, u8::MAX;
+ opt_u16: u16 = 0, u16::MAX;
+ opt_u32: u32 = 0, u32::MAX;
+ opt_u64: u64 = 0, u64::MAX;
+ opt_u128: u128 = 0, u128::MAX;
+ opt_usize: usize = 0, usize::MAX;
+ opt_i8: i8 = 0, i8::MIN;
+ opt_i16: i16 = 0, i16::MIN;
+ opt_i32: i32 = 0, i32::MIN;
+ opt_i64: i64 = 0, i64::MIN;
+ opt_i128: i128 = 0, i128::MIN;
+ opt_f32: f32 = -0.0, f32::NAN;
+ opt_f64: f64 = 0.0, f64::NAN;
+}
+
+fn opt_bool(data: &[u8]) -> Result , Error> {
+ match data.first() {
+ None => Err(Error::Short(1)),
+ Some(&b) if b % 3 == 0 => Ok(None),
+ Some(&b) => Ok(Some(b % 3 == 1)),
+ }
+}
+
+fn opt_char(data: &[u8]) -> Result , u8> {
+ let b = byte(data, 0)?;
+ Ok(char::from_u32(u32::from(b) * 0x1b3 + 0xd700))
+}
+
+/// `opt_u64`'s result returned as is, and taken apart by `?` and made again.
+fn opt_again(data: &[u8], first: bool) -> Result , Error> {
+ if first {
+ return opt_u64(data);
+ }
+ Ok(opt_u64(&data[data.len().min(1)..])?.map(|v| v >> 1))
+}
+
+/// An `Option` beside a number, first and last, and beside a slice.
+fn opt_first(data: &[u8]) -> Result<(Option, u64), Error> {
+ let n = opt_u8(data)?;
+ Ok((n, data.len() as u64))
+}
+
+fn opt_last(data: &[u8]) -> Result<(u64, Option), Error> {
+ Ok((data.len() as u64, opt_i128(data)?))
+}
+
+fn opt_rest(data: &[u8]) -> Result<(Option, &[u8]), Error> {
+ let (&b, rest) = data.split_first().ok_or(Error::Short(1))?;
+ Ok(((b % 2 == 0).then_some(u16::from(b) << 8), rest))
+}
+
+/// A guard whose drop writes the slot after its function's call did.
+struct Opted<'a>(&'a [u8]);
+
+impl Drop for Opted<'_> {
+ fn drop(&mut self) {
+ let _ = opt_u64(self.0);
+ }
+}
+
+fn opt_late(data: &[u8], other: &[u8]) -> Result, Error> {
+ let _late = Opted(other);
+ opt_u64(data)
+}
+
+/// A number's bytes, as each case writes it.
+trait Put {
+ fn put(self, out: &mut Vec);
+}
+
+macro_rules! put {
+ ($($t:ty),*) => {$(
+ impl Put for $t {
+ fn put(self, out: &mut Vec) {
+ out.extend_from_slice(&self.to_be_bytes());
+ }
+ }
+ )*};
+}
+
+put!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
+
+impl Put for usize {
+ fn put(self, out: &mut Vec) {
+ (self as u64).put(out);
+ }
+}
+
+impl Put for bool {
+ fn put(self, out: &mut Vec) {
+ out.push(self as u8);
+ }
+}
+
+impl Put for char {
+ fn put(self, out: &mut Vec) {
+ (self as u32).put(out);
+ }
+}
+
+/// A float's bits, or its sign alone if it is a NaN, whose payload is the engine's.
+impl Put for f32 {
+ fn put(self, out: &mut Vec) {
+ match self.is_nan() {
+ true => out.extend_from_slice(&[0x7f, self.is_sign_negative() as u8]),
+ false => self.to_bits().put(out),
+ }
+ }
+}
+
+impl Put for f64 {
+ fn put(self, out: &mut Vec) {
+ match self.is_nan() {
+ true => out.extend_from_slice(&[0x7f, self.is_sign_negative() as u8]),
+ false => self.to_bits().put(out),
+ }
+ }
+}
+
+/// Results of `Option`s of numbers: held as parts, kept whole, and read after the slot was
+/// written again.
+pub fn options(kind: u8, data: &[u8], out: &mut Vec) {
+ macro_rules! push {
+ ($r:expr) => {
+ match $r {
+ Ok(Some(v)) => {
+ out.push(1);
+ v.put(out);
+ }
+ Ok(None) => out.push(0),
+ Err(e) => out.extend_from_slice(&[0xee, e.code()]),
+ }
+ };
+ }
+ push!(opt_u8(data));
+ push!(opt_u16(data));
+ push!(opt_u32(data));
+ push!(opt_u64(data));
+ push!(opt_u128(data));
+ push!(opt_usize(data));
+ push!(opt_i8(data));
+ push!(opt_i16(data));
+ push!(opt_i32(data));
+ push!(opt_i64(data));
+ push!(opt_i128(data));
+ push!(opt_f32(data));
+ push!(opt_f64(data));
+ push!(opt_bool(data));
+ match opt_char(data) {
+ Ok(Some(c)) => c.put(out),
+ Ok(None) => out.push(0),
+ Err(b) => out.extend_from_slice(&[0xee, b]),
+ }
+ let tail = &data[data.len().min(1)..];
+ push!(opt_again(data, kind % 2 == 0));
+ push!(opt_late(data, tail));
+ match opt_first(data) {
+ Ok((n, len)) => out.extend_from_slice(&[n.map_or(0xaa, |n| n), len as u8]),
+ Err(e) => out.push(e.code()),
+ }
+ match opt_last(data) {
+ Ok((len, n)) => {
+ out.push(len as u8);
+ n.unwrap_or(-1).put(out);
+ }
+ Err(e) => out.push(e.code()),
+ }
+ match opt_rest(data) {
+ Ok((n, rest)) => out.extend_from_slice(&[n.is_some() as u8, (n.unwrap_or(0) >> 8) as u8, rest.len() as u8]),
+ Err(e) => out.push(e.code()),
+ }
+ // Both held while the slot is written again between them.
+ let (x, y) = (opt_u64(data), opt_u64(tail));
+ match (x, y) {
+ (Ok(Some(x)), Ok(Some(y))) => (x ^ y).put(out),
+ (x, y) => out.extend_from_slice(&[x.is_ok() as u8, y.is_ok() as u8, (x == y) as u8]),
+ }
+ // Kept whole: in a collection, and through a function as a value.
+ let kept: Vec, Error>> = (0..3).map(|i| opt_u64(&data[data.len().min(i)..])).collect();
+ for r in kept {
+ push!(r);
+ }
+ let f: fn(&[u8]) -> Result, Error> = if kind % 2 == 0 {
+ opt_i64
+ } else {
+ |d| opt_i64(&d[d.len().min(1)..])
+ };
+ push!(f(data));
+ // A loop that calls again while the last result is still read.
+ let mut rest = data;
+ let mut sum = 0u32;
+ while let Ok(Some(n)) = opt_u32(rest) {
+ sum = sum.wrapping_mul(31).wrapping_add(n);
+ rest = &rest[(n as usize % 5).min(rest.len()).max(1)..];
+ }
+ sum.put(out);
+}
diff --git a/ts/fixtures/lang/shapes/expected/lib.ts b/ts/fixtures/lang/shapes/expected/lib.ts
index f25959480..790e4e8fe 100644
--- a/ts/fixtures/lang/shapes/expected/lib.ts
+++ b/ts/fixtures/lang/shapes/expected/lib.ts
@@ -141,6 +141,8 @@ export function drop$generics_Run_generics_Ticked(_1: Run.Run): v
}
}
+export const out$Option_u8: { p: rt.u8 | undefined } = { p: undefined as never };
+
export const out$u8: { err: unknown } = { err: undefined };
/**
diff --git a/ts/fixtures/lang/shapes/expected/shapes.ts b/ts/fixtures/lang/shapes/expected/shapes.ts
index 1f158fc37..4a2717d9b 100644
--- a/ts/fixtures/lang/shapes/expected/shapes.ts
+++ b/ts/fixtures/lang/shapes/expected/shapes.ts
@@ -1,7 +1,7 @@
// Generated by rust2-ts. Do not edit.
import * as rt from "./rt.ts";
-import { copy$Option_shapes_Shape, copy$Option_tuple2_ref_sync_Mutex_u8_u8, copy$Result_tuple2_ref_sync_Mutex_u8_u8_u8, copy$array_ref_sync_Mutex_u8, copy$array_shapes_Point, copy$array_u8, copy$ops_ControlFlow_ref_sync_Arc_u8_array1_u8, copy$ops_ControlFlow_unit_array2_u8, copy$shapes_Gauge, copy$shapes_Held, copy$shapes_Lens, copy$shapes_Level, copy$shapes_Point, copy$shapes_Shape, copy$task_Poll_array1_u8, copy$tuple2_ref_sync_Mutex_u8_u8, copy$tuple2_shapes_Point_u8, copy$tuple2_u8_u8, out$u8 } from "./lib.ts";
+import { copy$Option_shapes_Shape, copy$Option_tuple2_ref_sync_Mutex_u8_u8, copy$Result_tuple2_ref_sync_Mutex_u8_u8_u8, copy$array_ref_sync_Mutex_u8, copy$array_shapes_Point, copy$array_u8, copy$ops_ControlFlow_ref_sync_Arc_u8_array1_u8, copy$ops_ControlFlow_unit_array2_u8, copy$shapes_Gauge, copy$shapes_Held, copy$shapes_Lens, copy$shapes_Level, copy$shapes_Point, copy$shapes_Shape, copy$task_Poll_array1_u8, copy$tuple2_ref_sync_Mutex_u8_u8, copy$tuple2_shapes_Point_u8, copy$tuple2_u8_u8, out$Option_u8, out$u8 } from "./lib.ts";
import { thenSome$0ztng9q, then$1i9qaz4, then$1btzga3 } from "./core/bool.ts";
import { unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr, map$0600mq0 as option_map$0600mq0, map$18z3v8h as option_map$18z3v8h, mapOr$1a3irjf as option_mapOr$1a3irjf, mapOr$1t0muvr as option_mapOr$1t0muvr, mapOr$1ybqvup as option_mapOr$1ybqvup, mapOr$0rtdylj as option_mapOr$0rtdylj, mapOr$0aserv9 as option_mapOr$0aserv9, mapOr$1hjjwvv as option_mapOr$1hjjwvv, okOr$1vxk0yk as option_okOr$1vxk0yk } from "./core/option.ts";
import { map$1dbyvzi as result_map$1dbyvzi, mapErr$0dzqwjy as result_mapErr$0dzqwjy } from "./core/result.ts";
@@ -2370,8 +2370,9 @@ export function library(data: rt.ByteSlice, out: rt.ByteVec): void {
}
/** A result with nothing set yet. */
-export function unset(): rt.Result {
- return rt.OK;
+export function unset(): rt.u8 | undefined {
+ out$Option_u8.p = undefined;
+ return undefined;
}
/** Steps a total by `x`: breaks with what it can't take, or continues with the new total. */
@@ -2478,11 +2479,15 @@ export function flows(data: rt.ByteSlice, out: rt.ByteVec): void {
rt.byteVecExtendFromSlice(out, rt.byteSliceFrom(flow3.value));
}
}
- let set: rt.Result = unset();
+ const err = unset();
+ let set: rt.Result = err !== undefined ? rt.Err(err as rt.u8) : rt.Ok(out$Option_u8.p);
if (set.ok) {
set = rt.Ok(a);
}
- const iter3: rt.Iter> = rt.iterSlice([set, unset()]);
+ const _108: rt.Result = set;
+ const err2: rt.u8 | undefined = unset();
+ const part: rt.u8 | undefined = out$Option_u8.p;
+ const iter3: rt.Iter> = rt.iterSlice([_108, (err2 !== undefined ? rt.Err(err2 as rt.u8) : rt.Ok(part)) as rt.Result]);
while (true) {
const _111: rt.Result | rt.Done = iter3.next();
if (_111 === rt.DONE) {
diff --git a/ts/fixtures/lang/splits/expected/core/option.ts b/ts/fixtures/lang/splits/expected/core/option.ts
index 2a488c6a7..5ee85205f 100644
--- a/ts/fixtures/lang/splits/expected/core/option.ts
+++ b/ts/fixtures/lang/splits/expected/core/option.ts
@@ -16,11 +16,4 @@ export function mapOr$11e0ggl(self: [rt.ByteSlice, rt.ByteSlice] | undefined, de
return f(self);
}
-export function okOr$0q0ogpn(self: [rt.ByteSlice, rt.ByteSlice] | undefined, err: rt.u8 | undefined): rt.Result<[rt.ByteSlice, rt.ByteSlice], rt.u8 | undefined> {
- if (self === undefined) {
- return rt.Err(err);
- }
- return rt.Ok(self);
-}
-
//# sourceMappingURL=option.ts.map
diff --git a/ts/fixtures/lang/splits/expected/splits.ts b/ts/fixtures/lang/splits/expected/splits.ts
index 201300562..1b090fe00 100644
--- a/ts/fixtures/lang/splits/expected/splits.ts
+++ b/ts/fixtures/lang/splits/expected/splits.ts
@@ -2,7 +2,7 @@
import * as rt from "./rt.ts";
import { out$tuple2_ref_slice_u8_ref_slice_u8, out$tuple3_u8_u16_ref_slice_u8 } from "./lib.ts";
-import { unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr, mapOr$11e0ggl as option_mapOr$11e0ggl, okOr$0q0ogpn as option_okOr$0q0ogpn } from "./core/option.ts";
+import { unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr, mapOr$11e0ggl as option_mapOr$11e0ggl } from "./core/option.ts";
import type * as Short from "./splits.Short.ts";
/** The first byte, then a big-endian `u16`, by `?` on `ok_or`. */
@@ -51,11 +51,10 @@ export function take(dataData: Uint8Array, dataStart: number, dataLen: number, n
/** The byte after the first, or an error that is itself an enum, held whole. */
export function second(dataData: Uint8Array, dataStart: number, dataLen: number, e: rt.u8 | undefined): rt.Result {
- const _4: rt.Result<[rt.ByteSlice, rt.ByteSlice], rt.u8 | undefined> = option_okOr$0q0ogpn((1 <= dataLen ? [new rt.ByteSlice(dataData, dataStart, 1), new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1)] as [rt.ByteSlice, rt.ByteSlice] : undefined) as [rt.ByteSlice, rt.ByteSlice] | undefined, e);
- if (_4.ok) {
- return rt.Ok(option_unwrapOr$0r2bmpr(rt.byteSliceFirst(_4.value[1]), 0));
+ if (1 <= dataLen) {
+ return rt.Ok(option_unwrapOr$0r2bmpr(rt.byteSliceFirst(new rt.ByteSlice(dataData, dataStart + 1, dataLen - 1)), 0));
}
- return _4;
+ return rt.Err(e);
}
/** A use that needs the slice itself. */
diff --git a/ts/src/lower/mir/scalar.rs b/ts/src/lower/mir/scalar.rs
index e6a482f92..013980bde 100644
--- a/ts/src/lower/mir/scalar.rs
+++ b/ts/src/lower/mir/scalar.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::{
StatementKind, TerminatorKind,
};
use rustc_middle::ty::adjustment::PointerCoercion;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{Span, Spanned};
use super::Fx;
@@ -32,7 +32,8 @@ use crate::ts::{Expr, Key, Stmt, StmtKind, Type};
pub enum Shape<'tcx> {
/// No JS value: `()`.
Unit,
- /// One JS value, held whole: a number, a reference to one, or an error.
+ /// One JS value, held whole: a number, a reference to one, an `Option` of one, or an
+ /// error.
Leaf(Ty<'tcx>),
/// `&[u8]` or `&[u8; N]`: its bytes, start, and length.
Slice,
@@ -136,11 +137,11 @@ impl<'tcx> Shape<'tcx> {
/// The parts that are JS objects as the local's object holds them: each slice, by its
/// bytes, and each value held whole that is no number.
- fn objects(&self, at: usize, out: &mut Vec) {
+ fn objects(&self, tcx: TyCtxt<'tcx>, at: usize, out: &mut Vec) {
match self {
Shape::Unit => {}
Shape::Leaf(ty) => {
- if !number(*ty) {
+ if !number(tcx, *ty) {
out.push(at);
}
}
@@ -148,14 +149,14 @@ impl<'tcx> Shape<'tcx> {
Shape::Tuple(_, fields) => {
let mut at = at;
for field in fields {
- field.objects(at, out);
+ field.objects(tcx, at, out);
at += field.size();
}
}
Shape::Enum(_, variants) => {
let mut at = at + usize::from(self.flagged());
for field in variants.iter().flatten().flatten() {
- field.objects(at, out);
+ field.objects(tcx, at, out);
at += field.size();
}
}
@@ -184,11 +185,20 @@ fn flag_name(ty: Ty<'_>) -> &'static str {
}
}
-/// Whether a `ty`'s JS value is a number or flag, which making its object makes nothing of.
-fn number(ty: Ty<'_>) -> bool {
+/// Whether a `ty`'s JS value is a number or flag, which making its object makes nothing of,
+/// or an `Option` of one, which is that or `undefined`.
+fn number<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
+ match ty.kind() {
+ ty::Adt(adt, args) if Std::of(tcx, adt.did()) == Some(Std::Option) => plain_number(args.type_at(0)),
+ _ => plain_number(ty),
+ }
+}
+
+/// Whether a `ty`'s JS value is a number or flag.
+fn plain_number(ty: Ty<'_>) -> bool {
match ty.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => true,
- ty::Ref(_, inner, _) => number(*inner),
+ ty::Ref(_, inner, _) => plain_number(*inner),
_ => false,
}
}
@@ -320,8 +330,9 @@ impl<'tcx> crate::lower::Translator<'_, 'tcx> {
/// Where `instance` hands back its `Ok`'s parts, if it does: a function of the crate's
/// that only translated code calls directly, and that returns a `Result` of byte slices
- /// and scalars, or of numbers alone, whose error is one value that is never
- /// `undefined`, such as `Result<(u64, &[u8]), E>` or `Result<(i64, u64), E>`, writes
+ /// and scalars, or of numbers alone, an `Option` of one counting as one, whose error is
+ /// one value that is never `undefined`, such as `Result<(u64, &[u8]), E>`,
+ /// `Result<(i64, u64), E>`, or `Result, E>`, writes
/// the `Ok`'s parts into a module-level slot its caller reads at once, and returns its
/// error or `undefined`. One whose first part is a number returns that, or `undefined`
/// for an error, and writes the error into the slot instead.
@@ -361,7 +372,7 @@ impl<'tcx> crate::lower::Translator<'_, 'tcx> {
let numbers = !parts.is_empty()
&& parts
.iter()
- .all(|(_, part)| matches!(part, Part::Value(t) if number(*t)));
+ .all(|(_, part)| matches!(part, Part::Value(t) if number(self.tcx, *t)));
if !shape.has_slice() && !numbers {
return None;
}
@@ -474,6 +485,14 @@ impl<'tcx> crate::lower::Translator<'_, 'tcx> {
let fields = tys.iter().map(|t| self.shape(t)).collect:: >>()?;
Some(Shape::Tuple(ty, fields))
}
+ // That or `undefined`, one JS value, as the number is.
+ ty::Adt(adt, args)
+ if Std::of(tcx, adt.did()) == Some(Std::Option)
+ && plain_number(args.type_at(0))
+ && matches!(self.shape(args.type_at(0)), Some(Shape::Leaf(_))) =>
+ {
+ Some(Shape::Leaf(ty))
+ }
ty::Adt(adt, args)
if matches!(
Std::of(tcx, adt.did()),
@@ -1297,7 +1316,7 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> {
let mut parts = Vec::new();
match made.boxed {
true => parts.extend(made.parts.clone()),
- false => shapes[&made.local].objects(0, &mut parts),
+ false => shapes[&made.local].objects(self.tcx, 0, &mut parts),
}
parts
.into_iter()