@marcuspuchalla/nachos 0.1.0

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 (100) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +674 -0
  3. package/README.md +345 -0
  4. package/dist/chunk-2FUTHZQQ.cjs +755 -0
  5. package/dist/chunk-2FUTHZQQ.cjs.map +1 -0
  6. package/dist/chunk-2HBCILJS.cjs +2034 -0
  7. package/dist/chunk-2HBCILJS.cjs.map +1 -0
  8. package/dist/chunk-7CFYWHS6.js +742 -0
  9. package/dist/chunk-7CFYWHS6.js.map +1 -0
  10. package/dist/chunk-PD72MVTX.cjs +160 -0
  11. package/dist/chunk-PD72MVTX.cjs.map +1 -0
  12. package/dist/chunk-ZDZ2B5PE.js +149 -0
  13. package/dist/chunk-ZDZ2B5PE.js.map +1 -0
  14. package/dist/chunk-ZRPJUEIZ.js +2020 -0
  15. package/dist/chunk-ZRPJUEIZ.js.map +1 -0
  16. package/dist/encoder/index.cjs +57 -0
  17. package/dist/encoder/index.cjs.map +1 -0
  18. package/dist/encoder/index.d.cts +72 -0
  19. package/dist/encoder/index.d.ts +72 -0
  20. package/dist/encoder/index.js +4 -0
  21. package/dist/encoder/index.js.map +1 -0
  22. package/dist/index.cjs +606 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +494 -0
  25. package/dist/index.d.ts +494 -0
  26. package/dist/index.js +523 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/metafile-cjs.json +1 -0
  29. package/dist/metafile-esm.json +1 -0
  30. package/dist/parser/index.cjs +85 -0
  31. package/dist/parser/index.cjs.map +1 -0
  32. package/dist/parser/index.d.cts +72 -0
  33. package/dist/parser/index.d.ts +72 -0
  34. package/dist/parser/index.js +4 -0
  35. package/dist/parser/index.js.map +1 -0
  36. package/dist/types-DvNlfbKB.d.cts +301 -0
  37. package/dist/types-DvNlfbKB.d.ts +301 -0
  38. package/dist/useCborSimpleEncoder-ButVU988.d.cts +268 -0
  39. package/dist/useCborSimpleEncoder-TVxzNJ_9.d.ts +268 -0
  40. package/dist/useCborTag-B_iaShG6.d.ts +142 -0
  41. package/dist/useCborTag-BfTIV8HM.d.cts +142 -0
  42. package/package.json +102 -0
  43. package/src/__tests__/public-api.test.ts +326 -0
  44. package/src/encoder/__tests__/cbor-collection-encoder.test.ts +331 -0
  45. package/src/encoder/__tests__/cbor-integer-encoder.test.ts +283 -0
  46. package/src/encoder/__tests__/cbor-simple-encoder.test.ts +224 -0
  47. package/src/encoder/__tests__/cbor-string-encoder.test.ts +345 -0
  48. package/src/encoder/__tests__/cbor-tag-encoder.test.ts +565 -0
  49. package/src/encoder/composables/#useCborTagEncoder.ts# +158 -0
  50. package/src/encoder/composables/useCborCollectionEncoder.ts +424 -0
  51. package/src/encoder/composables/useCborEncoder.ts +203 -0
  52. package/src/encoder/composables/useCborIntegerEncoder.ts +188 -0
  53. package/src/encoder/composables/useCborSimpleEncoder.ts +266 -0
  54. package/src/encoder/composables/useCborStringEncoder.ts +266 -0
  55. package/src/encoder/composables/useCborTagEncoder.ts +158 -0
  56. package/src/encoder/index.ts +35 -0
  57. package/src/encoder/types.ts +88 -0
  58. package/src/encoder/utils.ts +80 -0
  59. package/src/index.ts +434 -0
  60. package/src/parser/__tests__/ast-tree-structure.test.ts +311 -0
  61. package/src/parser/__tests__/cbor-collection-errors.test.ts +296 -0
  62. package/src/parser/__tests__/cbor-collection.test.ts +369 -0
  63. package/src/parser/__tests__/cbor-deterministic-encoding.test.ts +432 -0
  64. package/src/parser/__tests__/cbor-diagnostic.test.ts +333 -0
  65. package/src/parser/__tests__/cbor-duplicate-keys.test.ts +235 -0
  66. package/src/parser/__tests__/cbor-float-errors.test.ts +222 -0
  67. package/src/parser/__tests__/cbor-float.test.ts +502 -0
  68. package/src/parser/__tests__/cbor-integer-errors.test.ts +139 -0
  69. package/src/parser/__tests__/cbor-integer.test.ts +200 -0
  70. package/src/parser/__tests__/cbor-map-duplicate-keys.test.ts +403 -0
  71. package/src/parser/__tests__/cbor-parser-errors.test.ts +126 -0
  72. package/src/parser/__tests__/cbor-security-dos-protection.test.ts +503 -0
  73. package/src/parser/__tests__/cbor-sequences.test.ts +150 -0
  74. package/src/parser/__tests__/cbor-source-map.test.ts +321 -0
  75. package/src/parser/__tests__/cbor-standard-tags.test.ts +340 -0
  76. package/src/parser/__tests__/cbor-string-errors.test.ts +227 -0
  77. package/src/parser/__tests__/cbor-string.test.ts +224 -0
  78. package/src/parser/__tests__/cbor-tag-advanced.test.ts +500 -0
  79. package/src/parser/__tests__/cbor-tag-errors.test.ts +447 -0
  80. package/src/parser/__tests__/cbor-tag-source-map.test.ts +360 -0
  81. package/src/parser/__tests__/cbor-tag.test.ts +684 -0
  82. package/src/parser/__tests__/extreme-edge-cases.test.ts +146 -0
  83. package/src/parser/__tests__/pathBuilder.test.ts +256 -0
  84. package/src/parser/__tests__/rfc-test-vectors.test.ts +607 -0
  85. package/src/parser/__tests__/security-limits.test.ts +248 -0
  86. package/src/parser/__tests__/utils-errors.test.ts +127 -0
  87. package/src/parser/composables/useCborCollection.ts +509 -0
  88. package/src/parser/composables/useCborDiagnostic.ts +381 -0
  89. package/src/parser/composables/useCborFloat.ts +256 -0
  90. package/src/parser/composables/useCborInteger.ts +114 -0
  91. package/src/parser/composables/useCborParser.ts +951 -0
  92. package/src/parser/composables/useCborString.ts +330 -0
  93. package/src/parser/composables/useCborStringTypes.ts +129 -0
  94. package/src/parser/composables/useCborTag.ts +739 -0
  95. package/src/parser/index.ts +56 -0
  96. package/src/parser/types.ts +371 -0
  97. package/src/parser/utils/pathBuilder.ts +259 -0
  98. package/src/parser/utils.ts +398 -0
  99. package/src/utils/__tests__/logger.test.ts +186 -0
  100. package/src/utils/logger.ts +96 -0
