@exodus/bytes 1.0.0-rc.10 → 1.0.0-rc.12

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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Exodus Movement
3
+ Copyright (c) 2024-2025 Exodus Movement
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -64,8 +64,8 @@ If you don't need support for legacy multi-byte encodings, you can use the lite
64
64
  import { TextDecoder, TextEncoder } from '@exodus/bytes/encoding-lite.js'
65
65
  ```
66
66
 
67
- This reduces the bundle size 9x:\
68
- from 91 KiB gzipped for `@exodus/bytes/encoding.js` to 10 KiB gzipped for `@exodus/bytes/encoding-lite.js`.\
67
+ This reduces the bundle size 10x:\
68
+ from 90 KiB gzipped for `@exodus/bytes/encoding.js` to 9 KiB gzipped for `@exodus/bytes/encoding-lite.js`.\
69
69
  (For comparison, `text-encoding` module is 190 KiB gzipped, and `iconv-lite` is 194 KiB gzipped).
70
70
 
71
71
  It still supports `utf-8`, `utf-16le`, `utf-16be` and all single-byte encodings specified by the spec,
@@ -117,6 +117,11 @@ There is no loose variant for this encoding, all bytes can be decoded.
117
117
 
118
118
  Same as `windows1252toString = createSinglebyteDecoder('windows-1252')`.
119
119
 
120
+ ### `@exodus/bytes/bigint.js`
121
+
122
+ ##### `fromBigInt(bigint, { length, format = 'uint8' })`
123
+ ##### `toBigInt(arr)`
124
+
120
125
  ### `@exodus/bytes/hex.js`
121
126
 
122
127
  ##### `toHex(arr)`
@@ -150,6 +155,9 @@ Same as `windows1252toString = createSinglebyteDecoder('windows-1252')`.
150
155
  ##### `toBase58(arr)`
151
156
  ##### `fromBase58(str, format = 'uint8')`
152
157
 
158
+ ##### `toBase58xrp(arr)`
159
+ ##### `fromBase58xrp(str, format = 'uint8')`
160
+
153
161
  ### `@exodus/bytes/base58check.js`
154
162
 
155
163
  ##### `async toBase58check(arr)`
package/base58.js CHANGED
@@ -3,10 +3,10 @@ import { assertUint8 } from './assert.js'
3
3
  import { nativeDecoder, nativeEncoder, isHermes } from './fallback/_utils.js'
4
4
  import { encodeAscii, decodeAscii } from './fallback/latin1.js'
5
5
 
6
- const alphabet = [...'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz']
7
- const codes = new Uint8Array(alphabet.map((x) => x.charCodeAt(0)))
8
- const ZERO = alphabet[0]
9
- const zeroC = codes[0]
6
+ const alphabet58 = [...'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz']
7
+ const alphabetXRP = [...'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz']
8
+ const codes58 = new Uint8Array(alphabet58.map((x) => x.charCodeAt(0)))
9
+ const codesXRP = new Uint8Array(alphabetXRP.map((x) => x.charCodeAt(0)))
10
10
 
11
11
  const _0n = BigInt(0)
12
12
  const _1n = BigInt(1)
@@ -16,17 +16,18 @@ const _58n = BigInt(58)
16
16
  const _0xffffffffn = BigInt(0xff_ff_ff_ff)
17
17
 
18
18
  let table // 15 * 82, diagonal, <1kb
19
- let fromMap
19
+ const fromMaps = new Map()
20
20
 
21
21
  const E_CHAR = 'Invalid character in base58 input'
22
22
 
23
23
  const shouldUseBigIntFrom = isHermes // faster only on Hermes, numbers path beats it on normal engines
24
24
 
25
- export function toBase58(arr) {
25
+ function toBase58core(arr, alphabet, codes) {
26
26
  assertUint8(arr)
27
27
  const length = arr.length
28
28
  if (length === 0) return ''
29
29
 
30
+ const ZERO = alphabet[0]
30
31
  let zeros = 0
31
32
  while (zeros < length && arr[zeros] === 0) zeros++
32
33
 
@@ -120,18 +121,20 @@ export function toBase58(arr) {
120
121
  return ZERO.repeat(zeros) + out
121
122
  }
122
123
 
123
- // TODO: test on 'z'.repeat(from 1 to smth)
124
- export function fromBase58(str, format = 'uint8') {
124
+ function fromBase58core(str, alphabet, codes, format = 'uint8') {
125
125
  if (typeof str !== 'string') throw new TypeError('Input is not a string')
126
126
  const length = str.length
127
127
  if (length === 0) return typedView(new Uint8Array(), format)
128
128
 
129
+ const zeroC = codes[0]
129
130
  let zeros = 0
130
131
  while (zeros < length && str.charCodeAt(zeros) === zeroC) zeros++
131
132
 
133
+ let fromMap = fromMaps.get(alphabet)
132
134
  if (!fromMap) {
133
135
  fromMap = new Int8Array(256).fill(-1)
134
136
  for (let i = 0; i < 58; i++) fromMap[alphabet[i].charCodeAt(0)] = i
137
+ fromMaps.set(alphabet, fromMap)
135
138
  }
136
139
 
137
140
  const size = zeros + (((length - zeros + 1) * 3) >> 2) // 3/4 rounded up, larger than ~0.73 coef to fit everything
@@ -210,3 +213,8 @@ export function fromBase58(str, format = 'uint8') {
210
213
 
211
214
  return typedView(res.slice(at - zeros), format) // slice is faster for small sizes than subarray
212
215
  }
216
+
217
+ export const toBase58 = (arr) => toBase58core(arr, alphabet58, codes58)
218
+ export const fromBase58 = (str, format) => fromBase58core(str, alphabet58, codes58, format)
219
+ export const toBase58xrp = (arr) => toBase58core(arr, alphabetXRP, codesXRP)
220
+ export const fromBase58xrp = (str, format) => fromBase58core(str, alphabetXRP, codesXRP, format)
package/bigint.js ADDED
@@ -0,0 +1,14 @@
1
+ import { toHex, fromHex } from '@exodus/bytes/hex.js'
2
+ import { assert } from './fallback/_utils.js'
3
+
4
+ const _0n = BigInt(0)
5
+
6
+ export function fromBigInt(x, { length, format } = {}) {
7
+ assert(Number.isSafeInteger(length) && length > 0, 'Expected length arg to be a positive integer')
8
+ assert(typeof x === 'bigint' && x >= _0n, 'Expected a non-negative bigint')
9
+ const hex = x.toString(16)
10
+ assert(length * 2 >= hex.length, `Can not fit supplied number into ${length} bytes`)
11
+ return fromHex(hex.padStart(length * 2, '0'), format)
12
+ }
13
+
14
+ export const toBigInt = (a) => BigInt('0x' + (toHex(a) || '0'))
@@ -1,22 +1,30 @@
1
1
  const { Buffer, TextEncoder, TextDecoder } = globalThis
2
2
  const haveNativeBuffer = Buffer && !Buffer.TYPED_ARRAY_SUPPORT
3
- let isNative = (x) => x && (haveNativeBuffer || `${x}`.includes('[native code]')) // we consider Node.js TextDecoder/TextEncoder native
3
+ export const nativeBuffer = haveNativeBuffer ? Buffer : null
4
+ export const isHermes = Boolean(globalThis.HermesInternal)
5
+ export const isDeno = Boolean(globalThis.Deno)
6
+ export const isLE = new Uint8Array(Uint16Array.of(258).buffer)[0] === 2
7
+
8
+ let isNative = (x) => {
9
+ if (!x) return false
10
+ if (haveNativeBuffer) return true // we consider Node.js TextDecoder/TextEncoder native
11
+ const s = `${x}`
12
+ // See https://github.com/facebook/hermes/pull/1855#issuecomment-3659386410
13
+ return s.includes('[native code]') || s.includes(`[bytecode]`) // Static Hermes has [bytecode] for contrib, which includes TextEncoder/TextDecoder
14
+ }
15
+
4
16
  if (!haveNativeBuffer && isNative(() => {})) isNative = () => false // e.g. XS, we don't want false positives
5
17
 
6
18
  export const nativeEncoder = isNative(TextEncoder) ? new TextEncoder() : null
7
19
  export const nativeDecoder = isNative(TextDecoder)
8
20
  ? new TextDecoder('utf-8', { ignoreBOM: true })
9
21
  : null
10
- export const nativeBuffer = haveNativeBuffer ? Buffer : null
11
- export const isHermes = Boolean(globalThis.HermesInternal)
12
- export const isDeno = Boolean(globalThis.Deno)
13
- export const isLE = new Uint8Array(Uint16Array.of(258).buffer)[0] === 2
14
22
 
15
23
  // Actually windows-1252, compatible with ascii and latin1 decoding
16
24
  // Beware that on non-latin1, i.e. on windows-1252, this is broken in ~all Node.js versions released
17
25
  // in 2025 due to a regression, so we call it Latin1 as it's usable only for that
18
26
  let nativeDecoderLatin1impl = null
19
- if (isNative(TextDecoder)) {
27
+ if (nativeDecoder) {
20
28
  // Not all barebone engines with TextDecoder support something except utf-8, detect
21
29
  try {
22
30
  nativeDecoderLatin1impl = new TextDecoder('latin1', { ignoreBOM: true })
@@ -116,3 +124,7 @@ export function decode2string(arr, start, end, m) {
116
124
 
117
125
  return decodePart(arr, start, end, m)
118
126
  }
127
+
128
+ export function assert(condition, msg) {
129
+ if (!condition) throw new Error(msg)
130
+ }
@@ -30,7 +30,7 @@ export function normalizeEncoding(label) {
30
30
  if (label === 'utf-8' || label === 'utf8' || label === 'UTF-8' || label === 'UTF8') return 'utf-8'
31
31
  if (label === 'windows-1252' || label === 'ascii' || label === 'latin1') return 'windows-1252'
32
32
  // full map
33
- if (!/^[\w\t\n\f\r .:-]+$/i.test(label)) throw new RangeError(E_ENCODING) // must be ASCII (with ASCII whitespace)
33
+ if (!/^[\w\t\n\f\r .:-]+$/i.test(label)) return null // must be ASCII (with ASCII whitespace)
34
34
  const low = `${label}`.trim().toLowerCase()
35
35
  if (Object.hasOwn(labels, low)) return low
36
36
  if (!labelsMap) {
@@ -42,7 +42,7 @@ export function normalizeEncoding(label) {
42
42
 
43
43
  const mapped = labelsMap.get(low)
44
44
  if (mapped) return mapped
45
- throw new RangeError(E_ENCODING)
45
+ return null
46
46
  }
47
47
 
48
48
  const define = (obj, key, value) => Object.defineProperty(obj, key, { value, writable: false })
@@ -51,10 +51,7 @@ const fromSource = (x) => {
51
51
  if (x instanceof Uint8Array) return x
52
52
  if (x instanceof ArrayBuffer) return new Uint8Array(x)
53
53
  if (ArrayBuffer.isView(x)) return new Uint8Array(x.buffer, x.byteOffset, x.byteLength)
54
- if (globalThis.SharedArrayBuffer && x instanceof globalThis.SharedArrayBuffer) {
55
- return new Uint8Array(x.buffer, x.byteOffset, x.byteLength)
56
- }
57
-
54
+ if (globalThis.SharedArrayBuffer && x instanceof SharedArrayBuffer) return new Uint8Array(x)
58
55
  throw new TypeError('Argument must be a SharedArrayBuffer, ArrayBuffer or ArrayBufferView')
59
56
  }
60
57
 
@@ -74,7 +71,7 @@ export class TextDecoder {
74
71
  constructor(encoding = 'utf-8', options = {}) {
75
72
  if (typeof options !== 'object') throw new TypeError(E_OPTIONS)
76
73
  const enc = normalizeEncoding(encoding)
77
- if (enc === 'replacement') throw new RangeError(E_ENCODING)
74
+ if (!enc || enc === 'replacement') throw new RangeError(E_ENCODING)
78
75
  define(this, 'encoding', enc)
79
76
  define(this, 'fatal', Boolean(options.fatal))
80
77
  define(this, 'ignoreBOM', Boolean(options.ignoreBOM))
@@ -260,20 +257,34 @@ export function getBOMEncoding(input) {
260
257
  // Warning: encoding sniffed from BOM takes preference over the supplied one
261
258
  // Warning: lossy, performs replacement, no option of throwing
262
259
  // Expects normalized (lower-case) encoding as input. Completely ignores it and even skips validation when BOM is found
260
+ // Unlike TextDecoder public API, additionally supports 'replacement' encoding
263
261
  export function legacyHookDecode(input, fallbackEncoding) {
264
262
  let u8 = fromSource(input)
265
263
  const bomEncoding = getBOMEncoding(u8)
266
264
  if (bomEncoding) u8 = u8.subarray(bomEncoding === 'utf-8' ? 3 : 2)
267
265
  const enc = bomEncoding ?? fallbackEncoding ?? 'utf-8' // "the byte order mark is more authoritative than anything else"
266
+
268
267
  if (enc === 'utf-8') return utf8toStringLoose(u8)
269
- if (enc === 'utf-16le') return utf16toStringLoose(u8, 'uint8-le')
270
- if (enc === 'utf-16be') return utf16toStringLoose(u8, 'uint8-be')
271
- if (!Object.hasOwn(labels, enc) || enc === 'replacement') throw new RangeError(E_ENCODING)
268
+ if (enc === 'utf-16le' || enc === 'utf-16be') {
269
+ let suffix = ''
270
+ if (u8.byteLength % 2 !== 0) {
271
+ suffix = replacementChar
272
+ u8 = u8.subarray(0, -1)
273
+ }
274
+
275
+ return utf16toStringLoose(u8, enc === 'utf-16le' ? 'uint8-le' : 'uint8-be') + suffix
276
+ }
277
+
278
+ if (!Object.hasOwn(labels, enc)) throw new RangeError(E_ENCODING)
272
279
 
273
280
  if (multibyteSet.has(enc)) {
274
281
  if (!createMultibyteDecoder) throw new Error(E_MULTI)
275
282
  return createMultibyteDecoder(enc, true)(u8)
276
283
  }
277
284
 
285
+ // https://encoding.spec.whatwg.org/#replacement-decoder
286
+ // On non-streaming non-fatal case, it just replaces any non-empty input with a single replacement char
287
+ if (enc === 'replacement') return input.byteLength > 0 ? replacementChar : ''
288
+
278
289
  return createSinglebyteDecoder(enc, true)(u8)
279
290
  }
@@ -1,45 +1,60 @@
1
1
  // See tests/fixtures/encodings/single-byte/dump.js for generator
2
2
 
3
- const c =
4
- '\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0'
5
- const k8a = '─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥\xA0⌡°²·÷═║╒ё'
6
- const k8b = '©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ'
7
- const i2 = 'żŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙'
8
- const ch = 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
9
- const cl1 = 'абвгдежзийклмнопрстуфхцчшщъыьэю'
10
- const i8 = 'אבגדהוזחטיךכלםמןנסעףפץצקרשת'
11
- const p = '€\x81‚ƒ„…†‡'
12
- const s = 'µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž'
13
- const f = (n) => '\uFFFD'.repeat(n)
3
+ const e = (x) => new Array(x).fill(1)
4
+ const z = (x) => new Array(x).fill(0)
5
+
6
+ /* eslint-disable unicorn/numeric-separators-style, @exodus/export-default/named */
7
+
8
+ // Common ranges
9
+
10
+ // prettier-ignore
11
+ const k8a = [9472,2,10,4,4,4,4,8,8,8,8,68,4,4,4,4,1,1,1,-627,640,-903,1,46,28,1,-8645,8833,-8817,2,5,64,9305,1,1,-8449]
12
+ // prettier-ignore
13
+ const k8b = [-30,1,21,-18,1,15,-17,18,-13,...e(7),16,-15,1,1,1,-13,-4,26,-1,-20,17,5,-4,-2,3]
14
+ const p1 = [8364, -8235, 8089, -7816, 7820, 8, -6, 1]
15
+ const p2 = [-99, 12, 20, -12, 17, 37, -29, 2]
16
+ // prettier-ignore
17
+ const p3 = [1,1,65,-63,158,-156,1,1,1,40,30,42,-46,6,-66,1,83,-6,-6,-67,176,...p2,-114,121,-119,1,1,155,-49,25,16,-142,159,2,-158,38,42,-46,6,-35,1,52,-6,-6,-36,145,...p2,-83,90,-88,1,1,124,-49,25,16,-111,128,2]
18
+ const i0 = [128, ...e(32)]
19
+ // prettier-ignore
20
+ const i2 = [-40,-147,1,64,-62,117,-51,-63,69,-67,79,-77,79,-77,1,64,2,51,4,-116,1,124,-122,1,129,22,-148,150,-148,1,133,-131,118,-116,1,33,-31,86,-51,-32,38,-36,48,-46,48,-46,1,33,2,51,4,-85,1,93,-91,1,98,22,-117,119,-117,1,102,374]
21
+ const i4a = [-75, -63, ...e(5), 104, -34, -67, 79, -77, 75, -73, 1]
22
+ const i4b = [34, -32, ...e(5), 73, -34, -36, 48, -46, 44, -42, 1]
23
+ const i7 = [721, 1, 1, -719, 721, -719, 721, ...e(19), 64604, -64602, ...e(43), 64559]
24
+ const i8 = [...e(26), 64019, 0, -57327, 1, 57326]
25
+ const w0 = [8364, -8235, 8089, -8087, 8091, 8, -6, 1, -8089, 8104]
26
+ const w8 = [8072, 1, 3, 1, 5, -15, 1]
27
+ const w1 = [...w8, -7480, 7750, -8129, 7897, -7911, -182]
28
+ const w3 = [...w8, -8060, 8330, -8328, 8096, -8094]
29
+ const m0 = [8558, -8328, 8374, -66, -8539, 16, 8043, -8070]
14
30
 
15
- /* eslint-disable @exodus/export-default/named */
16
31
  // prettier-ignore
17
32
  export default {
18
- ibm866: ch + "абвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■\xA0",
19
- "iso-8859-10": c + "ĄĒĢĪĨͧĻĐŠŦŽ\xADŪŊ°ąēģīĩķ·ļđšŧž―ūŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞßāáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ",
20
- "iso-8859-13": c + "”¢£¤„¦§Ø©Ŗ«¬\xAD®Æ°±²³“" + s + "’",
21
- "iso-8859-14": c + "Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ\xAD®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶßàáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷ",
22
- "iso-8859-15": c + "¡¢£€¥Š§š©ª«¬\xAD®¯°±²³Žµ¶·ž¹º»ŒœŸ",
23
- "iso-8859-16": c + "ĄąŁ€„Чš©Ș«Ź\xADźŻ°±ČłŽ”¶·žčș»ŒœŸżÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚßàáâăäćæçèéêëìíîïđńòóôőöśűùúûüęț",
24
- "iso-8859-2": c + "Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xADŽŻ°ą˛ł´ľśˇ¸šşťź˝ž" + i2,
25
- "iso-8859-3": c + "Ħ˘£¤\uFFFDĤ§¨İŞĞĴ\xAD\uFFFDݰħ²³´µĥ·¸ışğĵ½\uFFFDżÀÁÂ\uFFFDÄĊĈÇÈÉÊËÌÍÎÏ\uFFFDÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ\uFFFDäċĉçèéêëìíîï\uFFFDñòóôġö÷ĝùúûüŭŝ˙",
26
- "iso-8859-4": c + "ĄĸŖ¤Ĩϧ¨ŠĒĢŦ\xADޝ°ą˛ŗ´ĩšēģŧŊžŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖרŲÚÛÜŨŪßāáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙",
27
- "iso-8859-5": c + "ЁЂЃЄЅІЇЈЉЊЋЌ\xADЎЏ" + ch + cl1 + "я№ёђѓєѕіїјљњћќ§ўџ",
28
- "iso-8859-6": c + f(3) + "¤" + f(7) + "،\xAD" + f(13) + "؛" + f(3) + "؟\uFFFDءآأؤإئابةتثجحخدذرزسشصضطظعغ" + f(5) + "ـفقكلمنهوىي\u064B\u064C\u064D\u064E\u064F\u0650\u0651\u0652" + f(13),
29
- "iso-8859-7": c + "‘’£€₯¦§¨©ͺ«¬\xAD\uFFFD―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ\uFFFDΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ\uFFFD",
30
- "iso-8859-8": c + "\uFFFD¢£¤¥¦§¨©×«¬\xAD®¯°±²³´µ¶·¸¹÷»¼½¾" + f(32) + "‗" + i8 + f(2) + "\u200E\u200F\uFFFD",
31
- "koi8-r": k8a + "╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬" + k8b,
32
- "koi8-u": k8a + "є╔ії╗╘╙╚╛ґў╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪ҐЎ" + k8b,
33
- macintosh: "ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»…\xA0ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ\uF8FFÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ",
34
- "windows-1250": "€\x81‚\x83„…†‡\x88‰Š‹ŚŤŽŹ\x90‘’“”•–—\x98™š›śťžź\xA0ˇ˘Ł¤Ą¦§¨©Ş«¬\xAD®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľ" + i2,
35
- "windows-1251": "ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—\x98™љ›њќћџ\xA0ЎўЈ¤Ґ¦§Ё©Є«¬\xAD®Ї°±Ііґµ¶·ё№є»јЅѕї" + ch + cl1 + 'я',
36
- "windows-1252": p + "ˆ‰Š‹Œ\x8DŽ\x8F\x90‘’“”•–—˜™š›œ\x9DžŸ",
37
- "windows-1253": p + "\x88‰\x8A‹\x8C\x8D\x8E\x8F\x90‘’“”•–—\x98™\x9A›\x9C\x9D\x9E\x9F\xA0΅Ά£¤¥¦§¨©\uFFFD«¬\xAD®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ\uFFFDΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ\uFFFD",
38
- "windows-1254": p + "ˆ‰Š‹Œ\x8D\x8E\x8F\x90‘’“”•–—˜™š›œ\x9D\x9EŸ\xA0¡¢£¤¥¦§¨©ª«¬\xAD®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖרÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüış",
39
- "windows-1255": p + "ˆ‰\x8A‹\x8C\x8D\x8E\x8F\x90‘’“”•–—˜™\x9A›\x9C\x9D\x9E\x9F\xA0¡¢£₪¥¦§¨©×«¬\xAD®¯°±²³´µ¶·¸¹÷»¼½¾¿\u05B0\u05B1\u05B2\u05B3\u05B4\u05B5\u05B6\u05B7\u05B8\u05B9\u05BA\u05BB\u05BC\u05BD־\u05BF׀\u05C1\u05C2׃װױײ׳״" + f(7) + i8 + f(2) + "\u200E\u200F\uFFFD",
40
- "windows-1256": "€پ‚ƒ„…†‡ˆ‰ٹ‹Œچژڈگ‘’“”•–—ک™ڑ›œ\u200C\u200Dں\xA0،¢£¤¥¦§¨©ھ«¬\xAD®¯°±²³´µ¶·¸¹؛»¼½¾؟ہءآأؤإئابةتثجحخدذرزسشصض×طظعغـفقكàلâمنهوçèéêëىيîï\u064B\u064C\u064D\u064Eô\u064F\u0650÷\u0651ù\u0652ûü\u200E\u200Fے",
41
- "windows-1257": "€\x81‚\x83„…†‡\x88‰\x8A‹\x8C¨ˇ¸\x90‘’“”•–—\x98™\x9A›\x9C¯˛\x9F\xA0\uFFFD¢£¤\uFFFD¦§Ø©Ŗ«¬\xAD®Æ°±²³´" + s + "˙",
42
- "windows-1258": p + "ˆ‰\x8A‹Œ\x8D\x8E\x8F\x90‘’“”•–—˜™\x9A›œ\x9D\x9EŸ\xA0¡¢£¤¥¦§¨©ª«¬\xAD®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË\u0300ÍÎÏĐÑ\u0309ÓÔƠÖרÙÚÛÜƯ\u0303ßàáâăäåæçèéêë\u0301íîïđñ\u0323óôơö÷øùúûüư₫",
43
- "windows-874": "€\x81\x82\x83\x84…\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90‘’“”•–—\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะ\u0E31าำ\u0E34\u0E35\u0E36\u0E37\u0E38\u0E39\u0E3A" + f(4) + "฿เแโใไๅๆ\u0E47\u0E48\u0E49\u0E4A\u0E4B\u0E4C\u0E4D\u0E4E๏๐๑๒๓๔๕๖๗๘๙๚๛" + f(4),
44
- "x-mac-cyrillic": ch + "†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»…\xA0ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёя" + cl1 + "€"
33
+ ibm866: [1040,...e(47),8530,1,1,-145,34,61,1,-12,-1,14,-18,6,6,-1,-1,-75,4,32,-8,-16,-28,60,34,1,-5,-6,21,-3,-6,-16,28,-5,1,-4,1,-12,-1,-6,1,24,-1,-82,-12,124,-4,8,4,-16,-8512,...e(15),-78,80,-77,80,-77,80,-73,80,-942,8553,-8546,8547,-260,-8306,9468,-9472],
34
+ 'iso-8859-10': [...i0,100,14,16,8,-2,14,-143,148,-43,80,6,23,-208,189,-32,-154,85,14,16,8,-2,14,-128,133,-43,80,6,23,7831,-7850,-32,...i4a,1,1,117,7,-121,1,1,1,146,-144,154,-152,...e(5),...i4b,1,1,86,7,-90,1,1,1,115,-113,123,-121,1,1,1,1,58],
35
+ 'iso-8859-13': [...i0,8061,-8059,1,1,8058,-8056,1,49,-47,173,-171,1,1,1,24,-22,1,1,1,8041,-8039,...p3,7835],
36
+ 'iso-8859-14': [...i0,7522,1,-7520,103,1,7423,-7523,7641,-7639,7641,-119,231,-7749,1,202,7334,1,-7423,1,7455,1,-7563,7584,43,-42,44,-35,147,-111,1,-36,-7585,...e(15),165,-163,...e(5),7572,-7570,...e(5),153,-151,...e(16),134,-132,...e(5),7541,-7539,...e(5),122],
37
+ 'iso-8859-15': [...i0,1,1,1,8201,-8199,187,-185,186,-184,...e(10),202,-200,1,1,199,-197,1,1,151,1,37],
38
+ 'iso-8859-16': [...i0,100,1,60,8043,-142,-7870,-185,186,-184,367,-365,206,-204,205,1,-203,1,91,54,59,7840,-8039,1,199,-113,268,-350,151,1,37,4,-188,1,1,64,-62,66,-64,...e(9),65,51,-113,1,1,124,-122,132,22,-151,1,1,1,60,258,-315,1,1,1,33,-31,35,-33,...e(9),34,51,-82,1,1,93,-91,101,22,-120,1,1,1,29,258],
39
+ 'iso-8859-2': [...i0,100,468,-407,-157,153,29,-179,1,184,-2,6,21,-204,208,-2,-203,85,470,-409,-142,138,29,364,-527,169,-2,6,21,355,-351,-2,...i2],
40
+ 'iso-8859-3': [...i0,134,434,-565,1,65369,-65241,-125,1,136,46,-64,22,-135,65360,-65154,-203,119,-117,1,1,1,112,-110,1,121,46,-64,22,-120,65344,-65153,-188,1,1,65339,-65337,70,-2,-65,...e(8),65326,-65324,1,1,1,76,-74,1,69,-67,1,1,1,144,-16,-125,1,1,1,65307,-65305,39,-2,-34,...e(8),65294,-65292,1,1,1,45,-43,1,38,-36,1,1,1,113,-16,380],
41
+ 'iso-8859-4': [...i0,100,52,30,-178,132,19,-148,1,184,-78,16,68,-185,208,-206,1,85,470,-388,-163,117,19,395,-527,169,-78,16,68,-29,52,-51,...i4a,92,-26,53,7,-22,-98,1,1,1,1,154,-152,1,1,140,2,-139,...i4b,61,-26,53,7,-22,-67,1,1,1,1,123,-121,1,1,109,2,366],
42
+ 'iso-8859-5': [...i0,865,...e(11),-863,865,...e(65),7367,-7365,...e(11),-949,951,1],
43
+ 'iso-8859-6': [...i0,65373,0,0,-65369,65369,...z(6),-63985,-1375,65360,...z(12),-63970,63970,0,0,-63966,63966,-63964,...e(25),63939,0,0,0,0,-63933,...e(18),63915,...z(12)],
44
+ 'iso-8859-7': [...i0,8056,1,-8054,8201,3,-8201,1,1,1,721,-719,1,1,65360,-57320,-8037,1,1,1,721,1,1,-719,...i7],
45
+ 'iso-8859-8': [...i0,65373,-65371,...e(7),46,-44,...e(14),62,-60,1,1,1,65343,...z(31),-57318,-6727,...i8],
46
+ 'koi8-r': [...k8a,8450,...e(14),-8544,8545,...e(10),-9411,933,...k8b,-28,...k8b],
47
+ 'koi8-u': [...k8a,3,8448,-8446,1,8448,1,1,1,1,-8394,-51,8448,1,1,1,-8544,3,8543,-8541,1,8543,1,1,1,1,-8410,-130,-869,933,...k8b,-28,...k8b],
48
+ macintosh: [196,1,2,2,8,5,6,5,-1,2,2,-1,2,2,2,-1,2,1,2,-1,2,1,2,2,-1,2,2,-1,5,-1,2,1,7972,-8048,-14,1,4,8059,-8044,41,-49,-5,8313,-8302,-12,8632,-8602,18,8518,-8557,8627,1,-8640,16,8525,15,-2,-7759,7787,-8577,16,751,-707,18,-57,-30,11,...m0,32,3,18,125,1,7872,1,8,1,-5,1,-7970,9427,-9419,121,7884,104,-115,1,56007,1,-56033,-8042,8035,4,18,-8046,8,-9,10,-3,5,1,1,-3,7,1,63531,-63533,8,1,-2,88,405,22,-557,553,1,1,-546,549,-2,-20],
49
+ 'windows-1250': [...w0,-7888,7897,-7903,10,25,-4,-233,...w8,-8060,8330,-8129,7897,-7903,10,25,-4,-218,551,17,-407,-157,96,-94,1,1,1,181,-179,1,1,1,205,-203,1,554,-409,-142,1,1,1,1,77,90,-164,130,416,-415,62,...i2],
50
+ 'windows-1251': [1026,1,7191,-7111,7115,8,-6,1,139,-124,-7207,7216,-7215,2,-1,4,67,7110,1,3,1,5,-15,1,-8060,8330,-7369,7137,-7136,2,-1,4,-959,878,80,-86,-868,1004,-1002,1,858,-856,859,-857,1,1,1,857,-855,1,853,80,59,-988,1,1,922,7365,-7362,-921,925,-83,80,2,-71,...e(63)],
51
+ 'windows-1252': [...p1,-7515,7530,-7888,7897,-7911,-197,240,-238,1,...w1,225,-6],
52
+ 'windows-1253': [...p1,-8089,8104,-8102,8111,-8109,1,1,1,1,...w3,1,1,1,1,741,1,-739,1,1,1,1,1,1,65364,-65362,1,1,1,8039,-8037,1,1,1,721,-719,1,1,...i7],
53
+ 'windows-1254': [...p1,-7515,7530,-7888,7897,-7911,-197,1,1,1,...w1,1,218,-216,...e(47),79,-77,...e(11),84,46,-127,...e(16),48,-46,...e(11),53,46],
54
+ 'windows-1255': [...p1,-7515,7530,-8102,8111,-8109,1,1,1,1,...w8,-7480,7750,-8328,8096,-8094,...e(7),8199,-8197,1,1,1,1,46,-44,...e(14),62,-60,1,1,1,1,1265,...e(19),45,1,1,1,1,64009,...z(6),-64045,...i8],
55
+ 'windows-1256': [8364,-6702,6556,-7816,7820,8,-6,1,-7515,7530,-6583,6592,-7911,1332,18,-16,39,6505,1,3,1,5,-15,1,-6507,6777,-6801,6569,-7911,7865,1,-6483,-1562,1388,-1386,...e(7),1557,-1555,...e(14),1378,-1376,1,1,1,1377,162,-160,...e(21),-1375,1376,1,1,1,6,1,1,1,-1379,1380,-1378,1379,1,1,1,-1377,1,1,1,1,1374,1,-1372,1,1372,1,1,1,-1370,1371,1,-1369,1370,-1368,1369,-1367,1,7954,1,-6461],
56
+ 'windows-1257': [...w0,-8102,8111,-8109,28,543,-527,-40,...w3,19,556,-572,1,65373,-65371,1,1,65369,-65367,1,49,-47,173,-171,1,1,1,24,-22,...e(5),...p3,347],
57
+ 'windows-1258': [...p1,-7515,7530,-8102,8111,-7911,-197,1,1,1,...w8,-7480,7750,-8328,8096,-7911,-182,1,218,-216,...e(34),64,-62,...e(7),565,-563,1,1,65,-63,568,-566,1,204,-202,1,1,1,1,1,1,211,340,-548,1,1,1,33,-31,...e(7),534,-532,1,1,34,-32,562,-560,1,173,-171,1,1,1,1,1,1,180,7931],
58
+ 'windows-874': [8364,-8235,1,1,1,8098,-8096,...e(10),...w8,-8060,...e(8),3425,...e(57),61891,0,0,0,-61886,...e(28),61858,0,0,0],
59
+ 'x-mac-cyrillic': [1040,...e(31),7153,-8048,992,-1005,4,8059,-8044,848,-856,-5,8313,-7456,80,7694,-7773,80,7627,-8557,8627,1,-7695,-929,988,-137,-4,80,-77,80,-78,80,-79,80,-2,-83,-857,...m0,875,80,-79,80,-7,7102,1,8,1,-5,1,-7970,7975,-7184,80,-79,80,7351,-7445,80,-2,-31,...e(30),7262]
45
60
  }
@@ -13,10 +13,11 @@ export const assertEncoding = (encoding) => {
13
13
  function getEncoding(encoding) {
14
14
  assertEncoding(encoding)
15
15
  if (encoding === xUserDefined) {
16
- return Array.from({ length: 128 }, (_, i) => String.fromCharCode(0xf7_80 + i)).join('')
16
+ return Array.from({ length: 128 }, (_, i) => 0xf7_80 + i)
17
17
  }
18
18
 
19
- return encodings[encoding]
19
+ let prev = 0
20
+ return encodings[encoding].map((x) => (prev += x)) // eslint-disable-line no-return-assign
20
21
  }
21
22
 
22
23
  const mappers = new Map()
@@ -28,13 +29,13 @@ export function encodingMapper(encoding) {
28
29
  const cached = mappers.get(encoding)
29
30
  if (cached) return cached
30
31
 
31
- const incomplete = getEncoding(encoding).includes('\uFFFD')
32
+ const codes = getEncoding(encoding)
33
+ const incomplete = codes.includes(0xff_fd)
32
34
  let map
33
35
  const mapper = (arr, start = 0) => {
34
36
  if (!map) {
35
37
  map = Uint16Array.from({ length: 256 }, (_, i) => i) // Unicode subset
36
- const strings = getEncoding(encoding).split('')
37
- map.set(Uint16Array.from(strings.map((x) => x.charCodeAt(0))), 128)
38
+ map.set(Uint16Array.from(codes), 128)
38
39
  }
39
40
 
40
41
  const o = Uint16Array.from(start === 0 ? arr : arr.subarray(start)) // copy to modify in-place, also those are 16-bit now
@@ -63,12 +64,13 @@ export function encodingDecoder(encoding) {
63
64
  if (cached) return cached
64
65
 
65
66
  let strings
66
- const incomplete = getEncoding(encoding).includes('\uFFFD')
67
+ const codes = getEncoding(encoding)
68
+ const incomplete = codes.includes(0xff_fd)
67
69
  const decoder = (arr, loose = false) => {
68
70
  if (!strings) {
69
- const part = getEncoding(encoding).split('')
70
- strings = Array.from({ length: 128 }, (_, i) => String.fromCharCode(i)).concat(part)
71
- while (strings.length < 256) strings.push(String.fromCharCode(strings.length))
71
+ const allCodes = Array.from({ length: 128 }, (_, i) => i).concat(codes)
72
+ while (allCodes.length < 256) allCodes.push(allCodes.length)
73
+ strings = allCodes.map((c) => String.fromCharCode(c))
72
74
  }
73
75
 
74
76
  const prefix = decodeLatin1(arr, 0, asciiPrefix(arr))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bytes",
3
- "version": "1.0.0-rc.10",
3
+ "version": "1.0.0-rc.12",
4
4
  "description": "Various operations on Uint8Array data",
5
5
  "scripts": {
6
6
  "lint": "eslint .",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "homepage": "https://github.com/ExodusOSS/bytes#readme",
41
41
  "engines": {
42
- "node": "^20.19.0 || >=22.13.0"
42
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
43
43
  },
44
44
  "type": "module",
45
45
  "files": [
@@ -66,6 +66,7 @@
66
66
  "/base58check.js",
67
67
  "/base64.js",
68
68
  "/bech32.js",
69
+ "/bigint.js",
69
70
  "/encoding.js",
70
71
  "/encoding-lite.js",
71
72
  "/hex.js",
@@ -87,6 +88,7 @@
87
88
  "./base58check.js": "./base58check.js",
88
89
  "./base64.js": "./base64.js",
89
90
  "./bech32.js": "./bech32.js",
91
+ "./bigint.js": "./bigint.js",
90
92
  "./hex.js": {
91
93
  "node": "./hex.node.js",
92
94
  "default": "./hex.js"
@@ -129,9 +131,10 @@
129
131
  "@scure/base": "^1.2.6",
130
132
  "@stablelib/base64": "^2.0.1",
131
133
  "@stablelib/hex": "^2.0.1",
132
- "@types/node": "^22.13.0",
134
+ "@types/node": "^22.12.0",
133
135
  "base-x": "^5.0.1",
134
136
  "base32.js": "^0.1.0",
137
+ "base58-js": "^3.0.3",
135
138
  "base64-js": "^1.5.1",
136
139
  "bech32": "^2.0.0",
137
140
  "bs58": "^6.0.0",
@@ -25,7 +25,7 @@ function latin1Prefix(arr, start) {
25
25
 
26
26
  export function createSinglebyteDecoder(encoding, loose = false) {
27
27
  if (encoding === 'iso-8859-8-i') encoding = 'iso-8859-8'
28
- const latin1path = encoding === 'windows-1252' // TODO: are there more?
28
+ const latin1path = encoding === 'windows-1252'
29
29
  if (isDeno) {
30
30
  const jsDecoder = encodingDecoder(encoding) // asserts
31
31
  return (arr) => {