@helios-lang/effect 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/bun.lock +60 -0
  2. package/package.json +1 -1
  3. package/tsconfig.build.tsbuildinfo +1 -0
  4. package/tsconfig.check.tsbuildinfo +1 -0
  5. package/tsconfig.tsbuildinfo +1 -0
  6. package/types/Address.d.ts +5 -0
  7. package/types/Address.d.ts.map +1 -0
  8. package/types/Bech32.d.ts +30 -0
  9. package/types/Bech32.d.ts.map +1 -0
  10. package/types/Cbor.d.ts +430 -0
  11. package/types/Cbor.d.ts.map +1 -0
  12. package/types/Ledger/Address.d.ts +109 -0
  13. package/types/Ledger/Address.d.ts.map +1 -0
  14. package/types/Ledger/AssetClass.d.ts +101 -0
  15. package/types/Ledger/AssetClass.d.ts.map +1 -0
  16. package/types/Ledger/Assets.d.ts +70 -0
  17. package/types/Ledger/Assets.d.ts.map +1 -0
  18. package/types/Ledger/Credential.d.ts +26 -0
  19. package/types/Ledger/Credential.d.ts.map +1 -0
  20. package/types/Ledger/DatumHash.d.ts +40 -0
  21. package/types/Ledger/DatumHash.d.ts.map +1 -0
  22. package/types/Ledger/IsMainnet.d.ts +6 -0
  23. package/types/Ledger/IsMainnet.d.ts.map +1 -0
  24. package/types/Ledger/MintingPolicy.d.ts +39 -0
  25. package/types/Ledger/MintingPolicy.d.ts.map +1 -0
  26. package/{src/Ledger/NetworkParams.ts → types/Ledger/NetworkParams.d.ts} +24 -26
  27. package/types/Ledger/NetworkParams.d.ts.map +1 -0
  28. package/types/Ledger/PubKeyHash.d.ts +40 -0
  29. package/types/Ledger/PubKeyHash.d.ts.map +1 -0
  30. package/types/Ledger/TxId.d.ts +10 -0
  31. package/types/Ledger/TxId.d.ts.map +1 -0
  32. package/types/Ledger/TxInput.d.ts +55 -0
  33. package/types/Ledger/TxInput.d.ts.map +1 -0
  34. package/types/Ledger/TxOutput.d.ts +63 -0
  35. package/types/Ledger/TxOutput.d.ts.map +1 -0
  36. package/types/Ledger/TxOutputDatum.d.ts +41 -0
  37. package/types/Ledger/TxOutputDatum.d.ts.map +1 -0
  38. package/types/Ledger/TxOutputId.d.ts +14 -0
  39. package/types/Ledger/TxOutputId.d.ts.map +1 -0
  40. package/types/Ledger/ValidatorHash.d.ts +40 -0
  41. package/types/Ledger/ValidatorHash.d.ts.map +1 -0
  42. package/types/Ledger/index.d.ts +16 -0
  43. package/types/Ledger/index.d.ts.map +1 -0
  44. package/types/Uplc/Cek.d.ts +72 -0
  45. package/types/Uplc/Cek.d.ts.map +1 -0
  46. package/types/Uplc/Data.d.ts +530 -0
  47. package/types/Uplc/Data.d.ts.map +1 -0
  48. package/types/Uplc/DataSchema.d.ts +227 -0
  49. package/types/Uplc/DataSchema.d.ts.map +1 -0
  50. package/types/Uplc/Primitive.d.ts +26 -0
  51. package/types/Uplc/Primitive.d.ts.map +1 -0
  52. package/types/Uplc/index.d.ts +3 -0
  53. package/types/Uplc/index.d.ts.map +1 -0
  54. package/types/index.d.ts +5 -0
  55. package/types/index.d.ts.map +1 -0
  56. package/types/internal/Base32.d.ts +49 -0
  57. package/types/internal/Base32.d.ts.map +1 -0
  58. package/types/internal/BigEndian.d.ts +22 -0
  59. package/types/internal/BigEndian.d.ts.map +1 -0
  60. package/types/internal/Bits.d.ts +123 -0
  61. package/types/internal/Bits.d.ts.map +1 -0
  62. package/types/internal/Bytes.d.ts +88 -0
  63. package/types/internal/Bytes.d.ts.map +1 -0
  64. package/types/internal/Flat.d.ts +71 -0
  65. package/types/internal/Flat.d.ts.map +1 -0
  66. package/types/internal/Float.d.ts +38 -0
  67. package/types/internal/Float.d.ts.map +1 -0
  68. package/types/internal/Utf8.d.ts +24 -0
  69. package/types/internal/Utf8.d.ts.map +1 -0
  70. package/src/Bech32.test.ts +0 -117
  71. package/src/Bech32.ts +0 -198
  72. package/src/Cbor.test.ts +0 -1610
  73. package/src/Cbor.ts +0 -1704
  74. package/src/Ledger/Address.ts +0 -248
  75. package/src/Ledger/AssetClass.ts +0 -90
  76. package/src/Ledger/Assets.ts +0 -164
  77. package/src/Ledger/Credential.ts +0 -29
  78. package/src/Ledger/DatumHash.ts +0 -36
  79. package/src/Ledger/IsMainnet.ts +0 -6
  80. package/src/Ledger/MintingPolicy.ts +0 -57
  81. package/src/Ledger/PubKeyHash.ts +0 -36
  82. package/src/Ledger/TxId.ts +0 -31
  83. package/src/Ledger/TxInput.test.ts +0 -21
  84. package/src/Ledger/TxInput.ts +0 -66
  85. package/src/Ledger/TxOutput.ts +0 -166
  86. package/src/Ledger/TxOutputDatum.ts +0 -64
  87. package/src/Ledger/TxOutputId.ts +0 -63
  88. package/src/Ledger/ValidatorHash.ts +0 -36
  89. package/src/Ledger/index.ts +0 -15
  90. package/src/Uplc/Cek.ts +0 -92
  91. package/src/Uplc/Data.test.ts +0 -321
  92. package/src/Uplc/Data.ts +0 -657
  93. package/src/Uplc/Primitive.ts +0 -56
  94. package/src/Uplc/index.ts +0 -2
  95. package/src/index.ts +0 -4
  96. package/src/internal/Base32.test.ts +0 -219
  97. package/src/internal/Base32.ts +0 -341
  98. package/src/internal/BigEndian.test.ts +0 -79
  99. package/src/internal/BigEndian.ts +0 -67
  100. package/src/internal/Bits.test.ts +0 -300
  101. package/src/internal/Bits.ts +0 -398
  102. package/src/internal/Bytes.test.ts +0 -369
  103. package/src/internal/Bytes.ts +0 -343
  104. package/src/internal/Flat.test.ts +0 -29
  105. package/src/internal/Flat.ts +0 -387
  106. package/src/internal/Float.test.ts +0 -51
  107. package/src/internal/Float.ts +0 -190
  108. package/src/internal/Utf8.test.ts +0 -69
  109. package/src/internal/Utf8.ts +0 -58