@@ -0,0 +1,188 @@
1
+ /**
2
+ * CBOR Integer Encoder Composable
3
+ * Handles Major Type 0 (Unsigned) and Major Type 1 (Negative)
4
+ * Following RFC 8949 specification
5
+ */
6
+
7
+ import type { EncodeResult } from '../types'
8
+ import { bytesToHex, writeUint, writeBigUint } from '../utils'
9
+
10
+ /**
11
+ * CBOR Integer Encoder Composable
12
+ *
13
+ * Provides functions to encode integers to CBOR format:
14
+ * - Major Type 0: Unsigned integers (0 to 2^64-1)
15
+ * - Major Type 1: Negative integers (-1 to -2^64)
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const { encodeUnsignedInt, encodeNegativeInt, encodeInteger } = useCborIntegerEncoder()
20
+ *
21
+ * // Encode unsigned integer
22
+ * const result1 = encodeUnsignedInt(100)
23
+ * // result1: { bytes: Uint8Array([0x18, 0x64]), hex: '1864' }
24
+ *
25
+ * // Encode negative integer
26
+ * const result2 = encodeNegativeInt(-100)
27
+ * // result2: { bytes: Uint8Array([0x38, 0x63]), hex: '3863' }
28
+ *
29
+ * // Auto-detect integer type
30
+ * const result3 = encodeInteger(-100)
31
+ * // result3: { bytes: Uint8Array([0x38, 0x63]), hex: '3863' }
32
+ * ```
33
+ */
34
+ export function useCborIntegerEncoder() {
35
+ /**
36
+ * Encode unsigned integer (Major Type 0)
37
+ *
38
+ * Encoding rules:
39
+ * - 0-23: Direct encoding in initial byte (0x00-0x17)
40
+ * - 24-255: 0x18 + 1 byte
41
+ * - 256-65535: 0x19 + 2 bytes
42
+ * - 65536-4294967295: 0x1a + 4 bytes
43
+ * - 4294967296-2^64-1: 0x1b + 8 bytes
44
+ *
45
+ * @param value - Unsigned integer (0 to 2^64-1)
46
+ * @returns Encoded CBOR bytes and hex string
47
+ * @throws Error if value is negative or >= 2^64
48
+ */
49
+ const encodeUnsignedInt = (value: number | bigint): EncodeResult => {
50
+ // Convert to BigInt for consistent handling
51
+ const bigValue = typeof value === 'bigint' ? value : BigInt(value)
52
+
53
+ // Validate value is non-negative
54
+ if (bigValue < 0n) {
55
+ throw new Error('Cannot encode negative value as unsigned integer')
56
+ }
57
+
58
+ // Validate value doesn't exceed 2^64-1
59
+ const MAX_UINT64 = 18446744073709551615n // 2^64 - 1
60
+ if (bigValue > MAX_UINT64) {
61
+ throw new Error('Value exceeds maximum unsigned integer (2^64-1)')
62
+ }
63
+
64
+ let bytes: Uint8Array
65
+
66
+ // Direct encoding (0-23)
67
+ if (bigValue <= 23n) {
68
+ bytes = new Uint8Array([Number(bigValue)])
69
+ }
70
+ // 1-byte encoding (24-255)
71
+ else if (bigValue <= 255n) {
72
+ bytes = new Uint8Array([0x18, Number(bigValue)])
73
+ }
74
+ // 2-byte encoding (256-65535)
75
+ else if (bigValue <= 65535n) {
76
+ const valueBytes = writeUint(Number(bigValue), 2)
77
+ bytes = new Uint8Array([0x19, ...valueBytes])
78
+ }
79
+ // 4-byte encoding (65536-4294967295)
80
+ else if (bigValue <= 4294967295n) {
81
+ const valueBytes = writeUint(Number(bigValue), 4)
82
+ bytes = new Uint8Array([0x1a, ...valueBytes])
83
+ }
84
+ // 8-byte encoding (> 4294967295)
85
+ else {
86
+ const valueBytes = writeBigUint(bigValue, 8)
87
+ bytes = new Uint8Array([0x1b, ...valueBytes])
88
+ }
89
+
90
+ return {
91
+ bytes,
92
+ hex: bytesToHex(bytes)
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Encode negative integer (Major Type 1)
98
+ *
99
+ * CBOR encodes negative integers as: -1 - N
100
+ * where N is the encoded value
101
+ *
102
+ * Encoding rules:
103
+ * - -1 to -24: Direct encoding in initial byte (0x20-0x37)
104
+ * - -25 to -256: 0x38 + 1 byte
105
+ * - -257 to -65536: 0x39 + 2 bytes
106
+ * - -65537 to -4294967296: 0x3a + 4 bytes
107
+ * - -4294967297 to -2^64: 0x3b + 8 bytes
108
+ *
109
+ * @param value - Negative integer (-1 to -2^64)
110
+ * @returns Encoded CBOR bytes and hex string
111
+ * @throws Error if value is non-negative or < -2^64
112
+ */
113
+ const encodeNegativeInt = (value: number | bigint): EncodeResult => {
114
+ // Convert to BigInt for consistent handling
115
+ const bigValue = typeof value === 'bigint' ? value : BigInt(value)
116
+
117
+ // Validate value is negative
118
+ if (bigValue >= 0n) {
119
+ throw new Error('Cannot encode positive value as negative integer')
120
+ }
121
+
122
+ // Validate value doesn't exceed -2^64
123
+ const MIN_INT64 = -18446744073709551616n // -2^64
124
+ if (bigValue < MIN_INT64) {
125
+ throw new Error('Value exceeds minimum negative integer (-2^64)')
126
+ }
127
+
128
+ // CBOR encodes negative as: -1 - N
129
+ // So for value V, we encode N = -1 - V
130
+ const encoded = -1n - bigValue
131
+
132
+ let bytes: Uint8Array
133
+
134
+ // Direct encoding (-1 to -24, encoded as 0-23)
135
+ if (encoded <= 23n) {
136
+ bytes = new Uint8Array([0x20 + Number(encoded)])
137
+ }
138
+ // 1-byte encoding (-25 to -256, encoded as 24-255)
139
+ else if (encoded <= 255n) {
140
+ bytes = new Uint8Array([0x38, Number(encoded)])
141
+ }
142
+ // 2-byte encoding (-257 to -65536, encoded as 256-65535)
143
+ else if (encoded <= 65535n) {
144
+ const valueBytes = writeUint(Number(encoded), 2)
145
+ bytes = new Uint8Array([0x39, ...valueBytes])
146
+ }
147
+ // 4-byte encoding (-65537 to -4294967296, encoded as 65536-4294967295)
148
+ else if (encoded <= 4294967295n) {
149
+ const valueBytes = writeUint(Number(encoded), 4)
150
+ bytes = new Uint8Array([0x3a, ...valueBytes])
151
+ }
152
+ // 8-byte encoding (< -4294967296)
153
+ else {
154
+ const valueBytes = writeBigUint(encoded, 8)
155
+ bytes = new Uint8Array([0x3b, ...valueBytes])
156
+ }
157
+
158
+ return {
159
+ bytes,
160
+ hex: bytesToHex(bytes)
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Encode integer (auto-detect type)
166
+ *
167
+ * Automatically selects Major Type 0 (unsigned) or Major Type 1 (negative)
168
+ * based on the sign of the value.
169
+ *
170
+ * @param value - Any integer
171
+ * @returns Encoded CBOR bytes and hex string
172
+ */
173
+ const encodeInteger = (value: number | bigint): EncodeResult => {
174
+ const bigValue = typeof value === 'bigint' ? value : BigInt(value)
175
+
176
+ if (bigValue < 0n) {
177
+ return encodeNegativeInt(bigValue)
178
+ } else {
179
+ return encodeUnsignedInt(bigValue)
180
+ }
181
+ }
182
+
183
+ return {
184
+ encodeUnsignedInt,
185
+ encodeNegativeInt,
186
+ encodeInteger
187
+ }
188
+ }
@@ -0,0 +1,266 @@
1
+ /**
2
+ * CBOR Simple Values and Floats Encoder Composable
3
+ * Handles Major Type 7 (Floats and Simple Values)
4
+ * Following RFC 8949 specification
5
+ */
6
+
7
+ import type { EncodeResult, EncodeOptions } from '../types'
8
+ import { bytesToHex } from '../utils'
9
+ import { useCborIntegerEncoder } from './useCborIntegerEncoder'
10
+
11
+ /**
12
+ * CBOR Simple Values and Floats Encoder Composable
13
+ *
14
+ * Provides functions to encode:
15
+ * - Simple values: false, true, null, undefined
16
+ * - Floating-point numbers: float16, float32, float64
17
+ *
18
+ * @param options - Global encoder options
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const { encodeSimple, encodeFloat } = useCborSimpleEncoder()
23
+ *
24
+ * // Encode simple values
25
+ * const result1 = encodeSimple(true)
26
+ * // result1: { bytes: Uint8Array([0xf5]), hex: 'f5' }
27
+ *
28
+ * // Encode float
29
+ * const result2 = encodeFloat(1.1)
30
+ * // result2: { bytes: Uint8Array([0xfb, ...]), hex: 'fb...' }
31
+ * ```
32
+ */
33
+ export function useCborSimpleEncoder(_globalOptions?: Partial<EncodeOptions>) {
34
+ const { encodeInteger } = useCborIntegerEncoder()
35
+
36
+ /**
37
+ * Encode simple values (booleans, null, undefined)
38
+ *
39
+ * @param value - Simple value to encode
40
+ * @returns Encoded CBOR bytes and hex string
41
+ */
42
+ const encodeSimple = (value: boolean | null | undefined): EncodeResult => {
43
+ let byte: number
44
+
45
+ if (value === false) {
46
+ byte = 0xf4
47
+ } else if (value === true) {
48
+ byte = 0xf5
49
+ } else if (value === null) {
50
+ byte = 0xf6
51
+ } else if (value === undefined) {
52
+ byte = 0xf7
53
+ } else {
54
+ throw new Error(`Unsupported simple value: ${value}`)
55
+ }
56
+
57
+ return {
58
+ bytes: new Uint8Array([byte]),
59
+ hex: bytesToHex(new Uint8Array([byte]))
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Encode float16 (IEEE 754 half precision)
65
+ *
66
+ * @param value - Number to encode
67
+ * @returns Uint8Array with float16 bytes (2 bytes)
68
+ */
69
+ const encodeFloat16Bytes = (value: number): Uint8Array => {
70
+ // Handle special cases
71
+ if (value === 0) return new Uint8Array([0x00, 0x00])
72
+ if (value === -0) return new Uint8Array([0x80, 0x00])
73
+ if (Number.isNaN(value)) return new Uint8Array([0x7e, 0x00])
74
+ if (value === Infinity) return new Uint8Array([0x7c, 0x00])
75
+ if (value === -Infinity) return new Uint8Array([0xfc, 0x00])
76
+
77
+ // Convert float64 to float16
78
+ const sign = value < 0 ? 1 : 0
79
+ const absValue = Math.abs(value)
80
+
81
+ // Get exponent and mantissa from float64
82
+ const buffer = new ArrayBuffer(8)
83
+ const view = new DataView(buffer)
84
+ view.setFloat64(0, absValue, false)
85
+
86
+ const bits = view.getBigUint64(0, false)
87
+ const exp64 = Number((bits >> 52n) & 0x7ffn) - 1023
88
+ const mant64 = Number(bits & 0xfffffffffffffn)
89
+
90
+ // Convert to float16 range
91
+ let exp16: number
92
+ let mant16: number
93
+
94
+ if (exp64 < -14) {
95
+ // Subnormal or zero
96
+ exp16 = 0
97
+ mant16 = 0
98
+ } else if (exp64 > 15) {
99
+ // Overflow to infinity
100
+ exp16 = 31
101
+ mant16 = 0
102
+ } else {
103
+ // Normal number
104
+ exp16 = exp64 + 15
105
+ // Take top 10 bits of mantissa
106
+ mant16 = mant64 >> 42
107
+ }
108
+
109
+ const float16 = (sign << 15) | (exp16 << 10) | mant16
110
+
111
+ return new Uint8Array([
112
+ (float16 >> 8) & 0xff,
113
+ float16 & 0xff
114
+ ])
115
+ }
116
+
117
+ /**
118
+ * Encode float32 (IEEE 754 single precision)
119
+ *
120
+ * @param value - Number to encode
121
+ * @returns Uint8Array with float32 bytes (4 bytes)
122
+ */
123
+ const encodeFloat32Bytes = (value: number): Uint8Array => {
124
+ const buffer = new ArrayBuffer(4)
125
+ const view = new DataView(buffer)
126
+ view.setFloat32(0, value, false) // Big-endian
127
+
128
+ return new Uint8Array(buffer)
129
+ }
130
+
131
+ /**
132
+ * Encode float64 (IEEE 754 double precision)
133
+ *
134
+ * @param value - Number to encode
135
+ * @returns Uint8Array with float64 bytes (8 bytes)
136
+ */
137
+ const encodeFloat64Bytes = (value: number): Uint8Array => {
138
+ const buffer = new ArrayBuffer(8)
139
+ const view = new DataView(buffer)
140
+ view.setFloat64(0, value, false) // Big-endian
141
+
142
+ return new Uint8Array(buffer)
143
+ }
144
+
145
+ /**
146
+ * Check if a number can be exactly represented as float16
147
+ *
148
+ * @param value - Number to check
149
+ * @returns True if can be represented as float16
150
+ */
151
+ const canBeFloat16 = (value: number): boolean => {
152
+ // Special values
153
+ if (!Number.isFinite(value) || value === 0 || value === -0) {
154
+ return true
155
+ }
156
+
157
+ // Check range
158
+ const absValue = Math.abs(value)
159
+ if (absValue < 0.00006103515625 || absValue > 65504) {
160
+ return false
161
+ }
162
+
163
+ // Encode and decode to check for precision loss
164
+ const bytes = encodeFloat16Bytes(value)
165
+ const view = new DataView(bytes.buffer)
166
+ const bits = view.getUint16(0, false)
167
+
168
+ const sign = (bits >> 15) & 0x1
169
+ const exp = (bits >> 10) & 0x1f
170
+ const mant = bits & 0x3ff
171
+
172
+ let decoded: number
173
+
174
+ if (exp === 0) {
175
+ decoded = (sign ? -1 : 1) * Math.pow(2, -14) * (mant / 1024)
176
+ } else if (exp === 31) {
177
+ decoded = mant === 0 ? (sign ? -Infinity : Infinity) : NaN
178
+ } else {
179
+ decoded = (sign ? -1 : 1) * Math.pow(2, exp - 15) * (1 + mant / 1024)
180
+ }
181
+
182
+ return decoded === value
183
+ }
184
+
185
+ /**
186
+ * Check if a number can be exactly represented as float32
187
+ *
188
+ * @param value - Number to check
189
+ * @returns True if can be represented as float32
190
+ */
191
+ const canBeFloat32 = (value: number): boolean => {
192
+ // Special values
193
+ if (!Number.isFinite(value) || value === 0 || value === -0) {
194
+ return true
195
+ }
196
+
197
+ // Encode as float32 and decode back to check for precision loss
198
+ const buffer = new ArrayBuffer(4)
199
+ const view = new DataView(buffer)
200
+ view.setFloat32(0, value, false)
201
+ const decoded = view.getFloat32(0, false)
202
+
203
+ return decoded === value
204
+ }
205
+
206
+ /**
207
+ * Check if a number is an integer
208
+ *
209
+ * @param value - Number to check
210
+ * @returns True if value is an integer
211
+ */
212
+ const isInteger = (value: number): boolean => {
213
+ return Number.isInteger(value) && Number.isSafeInteger(value)
214
+ }
215
+
216
+ /**
217
+ * Encode floating-point number
218
+ *
219
+ * @param value - Number to encode
220
+ * @param precision - Optional precision (16, 32, or 64). If not specified, uses smallest possible.
221
+ * @returns Encoded CBOR bytes and hex string
222
+ */
223
+ const encodeFloat = (value: number, precision?: 16 | 32 | 64): EncodeResult => {
224
+ let bytes: Uint8Array
225
+
226
+ // If value is an integer, encode as integer
227
+ if (isInteger(value) && !precision) {
228
+ return encodeInteger(value)
229
+ }
230
+
231
+ // If precision is specified, use it
232
+ if (precision === 16) {
233
+ const floatBytes = encodeFloat16Bytes(value)
234
+ bytes = new Uint8Array([0xf9, ...floatBytes])
235
+ } else if (precision === 32) {
236
+ const floatBytes = encodeFloat32Bytes(value)
237
+ bytes = new Uint8Array([0xfa, ...floatBytes])
238
+ } else if (precision === 64) {
239
+ const floatBytes = encodeFloat64Bytes(value)
240
+ bytes = new Uint8Array([0xfb, ...floatBytes])
241
+ } else {
242
+ // Auto-detect smallest precision
243
+ if (canBeFloat16(value)) {
244
+ const floatBytes = encodeFloat16Bytes(value)
245
+ bytes = new Uint8Array([0xf9, ...floatBytes])
246
+ } else if (canBeFloat32(value)) {
247
+ const floatBytes = encodeFloat32Bytes(value)
248
+ bytes = new Uint8Array([0xfa, ...floatBytes])
249
+ } else {
250
+ // Use float64 for best precision
251
+ const floatBytes = encodeFloat64Bytes(value)
252
+ bytes = new Uint8Array([0xfb, ...floatBytes])
253
+ }
254
+ }
255
+
256
+ return {
257
+ bytes,
258
+ hex: bytesToHex(bytes)
259
+ }
260
+ }
261
+
262
+ return {
263
+ encodeSimple,
264
+ encodeFloat
265
+ }
266
+ }