import { describe, expect, it } from "@suaveplan/testing/runner"; import { encode } from "./encoder.js"; import { tryEncodeFloat16 } from "./half-float.js"; const hex = (b: Uint8Array): string => Array.from(b, (x) => x.toString(16).padStart(2, "0")).join(""); describe("encoder — bigint range branches", () => { it("encodes -1n as major-1 minor=0", { timeout: 5000 }, () => { // -1n is in [-u64, -1]: encoded as major 1, value = -(-1) - 1 = 0 expect(hex(encode(-1n))).toBe("20"); }); it("encodes -100n via major-1", { timeout: 5000 }, () => { // -100n encodes as major 1 minor=24 0x63 (= -1 - 99 = -100) expect(hex(encode(-100n))).toBe("3863"); }); it("encodes negative on the u64 boundary", { timeout: 5000 }, () => { // -2^64 in range? value >= -0x10000000000000000n is true for value=-2^64 // -value - 1n = 2^64 - 1 = 0xffffffffffffffff fits in 8 bytes expect(hex(encode(-(2n ** 64n)))).toBe("3bffffffffffffffff"); }); }); describe("encoder — half-float edge branches", () => { it("subnormal reconstruction mismatch returns undefined", { timeout: 5000, }, () => { // 1.5 * 2^-24 — mant rounds to 2, reconstructed = 2^-23 ≠ original expect(tryEncodeFloat16(1.5 * 2 ** -24)).toBeUndefined(); }); it("returns undefined when rollup overflows exponent", { timeout: 5000, }, () => { // Value such that mantissa rounds up to 1024, pushing biasedExp from // 30 (0x1e) to 31 (0x1f) — overflow → undefined. // 65520 has mantissa-bits 1023.5 which rounds to 1024. expect(tryEncodeFloat16(65520)).toBeUndefined(); }); it("returns undefined when normal-path reconstruction mismatch", { timeout: 5000, }, () => { // 1.0001 — fraction rounds to a mantissa whose reconstructed value // differs from the input by a tiny amount. expect(tryEncodeFloat16(1.0001)).toBeUndefined(); }); }); describe("encoder — Map with Tagged keys", () => { it("deterministic mode sorts mixed-type keys by canonical bytes", { timeout: 5000, }, () => { // Keys: "b" (62), 1 (01), 0xff (18ff) const m = new Map([ ["b", 1], [1, 2], [255, 3], ]); // Canonical-byte sort: 01 < 18ff < 6162. Expected order: 1, 255, "b" const out = hex(encode(m, { deterministic: true })); expect(out.startsWith("a3")).toBe(true); // Body: 0102 18ff03 616201 expect(out).toBe("a3010218ff036162 01".replace(/\s/g, "")); }); }); describe("encoder — depth boundary", () => { it("encodes at exact maxDepth without throw", { timeout: 5000 }, () => { let nested: unknown = 1; for (let i = 0; i < 5; i++) nested = [nested]; // maxDepth=5 should accept depth-5; depth-6 throws expect(() => encode(nested, { maxDepth: 5 })).not.toThrow(); }); }); describe("encoder — depth on bigint outside u64", () => { it("encodes large positive bignum via tag 2", { timeout: 5000 }, () => { // 2^128 → tag 2 + 16-byte payload expect(hex(encode(2n ** 128n)).startsWith("c25")).toBe(true); }); }); describe("encoder — float branch coverage", () => { it("deterministic mode encodes NaN via float32 (NaN-NaN equality path)", { timeout: 5000, }, () => { const out = encode(Number.NaN, { deterministic: true }); expect(out[0]).toBe(0xfa); // float32 }); it("preferFloat16=true falls through to float32 when f16 not exact", { timeout: 5000, }, () => { // 1 + 2^-23 — float32-exact; f16 cannot represent the fractional bit. const value = 1 + 2 ** -23; const out = encode(value, { preferFloat16: true }); expect(out[0]).toBe(0xfa); // float32 expect(out.length).toBe(5); }); it("default float path emits float64 when not exact in float32", { timeout: 5000, }, () => { const out = encode(0.1); expect(out[0]).toBe(0xfb); // float64 expect(out.length).toBe(9); }); });