@exodus/bytes 1.0.0-rc.5 → 1.0.0-rc.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/bytes",
3
- "version": "1.0.0-rc.5",
3
+ "version": "1.0.0-rc.6",
4
4
  "description": "Various operations on Uint8Array data",
5
5
  "scripts": {
6
6
  "lint": "eslint .",
@@ -39,6 +39,7 @@
39
39
  "type": "module",
40
40
  "files": [
41
41
  "/fallback/_utils.js",
42
+ "/fallback/latin1.js",
42
43
  "/fallback/base32.js",
43
44
  "/fallback/base64.js",
44
45
  "/fallback/hex.js",
@@ -74,12 +75,12 @@
74
75
  "@exodus/crypto": "1.0.0-rc.29",
75
76
  "@exodus/eslint-config": "^5.24.0",
76
77
  "@exodus/prettier": "^1.0.0",
77
- "@exodus/test": "^1.0.0-rc.107",
78
+ "@exodus/test": "^1.0.0-rc.108",
78
79
  "@noble/hashes": "^2.0.1",
79
80
  "@scure/base": "^1.2.6",
80
81
  "@stablelib/base64": "^2.0.1",
81
82
  "@stablelib/hex": "^2.0.1",
82
- "@types/node": "^24.0.10",
83
+ "@types/node": "^22.13.0",
83
84
  "base-x": "^5.0.1",
84
85
  "base32.js": "^0.1.0",
85
86
  "base64-js": "^1.5.1",
@@ -91,9 +92,11 @@
91
92
  "eslint": "^8.44.0",
92
93
  "fast-base64-decode": "^2.0.0",
93
94
  "fast-base64-encode": "^1.0.0",
95
+ "hextreme": "^1.0.7",
94
96
  "hi-base32": "^0.5.1",
95
97
  "jsvu": "^3.0.0",
96
- "text-encoding": "^0.7.0"
98
+ "text-encoding": "^0.7.0",
99
+ "typescript": "^5.9.3"
97
100
  },
98
101
  "prettier": "@exodus/prettier",
99
102
  "packageManager": "pnpm@10.12.1+sha256.889bac470ec93ccc3764488a19d6ba8f9c648ad5e50a9a6e4be3768a5de387a3"
package/utf8.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { assertUint8 } from './assert.js'
2
2
  import { typedView } from './array.js'
3
3
  import * as js from './fallback/utf8.js'
4
+ import { asciiPrefix, decodeLatin1 } from './fallback/latin1.js'
4
5
 
5
6
  const { Buffer, TextEncoder, TextDecoder, decodeURIComponent, escape } = globalThis // Buffer is optional
6
7
  const haveNativeBuffer = Buffer && !Buffer.TYPED_ARRAY_SUPPORT
@@ -18,7 +19,7 @@ const { E_STRICT, E_STRICT_UNICODE } = js
18
19
  const shouldUseEscapePath = Boolean(globalThis.HermesInternal) // faster only on Hermes, js path beats it on normal engines
19
20
 
20
21
  function deLoose(str, loose, res) {
21
- if (loose) return res
22
+ if (loose || str.length === res.length) return res // length is equal only for ascii, which is automatically fine
22
23
  if (isWellFormed) {
23
24
  // We have a fast native method
24
25
  if (isWellFormed.call(str)) return res
@@ -51,64 +52,27 @@ function encode(str, loose = false) {
51
52
  return js.encode(str, loose)
52
53
  }
53
54
 
54
- let escapes
55
-
56
- function toEscapesPart(arr, start, end) {
57
- let o = ''
58
- let i = start
59
- const last3 = end - 3
60
- // Unrolled loop is faster
61
- while (i < last3) {
62
- const a = arr[i++]
63
- const b = arr[i++]
64
- const c = arr[i++]
65
- const d = arr[i++]
66
- o += escapes[a]
67
- o += escapes[b]
68
- o += escapes[c]
69
- o += escapes[d]
70
- }
71
-
72
- while (i < end) o += escapes[arr[i++]]
73
- return o
74
- }
75
-
76
55
  function decode(arr, loose = false) {
77
56
  assertUint8(arr)
78
57
  if (haveDecoder) return loose ? decoderLoose.decode(arr) : decoderFatal.decode(arr) // Node.js and browsers
79
58
  // No reason to use native Buffer: it's not faster than TextDecoder, needs rechecks in non-loose mode, and Node.js has TextDecoder
80
59
 
81
- // This codepath gives a ~2x perf boost on Hermes
82
- if (shouldUseEscapePath && escape && decodeURIComponent) {
83
- if (!escapes) escapes = Array.from({ length: 256 }, (_, i) => escape(String.fromCharCode(i)))
84
- const length = arr.length
85
- let o
86
- if (length > 30_000) {
87
- // Limit concatenation to avoid excessive GC
88
- // TODO: recheck thresholds on Hermes (taken from hex)
89
- const concat = []
90
- for (let i = 0; i < length; ) {
91
- const step = i + 500
92
- const end = step > length ? length : step
93
- concat.push(toEscapesPart(arr, i, end))
94
- i = end
95
- }
96
-
97
- o = concat.join('')
98
- concat.length = 0
99
- } else {
100
- o = toEscapesPart(arr, 0, length)
101
- }
60
+ // Fast path for ASCII prefix, this is faster than all alternatives below
61
+ const prefix = decodeLatin1(arr, 0, asciiPrefix(arr))
62
+ if (prefix.length === arr.length) return prefix
102
63
 
64
+ // This codepath gives a ~3x perf boost on Hermes
65
+ if (shouldUseEscapePath && escape && decodeURIComponent) {
66
+ const o = escape(decodeLatin1(arr, prefix.length, arr.length))
103
67
  try {
104
- return decodeURIComponent(o) // asci to utf8, escape() is precalucated
68
+ return prefix + decodeURIComponent(o) // Latin1 to utf8
105
69
  } catch {
106
70
  if (!loose) throw new TypeError(E_STRICT)
107
71
  // Ok, we have to use manual implementation for loose decoder
108
72
  }
109
73
  }
110
74
 
111
- return js.decode(arr, loose)
75
+ return prefix + js.decode(arr, loose, prefix.length)
112
76
  }
113
77
 
114
78
  export const utf8fromString = (str, format = 'uint8') => typedView(encode(str, false), format)