@@ -1,29 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import { makeWriter as makeBitWriter } from "./Bits.js"
3
- import * as Flat from "./Flat.js"
4
-
5
- describe("Flat.encodeInt()", () => {
6
- it("writes 8 bits for 0", () => {
7
- const bw = makeBitWriter()
8
-
9
- Flat.encodeInt(bw, 0n)
10
-
11
- expect(bw.length).toBe(8)
12
- })
13
-
14
- it("writes 8 bits for 127", () => {
15
- const bw = makeBitWriter()
16
-
17
- Flat.encodeInt(bw, 127n)
18
-
19
- expect(bw.length).toBe(8)
20
- })
21
-
22
- it("writes 16 bits for 128", () => {
23
- const bw = makeBitWriter()
24
-
25
- Flat.encodeInt(bw, 128n)
26
-
27
- expect(bw.length).toBe(16)
28
- })
29
- })
@@ -1,387 +0,0 @@
1
- import * as Bits from "./Bits.js"
2
-
3
- /**
4
- * Instantiate a `Flat.Reader` with {@link makeReader}.
5
- */
6
- export interface Reader {
7
- isAtEnd(): boolean
8
- readBits(n: number): number
9
- readBool(): boolean
10
- readBuiltinId(): number
11
- readBytes(): number[]
12
- readInt(): bigint
13
- readTag(): number
14
- readList<T>(readItem: (r: Reader) => T): T[]
15
- }
16
-
17
- /**
18
- * @param bytes
19
- * @returns
20
- */
21
- export function makeReader(bytes: string | number[] | Uint8Array): Reader {
22
- return new ReaderImpl(bytes)
23
- }
24
-
25
- class ReaderImpl implements Reader {
26
- private readonly bitReader: Bits.Reader
27
-
28
- /**
29
- * @param bytes
30
- */
31
- constructor(bytes: string | number[] | Uint8Array) {
32
- this.bitReader = Bits.makeReader(bytes)
33
- }
34
-
35
- isAtEnd(): boolean {
36
- return this.bitReader.isAtEnd()
37
- }
38
-
39
- /**
40
- * @param n
41
- * @returns
42
- */
43
- readBits(n: number): number {
44
- return this.bitReader.readBits(n)
45
- }
46
-
47
- readBool(): boolean {
48
- return this.readBits(1) == 1
49
- }
50
-
51
- readBuiltinId(): number {
52
- return this.readBits(7)
53
- }
54
-
55
- readBytes(): number[] {
56
- return decodeBytes(this.bitReader)
57
- }
58
-
59
- /**
60
- * @returns {bigint}
61
- */
62
- readInt(): bigint {
63
- return decodeInt(this.bitReader)
64
- }
65
-
66
- /**
67
- * Reads a Plutus-core list with a specified size per element
68
- * Calls itself recursively until the end of the list is reached
69
- * @template T
70
- * @param readItem
71
- * @returns
72
- */
73
- readList<T>(readItem: (r: Reader) => T): T[] {
74
- // Cons and Nil constructors come from Lisp/Haskell
75
- // cons 'a' creates a linked list node,
76
- // nil creates an empty linked list
77
- const nilOrCons = this.readBits(1)
78
-
79
- if (nilOrCons == 0) {
80
- return []
81
- } else {
82
- return [readItem(this)].concat(this.readList(readItem))
83
- }
84
- }
85
-
86
- readTag(): number {
87
- return this.readBits(4)
88
- }
89
- }
90
-
91
- /**
92
- * Instantiate a `FlatWriter` with {@link makeWriter}.
93
- */
94
- export interface Writer {
95
- writeBool(b: boolean): Writer
96
- writeBytes(bytes: number[]): Writer
97
- writeInt(x: bigint | number): Writer
98
- writeListCons(): Writer
99
- writeListNil(): Writer
100
- writeTermTag(tag: number): Writer
101
- writeTypeBits(typeBits: string): Writer
102
- writeBuiltinId(id: number): Writer
103
- finalize(): number[]
104
- }
105
-
106
- /**
107
- * @returns
108
- */
109
- export function makeWriter(): Writer {
110
- return new WriterImpl()
111
- }
112
-
113
- class WriterImpl implements Writer {
114
- private readonly bitWriter: Bits.Writer
115
-
116
- constructor() {
117
- this.bitWriter = Bits.makeWriter()
118
- }
119
-
120
- /**
121
- * @param b
122
- * @returns
123
- * Self for chaining
124
- */
125
- writeBool(b: boolean): Writer {
126
- if (b) {
127
- this.bitWriter.writeBits("1")
128
- } else {
129
- this.bitWriter.writeBits("0")
130
- }
131
-
132
- return this
133
- }
134
-
135
- /**
136
- * @param bytes
137
- * @returns
138
- * Self for chaining
139
- */
140
- writeBytes(bytes: number[]): Writer {
141
- encodeBytes(this.bitWriter, bytes)
142
-
143
- return this
144
- }
145
-
146
- /**
147
- * @param x
148
- * @returns
149
- * Self for chaining
150
- * @throws
151
- * If x is negative
152
- */
153
- writeInt(x: bigint): Writer {
154
- if (x < 0) {
155
- throw new Error("x in writeInt isn't positive")
156
- }
157
- encodeInt(this.bitWriter, x)
158
-
159
- return this
160
- }
161
-
162
- /**
163
- * @returns
164
- * Self for chaining
165
- */
166
- writeListCons(): Writer {
167
- this.bitWriter.writeBits("1")
168
- return this
169
- }
170
-
171
- /**
172
- * @returns
173
- * Self for chaining
174
- */
175
- writeListNil(): Writer {
176
- this.bitWriter.writeBits("0")
177
- return this
178
- }
179
-
180
- /**
181
- * @param tag
182
- * @returns
183
- * Self for chaining
184
- */
185
- writeTermTag(tag: number): Writer {
186
- this.bitWriter.writeBits(Bits.pad(tag.toString(2), 4))
187
- return this
188
- }
189
-
190
- /**
191
- * @param typeBits
192
- * @returns
193
- * Self for chaining
194
- */
195
- writeTypeBits(typeBits: string): Writer {
196
- this.bitWriter.writeBits("1" + typeBits + "0")
197
- return this
198
- }
199
-
200
- /**
201
- * @param id
202
- */
203
- writeBuiltinId(id: number): Writer {
204
- this.bitWriter.writeBits(Bits.pad(id.toString(2), 7))
205
-
206
- return this
207
- }
208
-
209
- /**
210
- * @returns
211
- */
212
- finalize(): number[] {
213
- return this.bitWriter.finalize()
214
- }
215
- }
216
-
217
- /**
218
- * @param reader
219
- * @returns
220
- */
221
- export function decodeBytes(reader: Bits.Reader): number[] {
222
- reader.moveToByteBoundary(true)
223
-
224
- const bytes = []
225
-
226
- let nChunk = reader.readByte()
227
-
228
- while (nChunk > 0) {
229
- for (let i = 0; i < nChunk; i++) {
230
- bytes.push(reader.readByte())
231
- }
232
-
233
- nChunk = reader.readByte()
234
- }
235
-
236
- return bytes
237
- }
238
-
239
- /**
240
- * Write a list of bytes to the bitWriter using flat encoding.
241
- * Used by UplcString, UplcByteArray and UplcDataValue
242
- * Equivalent to E_B* function in Plutus-core docs
243
- * @param writer
244
- * @param bytes
245
- * @param pad
246
- * Optional, defaults to false
247
- */
248
- export function encodeBytes(
249
- writer: Bits.Writer,
250
- bytes: number[],
251
- pad: boolean = true
252
- ): void {
253
- if (pad) {
254
- writer.padToByteBoundary(true)
255
- }
256
-
257
- // the rest of this function is equivalent to E_C* function in Plutus-core docs
258
- const n = bytes.length
259
- let pos = 0
260
-
261
- // write chunks of 255
262
- while (pos < n) {
263
- // each iteration is equivalent to E_C function in Plutus-core docs
264
-
265
- const nChunk = Math.min(n - pos, 255)
266
-
267
- // equivalent to E_8 function in Plutus-core docs
268
- writer.writeBits(Bits.pad(nChunk.toString(2), 8))
269
-
270
- for (let i = pos; i < pos + nChunk; i++) {
271
- const b = bytes[i]
272
-
273
- // equivalent to E_8 function in Plutus-core docs
274
- writer.writeBits(Bits.pad(b.toString(2), 8))
275
- }
276
-
277
- pos += nChunk
278
- }
279
-
280
- if (pad) {
281
- writer.writeBits("00000000")
282
- }
283
- }
284
-
285
- /**
286
- * Includes type bits
287
- * @param n
288
- * @returns
289
- */
290
- export function bytesSize(n: number): number {
291
- return 4 + n * 8 + Math.ceil(n / 256) * 8 + 8
292
- }
293
-
294
- /**
295
- * Returns an unsigned (zigzag encoded) bigint
296
- * @param reader
297
- * @returns
298
- */
299
- export function decodeInt(reader: Bits.Reader): bigint {
300
- const bytes = []
301
-
302
- let b = reader.readByte()
303
- bytes.push(b)
304
-
305
- while (!rawByteIsLast(b)) {
306
- b = reader.readByte()
307
- bytes.push(b)
308
- }
309
-
310
- // strip the leading bit
311
- return decodeIntLE7(bytes.map((b) => parseRawByte(b))) // raw int is unsigned
312
- }
313
-
314
- /**
315
- * Combines a list of Plutus-core bytes into a bigint (leading bit of each byte is ignored).
316
- * Differs from bytesToBigInt in utils.js because only 7 bits are used from each byte.
317
- * @param bytes
318
- * @returns
319
- */
320
- function decodeIntLE7(bytes: number[]): bigint {
321
- let value = BigInt(0)
322
-
323
- const n = bytes.length
324
-
325
- for (let i = 0; i < n; i++) {
326
- const b = bytes[i]
327
-
328
- // 7 (not 8), because leading bit isn't used here
329
- value = value + BigInt(b) * pow2(BigInt(i) * 7n)
330
- }
331
-
332
- return value
333
- }
334
-
335
- /**
336
- * 2 to the power 'p' for bigint.
337
- * @param p
338
- * @returns
339
- */
340
- function pow2(p: bigint): bigint {
341
- return p <= 0n ? 1n : 2n << (p - 1n)
342
- }
343
-
344
- /**
345
- * Parses a single byte in the Plutus-core byte-list representation of an int
346
- * @param b
347
- * @returns
348
- */
349
- function parseRawByte(b: number): number {
350
- return b & 0b01111111
351
- }
352
-
353
- /**
354
- * Returns true if 'b' is the last byte in the Plutus-core byte-list representation of an int.
355
- * @param b
356
- * @returns
357
- */
358
- function rawByteIsLast(b: number): boolean {
359
- return (b & 0b10000000) == 0
360
- }
361
-
362
- /**
363
- * @param bitWriter
364
- * @param x
365
- * positive number
366
- */
367
- export function encodeInt(bitWriter: Bits.Writer, x: bigint) {
368
- const bitString = Bits.pad(x.toString(2), 7)
369
-
370
- // split every 7th
371
- const parts = []
372
- for (let i = 0; i < bitString.length; i += 7) {
373
- parts.push(bitString.slice(i, i + 7))
374
- }
375
-
376
- // reverse the parts
377
- parts.reverse()
378
-
379
- for (let i = 0; i < parts.length; i++) {
380
- if (i == parts.length - 1) {
381
- // last
382
- bitWriter.writeBits("0" + parts[i])
383
- } else {
384
- bitWriter.writeBits("1" + parts[i])
385
- }
386
- }
387
- }
@@ -1,51 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import { Either } from "effect"
3
- import { toHex } from "./Bytes.js"
4
- import * as Float from "./Float.js"
5
-
6
- /**
7
- * Taken from https://en.wikipedia.org/wiki/Half-precision_floating-point_format
8
- * [encoded, original number]
9
- */
10
- const testVector: [number[], number][] = [
11
- [[0, 0], 0],
12
- [[0, 1], 0.000000059604645],
13
- [[0x03, 0xff], 0.000060975552],
14
- [[4, 0], 0.00006103515625],
15
- [[0x35, 0x55], 0.33325195],
16
- [[0x3b, 0xff], 0.99951172],
17
- [[0x3c, 0x00], 1],
18
- [[0x3c, 0x01], 1.00097656],
19
- [[0x7b, 0xff], 65504],
20
- [[0x7c, 0x00], Number.POSITIVE_INFINITY],
21
- [[0x7c, 0x01], Number.NaN],
22
- [[0x80, 0x00], -0],
23
- [[0xc0, 0x00], -2],
24
- [[0xfc, 0x00], Number.NEGATIVE_INFINITY]
25
- ]
26
-
27
- describe("Float.decodeFloat16()", () => {
28
- testVector.forEach(([bytes, f]) => {
29
- it(`decodes #${toHex(bytes)} as ${f}`, () => {
30
- expect(
31
- Either.map(Float.decodeFloat16(bytes), (x) => x.toExponential(7))
32
- ).toEqual(Either.right(f.toExponential(7)))
33
- })
34
- })
35
-
36
- it("fails for more than 2 input bytes", () => {
37
- expect(Float.decodeFloat16([0, 0, 0])._tag).toBe("Left")
38
- })
39
-
40
- it("fails for less than 2 input bytes", () => {
41
- expect(Float.decodeFloat16([0])._tag).toBe("Left")
42
- })
43
- })
44
-
45
- describe("Float.encodeFloat16()", () => {
46
- testVector.forEach(([bytes, f]) => {
47
- it(`encodes ${f} as #${toHex(bytes)}`, () => {
48
- expect(Float.encodeFloat16(f)).toEqual(bytes)
49
- })
50
- })
51
- })
@@ -1,190 +0,0 @@
1
- import { Encoding, Either } from "effect"
2
- import { toHex } from "./Bytes.js"
3
-
4
- const SPECIAL_EXPONENT = 31
5
- const LARGEST_SIGNIFICAND = 1024
6
- const POW2 = [
7
- 0.00006103515625, // 2^-14
8
- 0.0001220703125, // 2^-13
9
- 0.000244140625, // 2^-12
10
- 0.00048828125, // 2^-11
11
- 0.0009765625, // 2^-10
12
- 0.001953125, // 2^-9
13
- 0.00390625, // 2^-8
14
- 0.0078125, // 2^-7
15
- 0.015625, // 2^-6
16
- 0.03125, // 2^-5
17
- 0.0625, // 2^-4
18
- 0.125, // 2^-3
19
- 0.25, // 2^-2
20
- 0.5, // 2^-1
21
- 1, // 2^0
22
- 2, // 2^1
23
- 4, // 2^2
24
- 8, // 2^3
25
- 16, // 2^4
26
- 32, // 2^5
27
- 64, // 2^6
28
- 128, // 2^7
29
- 256, // 2^8
30
- 512, // 2^9
31
- 1024, // 2^10
32
- 2048, // 2^11
33
- 4096, // 2^12
34
- 8192, // 2^13
35
- 16384, // 2^14
36
- 32768, // 2^15
37
- 65536 // 2^16
38
- ]
39
-
40
- /**
41
- * Custom IEEE 754 Float16 implementation, not fast, but easy to audit
42
- * @param {number[]} bytes
43
- * @returns {number}
44
- */
45
- export function decodeFloat16(
46
- bytes: number[]
47
- ): Either.Either<number, Encoding.DecodeException> {
48
- if (bytes.length != 2) {
49
- return Either.left(
50
- Encoding.DecodeException(
51
- toHex(bytes),
52
- `expected 2 bytes for IEEE 754 encoded Float16 number, got ${bytes.length}`
53
- )
54
- )
55
- }
56
-
57
- const sign = bytes[0] >> 7 ? -1 : 1
58
- const exponent = (bytes[0] & 0b01111100) >> 2
59
- const significand = (bytes[0] & 0b00000011) * 256 + bytes[1]
60
-
61
- if (exponent === 0) {
62
- if (significand == 0) {
63
- return Either.right(sign < 0 ? -0 : 0)
64
- } else {
65
- return Either.right((sign * POW2[0] * significand) / LARGEST_SIGNIFICAND)
66
- }
67
- } else if (exponent === SPECIAL_EXPONENT) {
68
- if (significand == 0) {
69
- return Either.right(
70
- sign < 0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY
71
- )
72
- } else {
73
- return Either.right(Number.NaN)
74
- }
75
- } else {
76
- return Either.right(
77
- sign * POW2[exponent - 1] * (1.0 + significand / LARGEST_SIGNIFICAND)
78
- )
79
- }
80
- }
81
-
82
- /**
83
- * Custom IEEE 754 Float16 implementation, not fast, but easy to audit
84
- * @param f
85
- * @returns
86
- */
87
- export function encodeFloat16(f: number): number[] {
88
- if (Object.is(f, 0)) {
89
- return [0, 0]
90
- } else if (Object.is(f, -0)) {
91
- return [0x80, 0]
92
- } else if (f === Number.NEGATIVE_INFINITY) {
93
- return [0xfc, 0]
94
- } else if (f === Number.POSITIVE_INFINITY) {
95
- return [0x7c, 0]
96
- } else if (Number.isNaN(f)) {
97
- return [0x7c, 1]
98
- } else {
99
- const sign = Math.sign(f)
100
- const signBit = sign > 0 ? 0 : 0b10000000
101
- f = Math.abs(f)
102
-
103
- if (f < POW2[0]) {
104
- const significand = Math.floor((f / POW2[0]) * LARGEST_SIGNIFICAND)
105
-
106
- return [signBit | (significand >> 8), significand & 0xff]
107
- } else {
108
- const unbiasedExponent = Math.floor(Math.log2(f))
109
- const exponent = (unbiasedExponent + 15) & 0b00011111
110
-
111
- const significand = Math.round(
112
- (f / POW2[exponent - 1] - 1) * LARGEST_SIGNIFICAND
113
- )
114
-
115
- return [
116
- signBit | (exponent << 2) | (significand >> 8),
117
- significand & 0xff
118
- ]
119
- }
120
- }
121
- }
122
-
123
- /**
124
- * Leverages the builtin DataView class to decode a IEEE 754 float32 number
125
- * @param {number[]} bytes
126
- * @returns
127
- */
128
- export function decodeFloat32(
129
- bytes: number[]
130
- ): Either.Either<number, Encoding.DecodeException> {
131
- if (bytes.length != 4) {
132
- return Either.left(
133
- Encoding.DecodeException(
134
- toHex(bytes),
135
- `expected 4 bytes for IEEE 754 encoded Float32, got ${bytes.length} bytes`
136
- )
137
- )
138
- }
139
-
140
- const view = new DataView(Uint8Array.from(bytes).buffer)
141
-
142
- return Either.right(view.getFloat32(0))
143
- }
144
-
145
- /**
146
- * Leverages the builtin DataView class to encode a floating point number using IEEE 754 float32 encoding
147
- * @param f
148
- * @returns
149
- */
150
- export function encodeFloat32(f: number): number[] {
151
- const view = new DataView(new ArrayBuffer(4))
152
-
153
- view.setFloat32(0, f)
154
-
155
- return Array.from(new Uint8Array(view.buffer))
156
- }
157
-
158
- /**
159
- * Leverages the builtin DataView class to decode a IEEE 754 float64 number
160
- * @param bytes
161
- * @returns
162
- */
163
- export function decodeFloat64(
164
- bytes: number[]
165
- ): Either.Either<number, Encoding.DecodeException> {
166
- if (bytes.length != 8) {
167
- return Either.left(
168
- Encoding.DecodeException(
169
- `expected 8 bytes for IEEE 754 encoded Float64, got ${bytes.length} bytes`
170
- )
171
- )
172
- }
173
-
174
- const view = new DataView(Uint8Array.from(bytes).buffer)
175
-
176
- return Either.right(view.getFloat64(0))
177
- }
178
-
179
- /**
180
- * Leverages the builtin DataView class to encode a floating point number using IEEE 754 float64 encoding
181
- * @param f
182
- * @returns
183
- */
184
- export function encodeFloat64(f: number): number[] {
185
- const view = new DataView(new ArrayBuffer(8))
186
-
187
- view.setFloat64(0, f)
188
-
189
- return Array.from(new Uint8Array(view.buffer))
190
- }
@@ -1,69 +0,0 @@
1
- import { describe, expect, it } from "bun:test"
2
- import { Effect } from "effect"
3
- import * as Utf8 from "./Utf8.js"
4
-
5
- describe("Utf8.isValid", () => {
6
- it("returns true for []", () => {
7
- expect(Utf8.isValid([])).toBe(true)
8
- })
9
-
10
- it("returns true for [104, 101, 108, ...]", () => {
11
- expect(
12
- Utf8.isValid([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100])
13
- ).toBe(true)
14
- })
15
-
16
- it("returns false for [256] (invalid byte)", () => {
17
- expect(Utf8.isValid([256])).toBe(false)
18
- })
19
-
20
- it("returns false for [255, 255, 255, 255] (invalid utf-8 sequence)", () => {
21
- expect(Utf8.isValid([255, 255, 255, 255])).toBe(false)
22
- })
23
-
24
- it("returns true for [0xf0, 0xb1, 0x8d, 0x90]", () => {
25
- expect(Utf8.isValid([0xf0, 0xb1, 0x8d, 0x90])).toBe(true)
26
- })
27
- })
28
-
29
- describe("Utf8.encode", () => {
30
- it("returns [] for an empty string", () => {
31
- expect(Array.from(Utf8.encode(""))).toEqual([])
32
- })
33
-
34
- it('returns [104, 101, 108, ...] for "hello world"', () => {
35
- expect(Array.from(Utf8.encode("hello world"))).toEqual([
36
- 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100
37
- ])
38
- })
39
-
40
- it('returns [0xf0, 0xb1, 0x8d, 0x90] for "\ud884\udf50"', () => {
41
- expect(Array.from(Utf8.encode("\ud884\udf50"))).toEqual([
42
- 0xf0, 0xb1, 0x8d, 0x90
43
- ])
44
- })
45
- })
46
-
47
- describe("Utf8.decode", () => {
48
- it("returns an empty string for []", () => {
49
- expect(Effect.runSync(Utf8.decode([]))).toBe("")
50
- })
51
-
52
- it('returns "hello world" for [104, 101, 108, ...]', () => {
53
- expect(
54
- Effect.runSync(
55
- Utf8.decode([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100])
56
- )
57
- ).toBe("hello world")
58
- })
59
-
60
- it('returns "\ud884\udf50" for [0xf0, 0xb1, 0x8d, 0x90]', () => {
61
- expect(Effect.runSync(Utf8.decode([0xf0, 0xb1, 0x8d, 0x90]))).toBe(
62
- "\ud884\udf50"
63
- )
64
- })
65
-
66
- it("fails for [255, 255, 255, 255] (invalid utf-8 sequence)", () => {
67
- expect(() => Effect.runSync(Utf8.decode([255, 255, 255, 255]))).toThrow()
68
- })
69
- })