| 1 | import { assert, describe, it } from "@effect/vitest" |
| 2 | import { Result } from "effect" |
| 3 | import * as Hex from "effect/encoding/Hex" |
| 4 | |
| 5 | const assertRandom = (length: number, expectedLength: number): void => { |
| 6 | const value = Hex.random(length) |
| 7 | assert.strictEqual(value.length, expectedLength) |
| 8 | assert.match(value, /^[0-9a-f]*$/) |
| 9 | } |
| 10 | |
| 11 | describe("Hex", () => { |
| 12 | it("encodes strings and bytes as lowercase hexadecimal", () => { |
| 13 | assert.strictEqual(Hex.encode("hello"), "68656c6c6f") |
| 14 | assert.strictEqual(Hex.encode(new Uint8Array([72, 101, 108, 108, 111])), "48656c6c6f") |
| 15 | }) |
| 16 | |
| 17 | it("decodes mixed-case bytes and UTF-8 strings", () => { |
| 18 | assert.deepStrictEqual( |
| 19 | Result.getOrThrow(Hex.decode("48656C6c6F")), |
| 20 | new Uint8Array([72, 101, 108, 108, 111]) |
| 21 | ) |
| 22 | assert.strictEqual(Result.getOrThrow(Hex.decodeString("f09f918b")), "👋") |
| 23 | }) |
| 24 | |
| 25 | it("rejects odd lengths and non-hexadecimal characters", () => { |
| 26 | const oddLength = Hex.decode("abc") |
| 27 | assert.isTrue(Result.isFailure(oddLength)) |
| 28 | if (Result.isFailure(oddLength)) { |
| 29 | assert.strictEqual(oddLength.failure.kind, "Decode") |
| 30 | assert.strictEqual(oddLength.failure.module, "Hex") |
| 31 | assert.strictEqual(oddLength.failure.input, "abc") |
| 32 | } |
| 33 | |
| 34 | assert.isTrue(Result.isFailure(Hex.decode("zz"))) |
| 35 | }) |
| 36 | |
| 37 | describe("random", () => { |
| 38 | it("generates lowercase hexadecimal words", () => { |
| 39 | assertRandom(0, 0) |
| 40 | assertRandom(8, 8) |
| 41 | assertRandom(16, 16) |
| 42 | assertRandom(32, 32) |
| 43 | }) |
| 44 | |
| 45 | it("rounds non-negative lengths down to multiples of 8", () => { |
| 46 | assertRandom(7, 0) |
| 47 | assertRandom(15.9, 8) |
| 48 | assertRandom(23, 16) |
| 49 | }) |
| 50 | |
| 51 | it("uses unsigned 32-bit coercion without validation", () => { |
| 52 | assertRandom(Number.NaN, 0) |
| 53 | assertRandom(Number.POSITIVE_INFINITY, 0) |
| 54 | assertRandom(2 ** 32, 0) |
| 55 | assertRandom(2 ** 32 + 8, 8) |
| 56 | }) |
| 57 | }) |
| 58 | }) |