├── .gitignore ├── .gitattributes ├── README.md ├── LICENSE └── cde.js /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | .DS_Store 3 | 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Disable LF normalization for all files 2 | * -text -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple CBOR::Core compatible encoder 2 | 3 | CBOR::Core specification: https://datatracker.ietf.org/doc/draft-rundgren-cbor-core/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /cde.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////////// 2 | // Minimalist CBOR encoder supporting the CBOR::Core primitives: 3 | // tstr, bstr, int, bigint, float (16/32/64 bit), 4 | // bool, null, tagged data (CBOR major type 6), and 5 | // simple (CBOR major type 7). 6 | // 7 | // Compatible with recent versions of node.js and browsers. 8 | // 9 | // Usage: 10 | // Plain vanilla numbers MUST be integers, otherwise an exception will be thrown. 11 | // Floating point, Tag, and Simple objects MUST be wrapped. See example. 12 | // 13 | // (C) Anders Rundgren, 2024, 2025 14 | //////////////////////////////////////////////////////////////////////////////////// 15 | 16 | class CBOR { 17 | 18 | // Float wrapper 19 | static Float = class { 20 | 21 | #encoded; 22 | 23 | constructor(value) { 24 | // Begin catching the F16 edge cases. 25 | if (Number.isNaN(value)) { 26 | this.#encoded = CBOR.#int16ToByteArray(0x7e00); 27 | } else if (!Number.isFinite(value)) { 28 | this.#encoded = CBOR.#int16ToByteArray(value < 0 ? 0xfc00 : 0x7c00); 29 | } else if (value == 0) { // works for -0 as well! 30 | this.#encoded = CBOR.#int16ToByteArray(Object.is(value, -0) ? 0x8000 : 0x0000); 31 | } else { 32 | // It is apparently a genuine (non-zero) number. 33 | // The following code depends on that Math.fround works as expected. 34 | let f32 = Math.fround(value); 35 | const u8 = new Uint8Array(8); 36 | new DataView(u8.buffer, 0, 8).setFloat64(0, value, false); 37 | let f32exp; 38 | let f32signif; 39 | while (true) { // "goto" surely beats quirky loop/break/return/flag constructs... 40 | if (f32 == value) { 41 | // Nothing was lost during the conversion, F32 or F16 is on the menu. 42 | f32exp = ((u8[0] & 0x7f) << 4) + (u8[1] >> 4) - 0x380; 43 | f32signif = ((u8[1] & 0x0f) << 19) + (u8[2] << 11) + (u8[3] << 3) + (u8[4] >> 5); 44 | // Very small F32 numbers may require subnormal representation. 45 | if (f32exp <= 0) { 46 | // The implicit "1" becomes explicit using subnormal representation. 47 | f32signif += 0x800000; 48 | // Denormalize by shifting right 1-23 positions. 49 | f32signif >>= (1 - f32exp); 50 | f32exp = 0; 51 | // Subnormal F32 cannot be represented by F16, stick to F32. 52 | break; 53 | } 54 | // If F16 would lose precision, stick to F32. 55 | if (f32signif & 0x1fff) { 56 | break; 57 | } 58 | // Setup for F16. 59 | let f16exp = f32exp - 0x70; 60 | // Too small or too big for F16, or running into F16 NaN/Infinity space. 61 | if (f16exp <= -10 || f16exp > 30) { 62 | break; 63 | } 64 | let f16signif = f32signif >> 13; 65 | // Finally, check if we need to denormalize F16. 66 | if (f16exp <= 0) { 67 | if (f16signif & ((1 << (1 - f16exp)) - 1)) { 68 | // Losing bits is not an option, stick to F32. 69 | break; 70 | } 71 | // The implicit "1" becomes explicit using subnormal representation. 72 | f16signif += 0x400; 73 | // Shift significand into position. 74 | f16signif >>= (1 - f16exp); 75 | // Valid and denormalized F16. 76 | f16exp = 0; 77 | } 78 | // A rarity, 16 bits turned out being sufficient for representing the number. 79 | this.#encoded = CBOR.#int16ToByteArray( 80 | // Put sign bit in position. 81 | ((u8[0] & 0x80) << 8) + 82 | // Exponent. Put it in front of significand. 83 | (f16exp << 10) + 84 | // Significand. 85 | f16signif); 86 | } else { 87 | // Converting value to F32 returned a truncated result. 88 | // Full 64-bit representation is required. 89 | this.#encoded = u8; 90 | } 91 | // Common F16 and F64 return point. 92 | return; 93 | } 94 | // Broken loop: 32 bits are apparently needed for maintaining magnitude and precision. 95 | let f32bin = 96 | // Put sign bit in position. Why not << 24? JS shift doesn't work above 2^31... 97 | ((u8[0] & 0x80) * 0x1000000) + 98 | // Exponent. Put it in front of significand (<< 23). 99 | (f32exp * 0x800000) + 100 | // Significand. 101 | f32signif; 102 | this.#encoded = CBOR.#addArrays(CBOR.#int16ToByteArray(f32bin / 0x10000), 103 | CBOR.#int16ToByteArray(f32bin % 0x10000)); 104 | } 105 | } 106 | 107 | encode = function() { 108 | return CBOR.#addArrays(new Uint8Array([(this.#encoded.length >> 2) + 0xf9]), this.#encoded); 109 | } 110 | } 111 | 112 | // Tag wrapper 113 | static Tag = class { 114 | 115 | #encoded; 116 | 117 | constructor(tagNumber /* BigInt */, object) { 118 | this.#encoded = CBOR.#addArrays(CBOR.#encodeInteger(0xc0, tagNumber), 119 | CBOR.encode(object)); 120 | } 121 | 122 | encode = function() { 123 | return this.#encoded; 124 | } 125 | } 126 | 127 | // Simple wrapper 128 | static Simple = class { 129 | 130 | #encoded; 131 | 132 | constructor(value) { 133 | if (!Number.isSafeInteger(value) || value < 0 || value > 255 || (value > 23 && value < 32)) { 134 | CBOR.#error('Invalid simple argument: ' + value); 135 | } 136 | this.#encoded = CBOR.#encodeInteger(0xe0, BigInt(value)); 137 | } 138 | 139 | encode = function() { 140 | return this.#encoded; 141 | } 142 | } 143 | 144 | // The Proxy concept enables checks for invocation by "new" and number of arguments. 145 | static #handler = class { 146 | 147 | constructor(numberOfArguments) { 148 | this.numberOfArguments = numberOfArguments; 149 | } 150 | 151 | apply(target, thisArg, argumentsList) { 152 | if (argumentsList.length != this.numberOfArguments) { 153 | CBOR.#error("CBOR." + target.name + " expects " + this.numberOfArguments + " argument(s)"); 154 | } 155 | return new target(...argumentsList); 156 | } 157 | 158 | construct(target, args) { 159 | CBOR.#error("CBOR." + target.name + " does not permit \"new\""); 160 | } 161 | } 162 | 163 | static Float = new Proxy(CBOR.Float, new CBOR.#handler(1)); 164 | static Tag = new Proxy(CBOR.Tag, new CBOR.#handler(2)); 165 | static Simple = new Proxy(CBOR.Simple, new CBOR.#handler(1)); 166 | 167 | static #addArrays = function(a, b) { 168 | let result = new Uint8Array(a.length + b.length); 169 | result.set(a); 170 | result.set(b, a.length); 171 | return result; 172 | } 173 | 174 | static #encodeString = function(tag, binary) { 175 | return CBOR.#addArrays(CBOR.#encodeInteger(tag, BigInt(binary.length)), binary); 176 | } 177 | 178 | static #int16ToByteArray = function(int16) { 179 | return new Uint8Array([int16 / 256, int16 % 256]); 180 | } 181 | 182 | static #encodeMap = function(object) { 183 | let result = CBOR.#encodeInteger(0xa0, BigInt(object.size)); 184 | let encPair = {}; 185 | object.forEach((value, key) => { 186 | let binaryKey = CBOR.encode(key); 187 | encPair[CBOR.toHex(binaryKey)] = CBOR.#addArrays(binaryKey, CBOR.encode(value)); 188 | }); 189 | Object.keys(encPair).sort().forEach((key) => { 190 | result = CBOR.#addArrays(result, encPair[key]); 191 | }); 192 | return result; 193 | } 194 | 195 | static #encodeInteger = function(tag, value) { 196 | let neg = value < 0n; 197 | // Only applies to "int" and "bigint" 198 | if (neg) { 199 | value = ~value; 200 | tag = 0x20; 201 | } 202 | // Convert BigInt to Uint8Array (but with a twist). 203 | let array = []; 204 | do { 205 | array.push(Number(value & 255n)); 206 | } while (value >>= 8n); 207 | let length = array.length; 208 | // Prepare for "int" encoding (1, 2, 4, 8). Only 3, 5, 6, and 7 need an action. 209 | while (length < 8 && length > 2 && length != 4) { 210 | array.push(0); 211 | length++; 212 | } 213 | // Make big endian. 214 | let byteArray = new Uint8Array(array.reverse()); 215 | // Does this number qualify as a "bigint"? 216 | if (length <= 8) { 217 | // Apparently not, encode it as "int". 218 | if (length == 1 && byteArray[0] <= 23) { 219 | return new Uint8Array([tag | byteArray[0]]); 220 | } 221 | let modifier = 24; 222 | while (length >>= 1) { 223 | modifier++; 224 | } 225 | return CBOR.#addArrays(new Uint8Array([tag | modifier]), byteArray); 226 | } 227 | // True "BigInt". 228 | return CBOR.#addArrays(new Uint8Array([neg ? 0xc3 : 0xc2]), 229 | CBOR.#encodeString(0x40, byteArray)); 230 | 231 | } 232 | 233 | static #error = function(message) { 234 | throw new Error(message); 235 | } 236 | 237 | // The primary method... 238 | static encode = function(object) { 239 | if (object === null) { 240 | return new Uint8Array([0xf6]); 241 | } 242 | 243 | if (object instanceof CBOR.Float || 244 | object instanceof CBOR.Tag || object instanceof CBOR.Simple) { 245 | return object.encode(); 246 | } 247 | 248 | if (object instanceof Uint8Array) { 249 | return CBOR.#encodeString(0x40, object); 250 | } 251 | 252 | if (object instanceof Map) { 253 | return CBOR.#encodeMap(object); 254 | } 255 | 256 | if (typeof object != 'object') { 257 | switch (typeof object) { 258 | case 'number': 259 | if (!Number.isSafeInteger(object)) CBOR.#error('Invalid integer: ' + object); 260 | object = BigInt(object); 261 | // Fallthrough 262 | case 'bigint': 263 | return CBOR.#encodeInteger(0x00, object); 264 | 265 | case 'string': 266 | return CBOR.#encodeString(0x60, new TextEncoder().encode(object)); 267 | 268 | case 'boolean': 269 | return new Uint8Array([object ? 0xf5 : 0xf4]); 270 | 271 | default: 272 | CBOR.#error('Unexpected object: ' + object); 273 | } 274 | } 275 | 276 | if (Array.isArray(object)) { 277 | let result = CBOR.#encodeInteger(0x80, BigInt(object.length)); 278 | object.forEach((element) => { 279 | result = CBOR.#addArrays(result, CBOR.encode(element)); 280 | }); 281 | return result; 282 | } 283 | // JavaScript object {} 284 | return CBOR.#encodeMap(new Map(Object.entries(object))); 285 | } 286 | 287 | static #oneHex = function(digit) { 288 | return String.fromCharCode(digit < 10 ? (0x30 + digit) : (0x57 + digit)); 289 | } 290 | 291 | static #twoHex = function(byte) { 292 | return CBOR.#oneHex(byte / 16) + CBOR.#oneHex(byte % 16); 293 | } 294 | 295 | // Nice to have... 296 | static toHex(binary) { 297 | let hexString = ''; 298 | binary.forEach((element) => { 299 | hexString += CBOR.#twoHex(element); 300 | }); 301 | return hexString; 302 | } 303 | } 304 | 305 | // Testing/Demo 306 | 307 | function test(description, object, reference) { 308 | let toHex = CBOR.toHex(CBOR.encode(object)); 309 | console.log(description + ':\n' + toHex + '\n') 310 | if (toHex.length != reference.length) { 311 | throw new Error('Length\n' + reference); 312 | } 313 | for (let i = 0; i < toHex.length; i++) if (toHex.charCodeAt(i) != reference.charCodeAt(i)) { 314 | let p = "^"; 315 | while (--i >= 0) p = ' ' + p; 316 | throw new Error(reference + '\n' + p); 317 | } 318 | } 319 | 320 | let map = { 321 | "int": 6, // The Number type MUST in this implementation be a valid JS Integer. 322 | "float": CBOR.Float(50), // Ugly? The number of discrete Float variables are typically few. 323 | "bigint": 10000000000000000000000000002n, // 2n would of course still return 0x02. 324 | "binary": new Uint8Array([1, 2, 3, 4, -1]), 325 | "string": "hi there!", 326 | "simple": CBOR.Simple(59), 327 | "bool": true, 328 | "null": null, 329 | "jmap": new Map() // The more advanced map, permitting arbitrary key expressions. 330 | .set(3, "three") 331 | .set(1n, "one"), 332 | "tag": CBOR.Tag(6789n, {"key": "value"}), 333 | "array": [4, "str", CBOR.Float(Number.NaN), CBOR.Float(0.333333333333333), false] 334 | } 335 | test("General CBOR", map, 'ab63696e740663746167d91a85a1636b65796576616c75656462\ 336 | 6f6f6cf5646a6d6170a201636f6e6503657468726565646e756c6cf665617272617985046373747\ 337 | 2f97e00fb3fd555555555554ff465666c6f6174f9524066626967696e74c24c204fce5e3e250261\ 338 | 100000026662696e6172794501020304ff6673696d706c65f83b66737472696e676968692074686\ 339 | 5726521'); 340 | 341 | // Read a single data item. 342 | test("Float data item", map.float, 'f95240'); 343 | // Remove key and value. 344 | delete map.float; 345 | 346 | // Add a new key and value. 347 | map.jmap.set(-1, CBOR.Float(0.3)); 348 | test("Transformed CBOR", map, 'aa63696e740663746167d91a85a1636b65796576616c7565\ 349 | 64626f6f6cf5646a6d6170a301636f6e650365746872656520fb3fd3333333333333646e756c6cf\ 350 | 6656172726179850463737472f97e00fb3fd555555555554ff466626967696e74c24c204fce5e3e\ 351 | 250261100000026662696e6172794501020304ff6673696d706c65f83b66737472696e676968692\ 352 | 0746865726521'); 353 | 354 | let floats = [ 355 | 0.0, 356 | -0.0, 357 | Infinity, 358 | -Infinity, 359 | NaN, 360 | -5.960464477539062e-8, 361 | -5.960464477539063e-8, 362 | -5.960464477539064e-8, 363 | -5.960465188081798e-8, 364 | 0.00006097555160522461, 365 | 65504.0, 366 | 65504.00390625, 367 | 65536.0, 368 | 10.559998512268066, 369 | 10.559998512268068, 370 | 3.4028234663852886e+38, 371 | 3.402823466385289e+38, 372 | 1.4012984643248169e-45, 373 | 1.401298464324817e-45, 374 | 1.4012984643248174e-45, 375 | 1.4012986313726115e-45, 376 | 1.1754942106924411e-38, 377 | 5.0e-324, 378 | -1.7976931348623157e+308 379 | ]; 380 | for (let i = 0; i < floats.length; i++) floats[i] = CBOR.Float(floats[i]); 381 | test("Floating Point", floats, '9818f90000f98000f97c00f9fc00f97e00fbbe6ffffffff\ 382 | ffffff98001fbbe70000000000001fab3800001f903fff97bfffa477fe001fa47800000fa4128f5\ 383 | c1fb40251eb820000001fa7f7ffffffb47efffffe0000001fb369ffffffffffffffa00000001fb3\ 384 | 6a0000000000001fb36a0000020000000fa007ffffffb0000000000000001fbffefffffffffffff'); 385 | 386 | let ints = [ 387 | 0, 388 | -1, 389 | 2.0, // Note: JavaScript does not tag this any different than 2 390 | 23, 391 | 24, 392 | -24, 393 | -25, 394 | 255, 395 | 256, 396 | -256, 397 | -257, 398 | 2147483648, 399 | 4294967295, 400 | 4294967296, 401 | -4294967296, 402 | -4294967297, 403 | 1099511627775, 404 | 9007199254740991, 405 | 1n, 406 | 18446744073709551615n, 407 | 18446744073709551616n, 408 | -18446744073709551616n, 409 | -18446744073709551617n 410 | ]; 411 | 412 | test("Integers", ints, '9700200217181837381818ff19010038ff3901001a800000001aff\ 413 | ffffff1b00000001000000003affffffff3b00000001000000001b000000ffffffffff1b001fff\ 414 | ffffffffff011bffffffffffffffffc2490100000000000000003bffffffffffffffffc3490100\ 415 | 00000000000000'); 416 | 417 | // An unwrapped "Number", MUST be a JavaScript-constrained integer 418 | [1.5, 9007199254740992].forEach((element) => { 419 | try { 420 | CBOR.encode(element); 421 | throw new Error("Should fail"); 422 | } catch (error) { 423 | if (!error.toString().includes("Invalid integer: " + element)) { 424 | throw new Error("Error in error"); 425 | } 426 | } 427 | }); 428 | --------------------------------------------------------------------------------