├── .c8rc.json ├── .eslintrc.json ├── .github ├── dependabot.yml ├── release-drafter.yml └── workflows │ ├── codeql.yml │ ├── nodejs-ci.yml │ ├── post-dependabot-prs.yml │ └── release-drafter.yml ├── .gitignore ├── .mocharc.json ├── LICENSE ├── README.md ├── lib ├── index.ts └── tsconfig.json ├── package.json ├── test ├── test-classes.ts ├── test-ieee-754-floats.ts ├── test-int16.ts ├── test-int24.ts ├── test-int32.ts ├── test-int64.ts ├── test-int8.ts ├── test-iso-8859-1.ts ├── test-uint16.ts ├── test-uint24.ts ├── test-uint32.ts ├── test-uint64.ts ├── test-uint8.ts ├── tsconfig.json └── util.ts ├── tsconfig.json ├── tslint.json └── yarn.lock /.c8rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "reporter": [ 3 | "lcov", 4 | "text" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "prettier" 9 | ], 10 | "parser": "@typescript-eslint/parser", 11 | "parserOptions": { 12 | "project": "./tsconfig.json", 13 | "sourceType": "module" 14 | }, 15 | "plugins": [ 16 | "eslint-plugin-import", 17 | "eslint-plugin-jsdoc", 18 | "eslint-plugin-node", 19 | "eslint-plugin-unicorn", 20 | "@typescript-eslint" 21 | ], 22 | "rules": { 23 | "@typescript-eslint/adjacent-overload-signatures": "error", 24 | "@typescript-eslint/array-type": [ 25 | "error", 26 | { 27 | "default": "array" 28 | } 29 | ], 30 | "@typescript-eslint/ban-types": [ 31 | "error", 32 | { 33 | "types": { 34 | "Object": { 35 | "message": "Avoid using the `Object` type. Did you mean `object`?" 36 | }, 37 | "Function": { 38 | "message": "Avoid using the `Function` type. Prefer a specific function type, like `() => void`." 39 | }, 40 | "Boolean": { 41 | "message": "Avoid using the `Boolean` type. Did you mean `boolean`?" 42 | }, 43 | "Number": { 44 | "message": "Avoid using the `Number` type. Did you mean `number`?" 45 | }, 46 | "String": { 47 | "message": "Avoid using the `String` type. Did you mean `string`?" 48 | }, 49 | "Symbol": { 50 | "message": "Avoid using the `Symbol` type. Did you mean `symbol`?" 51 | } 52 | } 53 | } 54 | ], 55 | "@typescript-eslint/consistent-type-assertions": "error", 56 | "@typescript-eslint/dot-notation": "error", 57 | "@typescript-eslint/indent": [ 58 | "error", 59 | 2, 60 | { 61 | "ObjectExpression": "first", 62 | "FunctionDeclaration": { 63 | "parameters": "first" 64 | }, 65 | "FunctionExpression": { 66 | "parameters": "first" 67 | }, 68 | "SwitchCase": 1 69 | } 70 | ], 71 | "@typescript-eslint/naming-convention": "off", 72 | "@typescript-eslint/no-empty-function": [ 73 | "error", 74 | { 75 | "allow": [ 76 | "constructors" 77 | ] 78 | } 79 | ], 80 | "@typescript-eslint/no-empty-interface": "error", 81 | "@typescript-eslint/no-explicit-any": "off", 82 | "@typescript-eslint/no-misused-new": "error", 83 | "@typescript-eslint/no-namespace": "error", 84 | "@typescript-eslint/no-parameter-properties": "off", 85 | "@typescript-eslint/no-shadow": [ 86 | "error", 87 | { 88 | "hoist": "all" 89 | } 90 | ], 91 | "@typescript-eslint/no-this-alias": "error", 92 | "@typescript-eslint/no-unused-expressions": "error", 93 | "@typescript-eslint/no-use-before-define": "off", 94 | "@typescript-eslint/no-var-requires": "error", 95 | "@typescript-eslint/prefer-for-of": "off", 96 | "@typescript-eslint/prefer-function-type": "error", 97 | "@typescript-eslint/prefer-namespace-keyword": "error", 98 | "@typescript-eslint/quotes": "off", 99 | "@typescript-eslint/semi": [ 100 | "error", 101 | "always" 102 | ], 103 | "@typescript-eslint/triple-slash-reference": [ 104 | "error", 105 | { 106 | "path": "always", 107 | "types": "prefer-import", 108 | "lib": "always" 109 | } 110 | ], 111 | "@typescript-eslint/unified-signatures": "error", 112 | "arrow-parens": [ 113 | "error", 114 | "as-needed" 115 | ], 116 | "comma-dangle": "error", 117 | "complexity": "off", 118 | "constructor-super": "error", 119 | "curly": "off", 120 | "default-case": "off", 121 | "dot-notation": "error", 122 | "eqeqeq": [ 123 | "error", 124 | "smart" 125 | ], 126 | "guard-for-in": "off", 127 | "id-denylist": [ 128 | "error", 129 | "any", 130 | "Number", 131 | "number", 132 | "String", 133 | "string", 134 | "Boolean", 135 | "boolean", 136 | "Undefined", 137 | "undefined" 138 | ], 139 | "id-match": "error", 140 | "import/no-extraneous-dependencies": [ 141 | "error", {"devDependencies": ["test/**/*.ts"]} 142 | ], 143 | "import/no-internal-modules": "off", 144 | "import/order": "off", 145 | "import/no-unresolved": ["error", {"caseSensitiveStrict": true }], 146 | "indent": "off", 147 | "jsdoc/check-alignment": "error", 148 | "jsdoc/check-indentation": "error", 149 | "jsdoc/tag-lines": [ 150 | "error", 151 | "never" 152 | ], 153 | "max-classes-per-file": "off", 154 | "max-len": [ 155 | "error", 156 | { 157 | "code": 200 158 | } 159 | ], 160 | "new-parens": "error", 161 | "no-bitwise": "off", 162 | "no-caller": "error", 163 | "no-cond-assign": "error", 164 | "no-console": "error", 165 | "no-debugger": "error", 166 | "no-duplicate-case": "error", 167 | "no-duplicate-imports": "error", 168 | "no-empty": "error", 169 | "no-empty-function": "off", 170 | "no-eval": "error", 171 | "no-extra-bind": "error", 172 | "no-fallthrough": "off", 173 | "no-invalid-this": "off", 174 | "no-new-func": "error", 175 | "no-new-wrappers": "error", 176 | "no-redeclare": "error", 177 | "no-return-await": "error", 178 | "no-sequences": "error", 179 | "no-shadow": "off", 180 | "no-sparse-arrays": "error", 181 | "no-template-curly-in-string": "error", 182 | "no-throw-literal": "error", 183 | "no-trailing-spaces": "error", 184 | "no-undef-init": "error", 185 | "no-underscore-dangle": "error", 186 | "no-unsafe-finally": "error", 187 | "no-unused-expressions": "error", 188 | "no-unused-labels": "error", 189 | "no-use-before-define": "off", 190 | "no-var": "error", 191 | "node/file-extension-in-import": ["error", "always"], 192 | "node/no-extraneous-import": "error", 193 | "object-shorthand": "error", 194 | "one-var": [ 195 | "error", 196 | "never" 197 | ], 198 | "prefer-const": "error", 199 | "prefer-object-spread": "error", 200 | "quote-props": [ 201 | "error", 202 | "as-needed" 203 | ], 204 | "quotes": "off", 205 | "radix": "error", 206 | "semi": "error", 207 | "space-in-parens": [ 208 | "error", 209 | "never" 210 | ], 211 | "spaced-comment": [ 212 | "error", 213 | "always", 214 | { 215 | "markers": [ 216 | "/" 217 | ] 218 | } 219 | ], 220 | "unicorn/prefer-ternary": "error", 221 | "use-isnan": "error", 222 | "valid-typeof": "off" 223 | }, 224 | "settings": { 225 | "import/parsers": { 226 | "@typescript-eslint/parser": [ 227 | ".ts", 228 | ".tsx" 229 | ] 230 | }, 231 | "import/resolver": { 232 | "typescript": { 233 | "alwaysTryTypes": true, 234 | "project": [ 235 | "lib/tsconfig.json", 236 | "test/tsconfig.json" 237 | ] 238 | } 239 | } 240 | } 241 | } 242 | 243 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | 5 | # ECMAScript Module (ESM) 6 | - package-ecosystem: npm 7 | directory: "/" 8 | schedule: 9 | interval: weekly 10 | time: "06:00" 11 | open-pull-requests-limit: 10 12 | versioning-strategy: increase 13 | target-branch: "master" 14 | labels: 15 | - dependencies 16 | - ESM 17 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # Release Drafter template 2 | # Ref: https://github.com/marketplace/actions/release-drafter 3 | 4 | name-template: 'v$RESOLVED_VERSION' 5 | tag-template: 'v$RESOLVED_VERSION' 6 | categories: 7 | - title: 🚀 Enhancements 8 | labels: 9 | - enhancement 10 | - title: 🎨 Improvements 11 | labels: 12 | - improvement 13 | - title: 🐛 Bug Fixes 14 | labels: 15 | - bug 16 | - title: 🔧 Under the hood 17 | labels: 18 | - debt 19 | - dev-dependencies 20 | - title: ⬆️ Dependencies 21 | labels: 22 | - dependencies 23 | exclude-labels: 24 | - DevOps 25 | - dev-dependencies 26 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 27 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 28 | version-resolver: 29 | major: 30 | labels: 31 | - 'major' 32 | minor: 33 | labels: 34 | - 'minor' 35 | patch: 36 | labels: 37 | - 'patch' 38 | default: patch 39 | template: | 40 | ## Changes 41 | 42 | $CHANGES 43 | 44 | ## NPM release 45 | NPM release: [$REPOSITORY@$RESOLVED_VERSION](https://www.npmjs.com/package/$REPOSITORY/v/$RESOLVED_VERSION) 46 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | schedule: 9 | - cron: "26 15 * * 5" 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ javascript ] 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v2 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | - name: Autobuild 36 | uses: github/codeql-action/autobuild@v2 37 | 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v2 40 | with: 41 | category: "/language:${{ matrix.language }}" 42 | -------------------------------------------------------------------------------- /.github/workflows/nodejs-ci.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | on: 3 | pull_request: 4 | branches: [ "master" ] 5 | push: 6 | branches: [ "master" ] 7 | 8 | jobs: 9 | 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | 16 | - uses: actions/checkout@v4 17 | 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 22.x 21 | 22 | - name: Install production dependencies, check node engine compatiblity 23 | run: yarn install --production=true 24 | 25 | - name: Install development dependencies 26 | run: yarn install --production=false --ignore-engines 27 | 28 | - name: Build & Code analysis 29 | run: yarn run lint 30 | 31 | - name: Build 32 | run: yarn run build 33 | 34 | - name: Upload build 35 | uses: actions/upload-artifact@v4 36 | with: 37 | name: build 38 | path: | 39 | lib/**/*.js 40 | lib/**/*.js.map 41 | lib/**/*.d.ts 42 | test/**/*.js 43 | test/**/*.js.map 44 | 45 | test: 46 | 47 | runs-on: ubuntu-latest 48 | 49 | needs: build 50 | 51 | strategy: 52 | matrix: 53 | node-version: [16.x, 18.x, 20.x, 22.x] 54 | 55 | steps: 56 | 57 | - name: 'Checkout the repository' 58 | uses: actions/checkout@v4 59 | 60 | - name: Test with Node.js ${{ matrix.node-version }} 61 | uses: actions/setup-node@v4 62 | with: 63 | node-version: ${{ matrix.node-version }} 64 | 65 | - name: Install dependencies 66 | run: yarn install --ignore-engines 67 | 68 | - name: Download build 69 | uses: actions/download-artifact@v4 70 | with: 71 | name: build 72 | 73 | - name: Test with Node.js ${{ matrix.node-version }} 74 | run: yarn run test-coverage 75 | 76 | - name: Coveralls Parallel 77 | uses: coverallsapp/github-action@v2 78 | with: 79 | github-token: ${{ secrets.github_token }} 80 | flag-name: run-${{ matrix.test_number }} 81 | parallel: true 82 | 83 | finish: 84 | needs: test 85 | runs-on: ubuntu-latest 86 | steps: 87 | - name: Coveralls Finished 88 | uses: coverallsapp/github-action@v2 89 | with: 90 | github-token: ${{ secrets.github_token }} 91 | parallel-finished: true 92 | -------------------------------------------------------------------------------- /.github/workflows/post-dependabot-prs.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot Pull Request 2 | on: pull_request_target 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }} 7 | steps: 8 | - name: Fetch Dependabot metadata 9 | id: dependabot-metadata 10 | uses: dependabot/fetch-metadata@v1 11 | with: 12 | github-token: "${{ secrets.GITHUB_TOKEN }}" 13 | - name: Add dev-dependencies label 14 | uses: actions-ecosystem/action-add-labels@v1 15 | if: ${{ steps.dependabot-metadata.outputs.dependency-type == 'direct:development' }} 16 | with: 17 | labels: dev-dependencies 18 | - name: Remove dependencies label 19 | uses: actions-ecosystem/action-remove-labels@v1 20 | if: ${{ steps.dependabot-metadata.outputs.dependency-type == 'direct:development' }} 21 | with: 22 | labels: dependencies 23 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | types: [opened, reopened, synchronize] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | update_release_draft: 15 | permissions: 16 | contents: write 17 | pull-requests: write 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: release-drafter/release-drafter@v6 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | node_modules 3 | **/*.js 4 | **/*.js.map 5 | **/*.d.ts 6 | coverage 7 | -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ["ts", "tsx"], 3 | "watch-files": ["lib/**/*.ts", "test/**/*.ts"], 4 | "spec": ["test/*.ts"], 5 | "loader": ["ts-node/esm"], 6 | "extensions": ["ts", "tsx"] 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Borewit 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Node.js CI](https://github.com/Borewit/token-types/actions/workflows/nodejs-ci.yml/badge.svg?branch=master)](https://github.com/Borewit/token-types/actions/workflows/nodejs-ci.yml?query=branch%3Amaster) 2 | [![NPM version](https://badge.fury.io/js/token-types.svg)](https://npmjs.org/package/token-types) 3 | [![npm downloads](http://img.shields.io/npm/dm/token-types.svg)](https://npmcharts.com/compare/token-types,strtok3?start=1200&interval=30) 4 | [![coveralls](https://coveralls.io/repos/github/Borewit/token-types/badge.svg?branch=master)](https://coveralls.io/github/Borewit/token-types?branch=master) 5 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/4723ce4613fc49cda8db5eed29f18834)](https://www.codacy.com/app/Borewit/token-types?utm_source=github.com&utm_medium=referral&utm_content=Borewit/token-types&utm_campaign=Badge_Grade) 6 | [![DeepScan grade](https://deepscan.io/api/teams/5165/projects/6940/branches/61852/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=5165&pid=6940&bid=61852) 7 | [![Known Vulnerabilities](https://snyk.io/test/github/Borewit/token-types/badge.svg?targetFile=package.json)](https://snyk.io/test/github/Borewit/token-types?targetFile=package.json) 8 | 9 | # token-types 10 | 11 | A primitive token library used to read and write from a `Uint8Array`. 12 | Although it is possible to use this module directly, it is primarily designed to be used with [strtok3 tokenizer](https://github.com/Borewit/strtok3). 13 | 14 | ## Compatibility 15 | 16 | Module: version 5 migrated from [CommonJS](https://en.wikipedia.org/wiki/CommonJS) to [pure ECMAScript Module (ESM)](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). 17 | JavaScript is compliant with [ECMAScript 2019 (ES10)](https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_%E2%80%93_ECMAScript_2019). 18 | 19 | ## Installation 20 | 21 | ```sh 22 | npm install --save token-types 23 | ``` 24 | Usually in combination with [strtok3](https://github.com/Borewit/strtok3): 25 | ```sh 26 | npm install --save strtok3 27 | ``` 28 | 29 | Using TypeScript you should also install [@tokenizer/token](https://github.com/Borewit/tokenizer-token) as a development 30 | dependency: 31 | 32 | ```shell 33 | npm install --save-dev @tokenizer/token 34 | ``` 35 | 36 | 37 | ## Example 38 | 39 | ```js 40 | import * as strtok3 from 'strtok3'; 41 | import * as token from 'token-types'; 42 | 43 | (async () => { 44 | 45 | const tokenizer = await strtok3.fromFile("somefile.bin"); 46 | try { 47 | const myNumber = await tokenizer.readToken(token.Float32_BE); 48 | console.log(`My number: ${myNumber}`); 49 | } finally { 50 | tokenizer.close(); // Close the file 51 | } 52 | })(); 53 | ``` 54 | 55 | ## Tokens 56 | 57 | ### Numeric tokens 58 | 59 | `token-types` supports a wide variety of numeric tokens out of the box: 60 | 61 | | Token | Number | Bits | Endianness | 62 | |---------------|------------------|------|----------------| 63 | | `UINT8` | Unsigned integer | 8 | n/a | 64 | | `UINT16_BE` | Unsigned integer | 16 | big endian | 65 | | `UINT16_LE` | Unsigned integer | 16 | little endian | 66 | | `UINT24_BE` | Unsigned integer | 24 | big endian | 67 | | `UINT24_LE` | Unsigned integer | 24 | little endian | 68 | | `UINT32_BE` | Unsigned integer | 32 | big endian | 69 | | `UINT32_LE` | Unsigned integer | 32 | little endian | 70 | | `UINT64_BE` | Unsigned integer | 64 | big endian | 71 | | `UINT64_LE`* | Unsigned integer | 64 | little endian | 72 | | `INT8` | Signed integer | 8 | n/a | 73 | | `INT16_BE` | Signed integer | 16 | big endian | 74 | | `INT16_LE` | Signed integer | 16 | little endian | 75 | | `INT24_BE` | Signed integer | 24 | big endian | 76 | | `INT24_LE` | Signed integer | 24 | little endian | 77 | | `INT32_BE` | Signed integer | 32 | big endian | 78 | | `INT32_LE` | Signed integer | 32 | little endian | 79 | | `INT64_BE` | Signed integer | 64 | big endian | 80 | | `INT64_LE`* | Signed integer | 64 | little endian | 81 | | `Float16_BE` | IEEE 754 float | 16 | big endian | 82 | | `Float16_LE` | IEEE 754 float | 16 | little endian | 83 | | `Float32_BE` | IEEE 754 float | 32 | big endian | 84 | | `Float32_LE` | IEEE 754 float | 32 | little endian | 85 | | `Float64_BE` | IEEE 754 float | 64 | big endian | 86 | | `Float64_LE` | IEEE 754 float | 64 | little endian | 87 | | `Float80_BE`* | IEEE 754 float | 80 | big endian | 88 | | `Float80_LE`* | IEEE 754 float | 80 | little endian | 89 | 90 | (*) The tokens exceed the JavaScript IEEE 754 64-bit Floating Point precision, decoding and encoding is best effort based. 91 | 92 | ### String tokens 93 | 94 | StringType decoding is implemented using TextDecoder which supports a large number of encodings including but not limited to: 95 | 96 | * UTF-8 (the default) 97 | * Windows-1252 98 | * ISO-8859-1 99 | 100 | Check out [the MDN web docs for the TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/encoding) for a complete list 101 | 102 | ### Custom tokens 103 | 104 | Custom tokens can be added, suitable for reading binary files or network messages: 105 | ```js 106 | ExtendedHeader = { 107 | len: 10, 108 | 109 | get: (buf, off) => { 110 | return { 111 | // Extended header size 112 | size: Token.UINT32_BE.get(buf, off), 113 | // Extended Flags 114 | extendedFlags: Token.UINT16_BE.get(buf, off + 4), 115 | // Size of padding 116 | sizeOfPadding: Token.UINT32_BE.get(buf, off + 6), 117 | // CRC data present 118 | crcDataPresent: common.strtokBITSET.get(buf, off + 4, 31) 119 | }; 120 | } 121 | }; 122 | ``` 123 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import * as ieee754 from 'ieee754'; 2 | import type { IToken, IGetToken } from '@tokenizer/token'; 3 | 4 | // Primitive types 5 | 6 | function dv(array: Uint8Array) { 7 | return new DataView(array.buffer, array.byteOffset); 8 | } 9 | 10 | /** 11 | * 8-bit unsigned integer 12 | */ 13 | export const UINT8: IToken = { 14 | 15 | len: 1, 16 | 17 | get(array: Uint8Array, offset: number): number { 18 | return dv(array).getUint8(offset); 19 | }, 20 | 21 | put(array: Uint8Array, offset: number, value: number): number { 22 | dv(array).setUint8(offset, value); 23 | return offset + 1; 24 | } 25 | }; 26 | 27 | /** 28 | * 16-bit unsigned integer, Little Endian byte order 29 | */ 30 | export const UINT16_LE: IToken = { 31 | 32 | len: 2, 33 | 34 | get(array: Uint8Array, offset: number): number { 35 | return dv(array).getUint16(offset, true); 36 | }, 37 | 38 | put(array: Uint8Array, offset: number, value: number): number { 39 | dv(array).setUint16(offset, value, true); 40 | return offset + 2; 41 | } 42 | }; 43 | 44 | /** 45 | * 16-bit unsigned integer, Big Endian byte order 46 | */ 47 | export const UINT16_BE: IToken = { 48 | 49 | len: 2, 50 | 51 | get(array: Uint8Array, offset: number): number { 52 | return dv(array).getUint16(offset); 53 | }, 54 | 55 | put(array: Uint8Array, offset: number, value: number): number { 56 | dv(array).setUint16(offset, value); 57 | return offset + 2; 58 | } 59 | }; 60 | 61 | /** 62 | * 24-bit unsigned integer, Little Endian byte order 63 | */ 64 | export const UINT24_LE: IToken = { 65 | len: 3, 66 | get(array: Uint8Array, offset: number): number { 67 | const dataView = dv(array); 68 | return dataView.getUint8(offset) + (dataView.getUint16(offset + 1, true) << 8); 69 | }, 70 | put(array: Uint8Array, offset: number, value: number): number { 71 | const dataView = dv(array); 72 | dataView.setUint8(offset, value & 0xff); 73 | dataView.setUint16(offset + 1, value >> 8, true); 74 | return offset + 3; 75 | } 76 | }; 77 | 78 | /** 79 | * 24-bit unsigned integer, Big Endian byte order 80 | */ 81 | export const UINT24_BE: IToken = { 82 | len: 3, 83 | get(array: Uint8Array, offset: number): number { 84 | const dataView = dv(array); 85 | return (dataView.getUint16(offset) << 8) + dataView.getUint8(offset + 2); 86 | }, 87 | put(array: Uint8Array, offset: number, value: number): number { 88 | const dataView = dv(array); 89 | dataView.setUint16(offset, value >> 8); 90 | dataView.setUint8(offset + 2, value & 0xff); 91 | return offset + 3; 92 | } 93 | }; 94 | 95 | /** 96 | * 32-bit unsigned integer, Little Endian byte order 97 | */ 98 | export const UINT32_LE: IToken = { 99 | 100 | len: 4, 101 | 102 | get(array: Uint8Array, offset: number): number { 103 | return dv(array).getUint32(offset, true); 104 | }, 105 | 106 | put(array: Uint8Array, offset: number, value: number) { 107 | dv(array).setUint32(offset, value, true); 108 | return offset + 4; 109 | } 110 | }; 111 | 112 | /** 113 | * 32-bit unsigned integer, Big Endian byte order 114 | */ 115 | export const UINT32_BE: IToken = { 116 | 117 | len: 4, 118 | 119 | get(array: Uint8Array, offset: number): number { 120 | return dv(array).getUint32(offset); 121 | }, 122 | 123 | put(array: Uint8Array, offset: number, value: number): number { 124 | dv(array).setUint32(offset, value); 125 | return offset + 4; 126 | } 127 | }; 128 | 129 | /** 130 | * 8-bit signed integer 131 | */ 132 | export const INT8: IToken = { 133 | 134 | len: 1, 135 | 136 | get(array: Uint8Array, offset: number): number { 137 | return dv(array).getInt8(offset); 138 | }, 139 | 140 | put(array: Uint8Array, offset: number, value: number): number { 141 | dv(array).setInt8(offset, value); 142 | return offset + 1; 143 | } 144 | }; 145 | 146 | /** 147 | * 16-bit signed integer, Big Endian byte order 148 | */ 149 | export const INT16_BE: IToken = { 150 | len: 2, 151 | get(array: Uint8Array, offset: number): number { 152 | return dv(array).getInt16(offset); 153 | }, 154 | put(array: Uint8Array, offset: number, value: number): number { 155 | dv(array).setInt16(offset, value); 156 | return offset + 2; 157 | } 158 | }; 159 | 160 | /** 161 | * 16-bit signed integer, Little Endian byte order 162 | */ 163 | export const INT16_LE: IToken = { 164 | len: 2, 165 | get(array: Uint8Array, offset: number): number { 166 | return dv(array).getInt16(offset, true); 167 | }, 168 | put(array: Uint8Array, offset: number, value: number): number { 169 | dv(array).setInt16(offset, value, true); 170 | return offset + 2; 171 | } 172 | }; 173 | 174 | /** 175 | * 24-bit signed integer, Little Endian byte order 176 | */ 177 | export const INT24_LE: IToken = { 178 | len: 3, 179 | get(array: Uint8Array, offset: number): number { 180 | const unsigned = UINT24_LE.get(array, offset); 181 | return unsigned > 0x7fffff ? unsigned - 0x1000000 : unsigned; 182 | }, 183 | put(array: Uint8Array, offset: number, value: number): number { 184 | const dataView = dv(array); 185 | dataView.setUint8(offset, value & 0xff); 186 | dataView.setUint16(offset + 1, value >> 8, true); 187 | return offset + 3; 188 | } 189 | }; 190 | 191 | /** 192 | * 24-bit signed integer, Big Endian byte order 193 | */ 194 | export const INT24_BE: IToken = { 195 | len: 3, 196 | get(array: Uint8Array, offset: number): number { 197 | const unsigned = UINT24_BE.get(array, offset); 198 | return unsigned > 0x7fffff ? unsigned - 0x1000000 : unsigned; 199 | }, 200 | put(array: Uint8Array, offset: number, value: number): number { 201 | const dataView = dv(array); 202 | dataView.setUint16(offset, value >> 8); 203 | dataView.setUint8(offset + 2, value & 0xff); 204 | return offset + 3; 205 | } 206 | }; 207 | 208 | /** 209 | * 32-bit signed integer, Big Endian byte order 210 | */ 211 | export const INT32_BE: IToken = { 212 | len: 4, 213 | get(array: Uint8Array, offset: number): number { 214 | return dv(array).getInt32(offset); 215 | }, 216 | put(array: Uint8Array, offset: number, value: number): number { 217 | dv(array).setInt32(offset, value); 218 | return offset + 4; 219 | } 220 | }; 221 | 222 | /** 223 | * 32-bit signed integer, Big Endian byte order 224 | */ 225 | export const INT32_LE: IToken = { 226 | len: 4, 227 | get(array: Uint8Array, offset: number): number { 228 | return dv(array).getInt32(offset, true); 229 | }, 230 | put(array: Uint8Array, offset: number, value: number): number { 231 | dv(array).setInt32(offset, value, true); 232 | return offset + 4; 233 | } 234 | }; 235 | 236 | /** 237 | * 64-bit unsigned integer, Little Endian byte order 238 | */ 239 | export const UINT64_LE: IToken = { 240 | len: 8, 241 | get(array: Uint8Array, offset: number): bigint { 242 | return dv(array).getBigUint64(offset, true); 243 | }, 244 | put(array: Uint8Array, offset: number, value: bigint): number { 245 | dv(array).setBigUint64(offset, value, true); 246 | return offset + 8; 247 | } 248 | }; 249 | 250 | /** 251 | * 64-bit signed integer, Little Endian byte order 252 | */ 253 | export const INT64_LE: IToken = { 254 | len: 8, 255 | get(array: Uint8Array, offset: number): bigint { 256 | return dv(array).getBigInt64(offset, true); 257 | }, 258 | put(array: Uint8Array, offset: number, value: bigint): number { 259 | dv(array).setBigInt64(offset, value, true); 260 | return offset + 8; 261 | } 262 | }; 263 | 264 | /** 265 | * 64-bit unsigned integer, Big Endian byte order 266 | */ 267 | export const UINT64_BE: IToken = { 268 | len: 8, 269 | get(array: Uint8Array, offset: number): bigint { 270 | return dv(array).getBigUint64(offset); 271 | }, 272 | put(array: Uint8Array, offset: number, value: bigint): number { 273 | dv(array).setBigUint64(offset, value); 274 | return offset + 8; 275 | } 276 | }; 277 | 278 | /** 279 | * 64-bit signed integer, Big Endian byte order 280 | */ 281 | export const INT64_BE: IToken = { 282 | len: 8, 283 | get(array: Uint8Array, offset: number): bigint { 284 | return dv(array).getBigInt64(offset); 285 | }, 286 | put(array: Uint8Array, offset: number, value: bigint): number { 287 | dv(array).setBigInt64(offset, value); 288 | return offset + 8; 289 | } 290 | }; 291 | 292 | /** 293 | * IEEE 754 16-bit (half precision) float, big endian 294 | */ 295 | export const Float16_BE: IToken = { 296 | len: 2, 297 | get(dataView: Uint8Array, offset: number): number { 298 | return ieee754.read(dataView, offset, false, 10, this.len); 299 | }, 300 | put(dataView: Uint8Array, offset: number, value: number): number { 301 | ieee754.write(dataView, value, offset, false, 10, this.len); 302 | return offset + this.len; 303 | } 304 | }; 305 | 306 | /** 307 | * IEEE 754 16-bit (half precision) float, little endian 308 | */ 309 | export const Float16_LE: IToken = { 310 | len: 2, 311 | get(array: Uint8Array, offset: number): number { 312 | return ieee754.read(array, offset, true, 10, this.len); 313 | }, 314 | put(array: Uint8Array, offset: number, value: number): number { 315 | ieee754.write(array, value, offset, true, 10, this.len); 316 | return offset + this.len; 317 | } 318 | }; 319 | 320 | /** 321 | * IEEE 754 32-bit (single precision) float, big endian 322 | */ 323 | export const Float32_BE: IToken = { 324 | len: 4, 325 | get(array: Uint8Array, offset: number): number { 326 | return dv(array).getFloat32(offset); 327 | }, 328 | put(array: Uint8Array, offset: number, value: number): number { 329 | dv(array).setFloat32(offset, value); 330 | return offset + 4; 331 | } 332 | }; 333 | 334 | /** 335 | * IEEE 754 32-bit (single precision) float, little endian 336 | */ 337 | export const Float32_LE: IToken = { 338 | len: 4, 339 | get(array: Uint8Array, offset: number): number { 340 | return dv(array).getFloat32(offset, true); 341 | }, 342 | put(array: Uint8Array, offset: number, value: number): number { 343 | dv(array).setFloat32(offset, value, true); 344 | return offset + 4; 345 | } 346 | }; 347 | 348 | /** 349 | * IEEE 754 64-bit (double precision) float, big endian 350 | */ 351 | export const Float64_BE: IToken = { 352 | len: 8, 353 | get(array: Uint8Array, offset: number): number { 354 | return dv(array).getFloat64(offset); 355 | }, 356 | put(array: Uint8Array, offset: number, value: number): number { 357 | dv(array).setFloat64(offset, value); 358 | return offset + 8; 359 | } 360 | }; 361 | 362 | /** 363 | * IEEE 754 64-bit (double precision) float, little endian 364 | */ 365 | export const Float64_LE: IToken = { 366 | len: 8, 367 | get(array: Uint8Array, offset: number): number { 368 | return dv(array).getFloat64(offset, true); 369 | }, 370 | put(array: Uint8Array, offset: number, value: number): number { 371 | dv(array).setFloat64(offset, value, true); 372 | return offset + 8; 373 | } 374 | }; 375 | 376 | /** 377 | * IEEE 754 80-bit (extended precision) float, big endian 378 | */ 379 | export const Float80_BE: IToken = { 380 | len: 10, 381 | get(array: Uint8Array, offset: number): number { 382 | return ieee754.read(array, offset, false, 63, this.len); 383 | }, 384 | put(array: Uint8Array, offset: number, value: number): number { 385 | ieee754.write(array, value, offset, false, 63, this.len); 386 | return offset + this.len; 387 | } 388 | }; 389 | 390 | /** 391 | * IEEE 754 80-bit (extended precision) float, little endian 392 | */ 393 | export const Float80_LE: IToken = { 394 | len: 10, 395 | get(array: Uint8Array, offset: number): number { 396 | return ieee754.read(array, offset, true, 63, this.len); 397 | }, 398 | put(array: Uint8Array, offset: number, value: number): number { 399 | ieee754.write(array, value, offset, true, 63, this.len); 400 | return offset + this.len; 401 | } 402 | }; 403 | 404 | /** 405 | * Ignore a given number of bytes 406 | */ 407 | export class IgnoreType implements IGetToken { 408 | 409 | /** 410 | * @param len number of bytes to ignore 411 | */ 412 | constructor(public len: number) { 413 | } 414 | 415 | // ToDo: don't read, but skip data 416 | // eslint-disable-next-line @typescript-eslint/no-empty-function 417 | public get(array: Uint8Array, off: number) { 418 | } 419 | } 420 | 421 | export class Uint8ArrayType implements IGetToken { 422 | 423 | public constructor(public len: number) { 424 | } 425 | 426 | public get(array: Uint8Array, offset: number): Uint8Array { 427 | return array.subarray(offset, offset + this.len); 428 | } 429 | } 430 | 431 | /** 432 | * Consume a fixed number of bytes from the stream and return a string with a specified encoding. 433 | */ 434 | export class StringType implements IGetToken { 435 | private textDecoder: TextDecoder; 436 | 437 | public constructor(public len: number, public encoding: string) { 438 | this.textDecoder = new TextDecoder(encoding); 439 | } 440 | 441 | public get(uint8Array: Uint8Array, offset: number): string { 442 | return this.textDecoder.decode(uint8Array.subarray(offset, offset + this.len)); 443 | } 444 | } 445 | 446 | /** 447 | * ANSI Latin 1 String 448 | * Using windows-1252 / ISO 8859-1 decoding 449 | */ 450 | export class AnsiStringType implements IGetToken { 451 | private textDecoder: TextDecoder; 452 | 453 | public constructor(public len: number) { 454 | this.textDecoder = new TextDecoder('windows-1252'); 455 | } 456 | 457 | public get(uint8Array: Uint8Array, offset: number = 0): string { 458 | return this.textDecoder.decode(uint8Array.subarray(offset, offset + this.len)); 459 | } 460 | } 461 | -------------------------------------------------------------------------------- /lib/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": true 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "token-types", 3 | "version": "6.0.0", 4 | "description": "Common token types for decoding and encoding numeric and string values", 5 | "author": { 6 | "name": "Borewit", 7 | "url": "https://github.com/Borewit" 8 | }, 9 | "funding": { 10 | "type": "github", 11 | "url": "https://github.com/sponsors/Borewit" 12 | }, 13 | "scripts": { 14 | "clean": "del-cli lib/**/*.js lib/***.js.map *.d.ts test/**/*.d.ts test/**/*.js test/**/*.js.map .nyc_output", 15 | "build": "npm run compile", 16 | "compile-src": "tsc --p lib", 17 | "compile-test": "tsc --p test", 18 | "compile": "npm run compile-src && npm run compile-test", 19 | "eslint": "eslint lib/**/*.ts --ignore-pattern lib/**/*.d.ts test/**/*.ts", 20 | "lint-ts": "tslint lib/index.ts --exclude '*.d.ts' 'test/**/*.ts' --exclude 'test/**/*.d.ts,lib/**/*.d.ts'", 21 | "lint-md": "remark -u preset-lint-recommended .", 22 | "lint": "npm run lint-md && npm run eslint", 23 | "test": "mocha", 24 | "test-coverage": "c8 npm run test", 25 | "send-codacy": "c8 report --reports-dir=./.coverage --reporter=text-lcov | codacy-coverage" 26 | }, 27 | "engines": { 28 | "node": ">=14.16" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "https://github.com/Borewit/token-types" 33 | }, 34 | "files": [ 35 | "lib/index.js", 36 | "lib/index.d.ts" 37 | ], 38 | "license": "MIT", 39 | "type": "module", 40 | "exports": "./lib/index.js", 41 | "types": "lib/index.d.ts", 42 | "bugs": { 43 | "url": "https://github.com/Borewit/token-types/issues" 44 | }, 45 | "devDependencies": { 46 | "@types/chai": "^4.3.1", 47 | "@types/mocha": "^10.0.0", 48 | "@types/node": "^20.14.9", 49 | "@typescript-eslint/eslint-plugin": "^7.15.0", 50 | "@typescript-eslint/parser": "^7.14.1", 51 | "c8": "^10.1.2", 52 | "chai": "^5.1.1", 53 | "del-cli": "^5.0.0", 54 | "eslint": "^8.57.0", 55 | "eslint-config-prettier": "^9.0.0", 56 | "eslint-import-resolver-typescript": "^3.6.1", 57 | "eslint-plugin-import": "^2.29.0", 58 | "eslint-plugin-jsdoc": "^48.5.2", 59 | "eslint-plugin-node": "^11.1.0", 60 | "eslint-plugin-unicorn": "^54.0.0", 61 | "mocha": "^10.6.0", 62 | "remark-cli": "^12.0.1", 63 | "remark-preset-lint-recommended": "^7.0.0", 64 | "source-map-support": "^0.5.21", 65 | "ts-node": "^10.9.1", 66 | "typescript": "^5.5.3" 67 | }, 68 | "dependencies": { 69 | "@tokenizer/token": "^0.3.0", 70 | "ieee754": "^1.2.1" 71 | }, 72 | "remarkConfig": { 73 | "plugins": [ 74 | "preset-lint-recommended" 75 | ] 76 | }, 77 | "keywords": [ 78 | "token", 79 | "integer", 80 | "unsigned", 81 | "numeric", 82 | "float", 83 | "IEEE", 84 | "754", 85 | "strtok3" 86 | ] 87 | } 88 | -------------------------------------------------------------------------------- /test/test-classes.ts: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import { StringType, Uint8ArrayType } from '../lib/index.js'; 3 | 4 | describe('Uint8ArrayType', () => { 5 | 6 | it('should should not copy data fom the source array', () => { 7 | 8 | const source = Uint8Array.from([0xa1, 0xa2, 0xb1, 0xb2, 0xc1, 0xc2]); 9 | 10 | const uint8ArrayType = new Uint8ArrayType(2); 11 | const bufferResult = uint8ArrayType.get(source, 2); 12 | 13 | assert.deepStrictEqual(bufferResult, Uint8Array.from([0xb1, 0xb2]), 'should be 2 middle bytes: 0xb1, 0xb2'); 14 | 15 | // Overwrite the result 16 | bufferResult[0] = 0xd1; 17 | bufferResult[1] = 0xd2; 18 | 19 | assert.deepStrictEqual(source, Uint8Array.from([0xa1, 0xa2, 0xd1, 0xd2, 0xc1, 0xc2]), 'should not copy the data'); 20 | }); 21 | }); 22 | 23 | describe('StringType', () => { 24 | 25 | it('decode from Buffer', () => { 26 | 27 | const source = new Uint8Array(Buffer.from('peter', 'utf8')); 28 | 29 | const stringType = new StringType(5, 'utf8'); 30 | 31 | assert.strictEqual(stringType.get(source, 0), 'peter', 'should be 2 middle bytes: 0xb1, 0xb2'); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/test-ieee-754-floats.ts: -------------------------------------------------------------------------------- 1 | // Test writing and reading uint8 values. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('IEEE 754 floats', () => { 8 | 9 | describe('16-bit (half precision)', () => { 10 | 11 | describe('big-endian', () => { 12 | 13 | it('should encode', () => { 14 | 15 | const buf = new Uint8Array(2); 16 | 17 | Token.Float16_BE.put(buf, 0, 0.0); 18 | util.checkBuffer(buf, '0000'); 19 | 20 | Token.Float16_BE.put(buf, 0, 85.125); 21 | util.checkBuffer(buf, '5552'); 22 | 23 | Token.Float16_BE.put(buf, 0, -1); 24 | util.checkBuffer(buf, 'bc00'); 25 | }); 26 | 27 | it('should decode', () => { 28 | const buf = new Uint8Array([0x55, 0x52]); 29 | assert.strictEqual(Token.Float16_BE.get(buf, 0), 85.125); 30 | }); 31 | 32 | }); 33 | 34 | describe('little-endian', () => { 35 | 36 | it('should encode', () => { 37 | 38 | const buf = new Uint8Array(2); 39 | 40 | Token.Float16_LE.put(buf, 0, 0.0); 41 | util.checkBuffer(buf, '0000'); 42 | 43 | Token.Float16_LE.put(buf, 0, 85.125); 44 | util.checkBuffer(buf, '5255'); 45 | 46 | Token.Float16_LE.put(buf, 0, -1); 47 | util.checkBuffer(buf, '00bc'); 48 | }); 49 | 50 | it('should decode', () => { 51 | const buf = new Uint8Array([0x52, 0x55]); 52 | assert.strictEqual(Token.Float16_LE.get(buf, 0), 85.125); 53 | }); 54 | 55 | }); 56 | }); 57 | 58 | describe('32-bit (single precision)', () => { 59 | 60 | describe('big-endian', () => { 61 | 62 | it('should encode', () => { 63 | 64 | const buffer = new Uint8Array(4); 65 | 66 | Token.Float32_BE.put(buffer, 0, 0.0); 67 | util.checkBuffer(buffer, '00000000'); 68 | 69 | Token.Float32_BE.put(buffer, 0, 85.125); 70 | util.checkBuffer(buffer, '42aa4000'); 71 | 72 | Token.Float32_BE.put(buffer, 0, -1); 73 | util.checkBuffer(buffer, 'bf800000'); 74 | }); 75 | 76 | it('should decode', () => { 77 | const buf = new Uint8Array([0x42, 0xAA, 0x40, 0x00]); 78 | assert.strictEqual(Token.Float32_BE.get(buf, 0), 85.125); 79 | }); 80 | 81 | }); 82 | 83 | describe('little-endian', () => { 84 | 85 | it('should encode', () => { 86 | 87 | const buf = new Uint8Array(4); 88 | 89 | Token.Float32_LE.put(buf, 0, 0.0); 90 | util.checkBuffer(buf, '00000000'); 91 | 92 | Token.Float32_LE.put(buf, 0, 85.125); 93 | util.checkBuffer(buf, '0040aa42'); 94 | 95 | Token.Float32_LE.put(buf, 0, -1); 96 | util.checkBuffer(buf, '000080bf'); 97 | }); 98 | 99 | it('should decode', () => { 100 | const buf = new Uint8Array([0x00, 0x40, 0xAA, 0x42]); 101 | assert.strictEqual(Token.Float32_LE.get(buf, 0), 85.125); 102 | }); 103 | 104 | }); 105 | }); 106 | 107 | describe('64-bit (double precision)', () => { 108 | 109 | describe('big-endian', () => { 110 | 111 | it('should encode', () => { 112 | 113 | const buf = new Uint8Array(8); 114 | 115 | Token.Float64_BE.put(buf, 0, 0.0); 116 | util.checkBuffer(buf, '0000000000000000'); 117 | 118 | Token.Float64_BE.put(buf, 0, 85.125); 119 | util.checkBuffer(buf, '4055480000000000'); 120 | 121 | Token.Float64_BE.put(buf, 0, -1); 122 | util.checkBuffer(buf, 'bff0000000000000'); 123 | }); 124 | 125 | it('should decode', () => { 126 | const buf = new Uint8Array([0x40, 0x55, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00]); 127 | assert.strictEqual(Token.Float64_BE.get(buf, 0), 85.125); 128 | }); 129 | 130 | }); 131 | 132 | describe('little-endian', () => { 133 | 134 | it('should encode', () => { 135 | 136 | const buf = new Uint8Array(8); 137 | 138 | Token.Float64_LE.put(buf, 0, 0.0); 139 | util.checkBuffer(buf, '0000000000000000'); 140 | 141 | Token.Float64_LE.put(buf, 0, 85.125); 142 | util.checkBuffer(buf, '0000000000485540'); 143 | 144 | Token.Float64_LE.put(buf, 0, -1); 145 | util.checkBuffer(buf, '000000000000f0bf'); 146 | }); 147 | 148 | it('should decode', () => { 149 | const buf = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x55, 0x40]); 150 | assert.strictEqual(Token.Float64_LE.get(buf, 0), 85.125); 151 | }); 152 | 153 | }); 154 | }); 155 | 156 | describe('80-bit (extended precision)', () => { 157 | 158 | describe('big-endian', () => { 159 | 160 | it('should encode', () => { 161 | 162 | const buf = new Uint8Array(10); 163 | 164 | Token.Float80_BE.put(buf, 0, 0.0); 165 | util.checkBuffer(buf, '00000000000000000000'); 166 | 167 | Token.Float80_BE.put(buf, 0, 85.125); 168 | util.checkBuffer(buf, '4002aa40000000000000'); 169 | 170 | Token.Float80_BE.put(buf, 0, -1); 171 | util.checkBuffer(buf, 'bfff8000000000000000'); 172 | }); 173 | 174 | it('should decode', () => { 175 | const buf = new Uint8Array([0x40, 0x02, 0xAA, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); 176 | assert.strictEqual(Token.Float80_BE.get(buf, 0), 85.125); 177 | }); 178 | 179 | }); 180 | 181 | describe('little-endian', () => { 182 | 183 | it('should encode', () => { 184 | 185 | const buf = new Uint8Array(10); 186 | 187 | Token.Float80_LE.put(buf, 0, 0.0); 188 | util.checkBuffer(buf, '00000000000000000000'); 189 | 190 | Token.Float80_LE.put(buf, 0, 85.125); 191 | util.checkBuffer(buf, '00000000000040aa0240'); 192 | 193 | Token.Float80_LE.put(buf, 0, -1); 194 | util.checkBuffer(buf, '0000000000000080ffbf'); 195 | }); 196 | 197 | it.skip('should decode', () => { 198 | const buf = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xAA, 0x02, 0x40]); 199 | assert.strictEqual(Token.Float80_LE.get(buf, 0), 85.125); 200 | }); 201 | 202 | }); 203 | }); 204 | 205 | }); 206 | -------------------------------------------------------------------------------- /test/test-int16.ts: -------------------------------------------------------------------------------- 1 | // Test reading int16 values. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 16-bit signed integer', () => { 8 | 9 | describe('big-endian', () => { 10 | 11 | it('should encode', () => { 12 | 13 | const buf = new Uint8Array(2); 14 | 15 | Token.INT16_BE.put(buf, 0, 0x00); 16 | util.checkBuffer(buf, '0000'); 17 | 18 | Token.INT16_BE.put(buf, 0, 0x0f0b); 19 | util.checkBuffer(buf, '0f0b'); 20 | 21 | Token.INT16_BE.put(buf, 0, -0x0f0b); 22 | util.checkBuffer(buf, 'f0f5'); 23 | }); 24 | 25 | it('should decode', () => { 26 | 27 | const buf = new Uint8Array([0x0a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00]); 28 | 29 | assert.equal(Token.INT16_BE.get(buf, 0), 2586); 30 | assert.equal(Token.INT16_BE.get(buf, 2), 0); 31 | assert.equal(Token.INT16_BE.get(buf, 4), -1); 32 | assert.equal(Token.INT16_BE.get(buf, 6), -32768); 33 | 34 | }); 35 | }); 36 | 37 | describe('little-endian', () => { 38 | 39 | it('should encode', () => { 40 | 41 | const buf = new Uint8Array(2); 42 | 43 | Token.INT16_LE.put(buf, 0, 0x00); 44 | util.checkBuffer(buf, '0000'); 45 | 46 | Token.INT16_LE.put(buf, 0, 0x0f0b); 47 | util.checkBuffer(buf, '0b0f'); 48 | 49 | Token.INT16_LE.put(buf, 0, -0x0f0b); 50 | util.checkBuffer(buf, 'f5f0'); 51 | }); 52 | 53 | it('should decode', () => { 54 | 55 | const buf = new Uint8Array([0x1a, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x80]); 56 | 57 | assert.equal(Token.INT16_LE.get(buf, 0), 2586); 58 | assert.equal(Token.INT16_LE.get(buf, 2), 0); 59 | assert.equal(Token.INT16_LE.get(buf, 4), -1); 60 | assert.equal(Token.INT16_LE.get(buf, 6), -32768); 61 | 62 | }); 63 | }); 64 | 65 | }); 66 | -------------------------------------------------------------------------------- /test/test-int24.ts: -------------------------------------------------------------------------------- 1 | // Test reading int24 values. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 24-bit signed integer', () => { 8 | 9 | describe('little-endian', () => { 10 | 11 | it('should encode', () => { 12 | 13 | const buf = new Uint8Array(3); 14 | 15 | Token.INT24_LE.put(buf, 0, 0x00); 16 | util.checkBuffer(buf, '000000'); 17 | 18 | Token.INT24_LE.put(buf, 0, 0x0f0ba0); 19 | util.checkBuffer(buf, 'a00b0f'); 20 | 21 | Token.INT24_LE.put(buf, 0, -0x0f0bcc); 22 | util.checkBuffer(buf, '34f4f0'); 23 | }); 24 | 25 | it('should decode', () => { 26 | 27 | const buf = new Uint8Array([0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0x00, 0x00, 0x80]); 28 | 29 | assert.equal(Token.INT24_LE.get(buf, 0), 0); 30 | assert.equal(Token.INT24_LE.get(buf, 3), -1); 31 | assert.equal(Token.INT24_LE.get(buf, 6), 1048831); 32 | assert.equal(Token.INT24_LE.get(buf, 9), -8388608); 33 | 34 | }); 35 | }); 36 | 37 | describe('big-endian', () => { 38 | 39 | it('should encode', () => { 40 | 41 | const buf = new Uint8Array(3); 42 | 43 | Token.INT24_BE.put(buf, 0, 0x00); 44 | util.checkBuffer(buf, '000000'); 45 | 46 | Token.INT24_BE.put(buf, 0, 0x0f0ba0); 47 | util.checkBuffer(buf, '0f0ba0'); 48 | 49 | Token.INT24_BE.put(buf, 0, -0x0f0bcc); 50 | util.checkBuffer(buf, 'f0f434'); 51 | }); 52 | 53 | it('should decode', () => { 54 | 55 | const buf = new Uint8Array([0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x10, 0x00, 0xff, 0x80, 0x00, 0x00]); 56 | 57 | assert.equal(Token.INT24_BE.get(buf, 0), 0); 58 | assert.equal(Token.INT24_BE.get(buf, 3), -1); 59 | assert.equal(Token.INT24_BE.get(buf, 6), 1048831); 60 | assert.equal(Token.INT24_BE.get(buf, 9), -8388608); 61 | 62 | }); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/test-int32.ts: -------------------------------------------------------------------------------- 1 | // Test reading int32 values. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 32-bit signed integer', () => { 8 | 9 | describe('big-endian', () => { 10 | 11 | it('should encode', () => { 12 | 13 | const buf = new Uint8Array(4); 14 | 15 | Token.INT32_BE.put(buf, 0, 0x00); 16 | util.checkBuffer(buf, '00000000'); 17 | 18 | Token.INT32_BE.put(buf, 0, 0x0f0bcca0); 19 | util.checkBuffer(buf, '0f0bcca0'); 20 | 21 | Token.INT32_BE.put(buf, 0, -1); 22 | util.checkBuffer(buf, 'ffffffff'); 23 | 24 | Token.INT32_BE.put(buf, 0, -0x0f0bcca0); 25 | util.checkBuffer(buf, 'f0f43360'); 26 | }); 27 | 28 | it('should decode', () => { 29 | 30 | let buf = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); 31 | assert.equal(Token.INT32_BE.get(buf, 0), 0); 32 | assert.equal(Token.INT32_BE.get(buf, 4), -1); 33 | 34 | buf = new Uint8Array([0x00, 0x10, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00]); 35 | assert.equal(Token.INT32_BE.get(buf, 0), 1048831); 36 | assert.equal(Token.INT32_BE.get(buf, 4), -2147483648); 37 | 38 | }); 39 | 40 | }); 41 | 42 | describe('little-endian', () => { 43 | 44 | it('should encode', () => { 45 | 46 | const buf = new Uint8Array(4); 47 | 48 | Token.INT32_LE.put(buf, 0, 0x00); 49 | util.checkBuffer(buf, '00000000'); 50 | 51 | Token.INT32_LE.put(buf, 0, 0x0f0bcca0); 52 | util.checkBuffer(buf, 'a0cc0b0f'); 53 | 54 | Token.INT32_LE.put(buf, 0, -1); 55 | util.checkBuffer(buf, 'ffffffff'); 56 | 57 | Token.INT32_LE.put(buf, 0, -0x0f0bcca0); 58 | util.checkBuffer(buf, '6033f4f0'); 59 | }); 60 | 61 | it('should decode', () => { 62 | 63 | let buf = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]); 64 | 65 | assert.equal(Token.INT32_LE.get(buf, 0), 0); 66 | assert.equal(Token.INT32_LE.get(buf, 4), -1); 67 | 68 | buf = new Uint8Array([0xff, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x80]); 69 | assert.equal(Token.INT32_LE.get(buf, 0), 1048831); 70 | assert.equal(Token.INT32_LE.get(buf, 4), -2147483648); 71 | 72 | }); 73 | 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /test/test-int64.ts: -------------------------------------------------------------------------------- 1 | // Test reading int64 values. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 64-bit signed integer', () => { 8 | 9 | describe('big-endian', () => { 10 | 11 | it('should encode', () => { 12 | 13 | const buf = new Uint8Array(8); 14 | 15 | Token.INT64_BE.put(buf, 0, BigInt(0x01)); 16 | util.checkBuffer(buf, '0000000000000001'); 17 | 18 | Token.INT64_BE.put(buf, 0, BigInt(0x0000ffbbeeddccaa)); 19 | util.checkBuffer(buf, '0000ffbbeeddccaa'); 20 | 21 | Token.INT64_BE.put(buf, 0, BigInt(-1)); 22 | util.checkBuffer(buf, 'ffffffffffffffff'); 23 | }); 24 | 25 | it('should decode', () => { 26 | 27 | assert.strictEqual(Token.INT64_BE.get(new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), 0), BigInt(0)); 28 | assert.strictEqual(Token.INT64_BE.get(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), 0), BigInt(-1)); 29 | 30 | }); 31 | 32 | }); 33 | 34 | describe('little-endian', () => { 35 | 36 | it('should encode', () => { 37 | 38 | const buf = new Uint8Array(8); 39 | 40 | Token.INT64_LE.put(buf, 0, BigInt(0x00)); 41 | util.checkBuffer(buf, '0000000000000000'); 42 | 43 | Token.INT64_LE.put(buf, 0, BigInt(0x0000ffbbeeddccaa)); 44 | util.checkBuffer(buf, 'aaccddeebbff0000'); 45 | 46 | Token.INT64_LE.put(buf, 0, BigInt(-1)); 47 | util.checkBuffer(buf, 'ffffffffffffffff'); 48 | }); 49 | 50 | it('should decode', () => { 51 | 52 | let buf = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); 53 | 54 | assert.strictEqual(Token.INT64_LE.get(buf, 0), BigInt(0)); 55 | assert.strictEqual(Token.INT64_LE.get(buf, 8), BigInt(-1)); 56 | 57 | buf = new Uint8Array([0xaa, 0xcc, 0xdd, 0xee, 0xbb, 0xff, 0x00, 0x00, 0xbb, 0xcc, 0xdd, 0xee, 0xbb, 0xff, 0x00, 0x00]); 58 | assert.strictEqual(Token.INT64_LE.get(buf, 0), BigInt(0x0000ffbbeeddccaa)); 59 | assert.strictEqual(Token.INT64_LE.get(buf, 8), BigInt(0x0000ffbbeeddccbb)); 60 | 61 | }); 62 | 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/test-int8.ts: -------------------------------------------------------------------------------- 1 | // Test reading int8 values. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 8-bit signed integer (INT8)', () => { 8 | 9 | it('should encode', () => { 10 | 11 | const buf = new Uint8Array(1); 12 | 13 | Token.INT8.put(buf, 0, 0x00); 14 | util.checkBuffer(buf, '00'); 15 | 16 | Token.INT8.put(buf, 0, 0x22); 17 | util.checkBuffer(buf, '22'); 18 | 19 | Token.INT8.put(buf, 0, -0x22); 20 | util.checkBuffer(buf, 'de'); 21 | }); 22 | 23 | it('should decode', () => { 24 | 25 | const buf = new Uint8Array([0x00, 0x7f, 0x80, 0xff, 0x81]); 26 | 27 | assert.strictEqual(Token.INT8.get(buf, 0), 0); 28 | assert.strictEqual(Token.INT8.get(buf, 1), 127); 29 | assert.strictEqual(Token.INT8.get(buf, 2), -128); 30 | assert.strictEqual(Token.INT8.get(buf, 3), -1); 31 | assert.strictEqual(Token.INT8.get(buf, 4), -127); 32 | 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/test-iso-8859-1.ts: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import { AnsiStringType } from '../lib/index.js'; 3 | 4 | /* eslint-disable max-len */ 5 | 6 | describe('Decode ANSI-string (ISO-8859-1)', () => { 7 | 8 | function decode(uint8Array: Uint8Array): string { 9 | const ansiStr = new AnsiStringType(uint8Array.length); 10 | return ansiStr.get(uint8Array); 11 | } 12 | 13 | it('should decode', () => { 14 | assert.equal( 15 | decode(new Uint8Array(new Array(128).fill(0).map((_, index) => index))), 16 | '\0\x01\x02\x03\x04\x05\x06\x07\b\t\n\x0B\f\r\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7F', 17 | 'U+0000 to U+007F remain unchanged' 18 | ); 19 | assert.equal( 20 | decode(new Uint8Array(new Array(128).fill(0).map((_, index) => index + 128))), 21 | '\u20AC\x81\u201A\u0192\u201E\u2026\u2020\u2021\u02C6\u2030\u0160\u2039\u0152\x8D\u017D\x8F\x90\u2018\u2019\u201C\u201D\u2022\u2013\u2014\u02DC\u2122\u0161\u203A\u0153\x9D\u017E\u0178\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF', 22 | 'Decoding all other symbols in the character set' 23 | ); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/test-uint16.ts: -------------------------------------------------------------------------------- 1 | // Test writing and reading uint16 values in different endiannesses. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 16-bit unsigned integer', () => { 8 | 9 | describe('combined little- and big-endian', () => { 10 | 11 | it('should encode', () => { 12 | 13 | const buf = new Uint8Array(4); 14 | 15 | Token.UINT16_LE.put(buf, 0, 0x00); 16 | Token.UINT16_LE.put(buf, 2, 0xffaa); 17 | util.checkBuffer(buf, '0000aaff'); 18 | 19 | Token.UINT16_BE.put(buf, 0, 0x00); 20 | Token.UINT16_BE.put(buf, 2, 0xffaa); 21 | util.checkBuffer(buf, '0000ffaa'); 22 | 23 | Token.UINT16_BE.put(buf, 0, 0xffaa); 24 | Token.UINT16_LE.put(buf, 2, 0xffaa); 25 | util.checkBuffer(buf, 'ffaaaaff'); 26 | }); 27 | 28 | it('should decode', () => { 29 | 30 | const buf = new Uint8Array([0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00]); 31 | 32 | assert.equal(Token.UINT16_LE.get(buf, 0), 0x001a); 33 | assert.equal(Token.UINT16_BE.get(buf, 2), 0x1a00); 34 | assert.equal(Token.UINT16_LE.get(buf, 4), 0x001a); 35 | assert.equal(Token.UINT16_BE.get(buf, 6), 0x1a00); 36 | 37 | }); 38 | 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/test-uint24.ts: -------------------------------------------------------------------------------- 1 | // Test writing and reading uint24 values in different endiannesses. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 24-bit unsigned integer', () => { 8 | 9 | describe('big-endian', () => { 10 | 11 | it('should encode', () => { 12 | 13 | const buf = new Uint8Array(3); 14 | 15 | Token.UINT24_BE.put(buf, 0, 0x00); 16 | util.checkBuffer(buf, '000000'); 17 | 18 | Token.UINT24_BE.put(buf, 0, 0xff); 19 | util.checkBuffer(buf, '0000ff'); 20 | 21 | Token.UINT24_BE.put(buf, 0, 0xaabbcc); 22 | util.checkBuffer(buf, 'aabbcc'); 23 | }); 24 | 25 | it('should decode', () => { 26 | 27 | const buf = new Uint8Array([0x00, 0x00, 0x00, 0x1a, 0x1a, 0x00, 0xff, 0xff, 0xff]); 28 | assert.strictEqual(Token.UINT24_BE.get(buf, 0), 0x000000); 29 | assert.strictEqual(Token.UINT24_BE.get(buf, 3), 0x1a1a00); 30 | assert.strictEqual(Token.UINT24_BE.get(buf, 6), 0xffffff); 31 | }); 32 | 33 | }); 34 | 35 | describe('little-endian', () => { 36 | 37 | it('should encode', () => { 38 | 39 | const buf = new Uint8Array(3); 40 | 41 | Token.UINT24_LE.put(buf, 0, 0x00); 42 | util.checkBuffer(buf, '000000'); 43 | 44 | Token.UINT24_LE.put(buf, 0, 0xff); 45 | util.checkBuffer(buf, 'ff0000'); 46 | 47 | Token.UINT24_LE.put(buf, 0, 0xaabbcc); 48 | util.checkBuffer(buf, 'ccbbaa'); 49 | }); 50 | 51 | it('should decode', () => { 52 | 53 | const buf = new Uint8Array([0x00, 0x00, 0x00, 0x1a, 0x1a, 0x00, 0xff, 0xff, 0xff]); 54 | 55 | assert.strictEqual(Token.UINT24_LE.get(buf, 0), 0x000000); 56 | assert.strictEqual(Token.UINT24_LE.get(buf, 3), 0x001a1a); 57 | assert.strictEqual(Token.UINT24_LE.get(buf, 6), 0xffffff); 58 | }); 59 | 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /test/test-uint32.ts: -------------------------------------------------------------------------------- 1 | // Test writing and reading uint32 values in different endiannesses. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 32-bit unsigned integer', () => { 8 | 9 | const decbuf = new Uint8Array([0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00]); 10 | 11 | describe('big-endian', () => { 12 | 13 | it('should encode', () => { 14 | const buf = new Uint8Array(4); 15 | 16 | Token.UINT32_BE.put(buf, 0, 0x00); 17 | util.checkBuffer(buf, '00000000'); 18 | 19 | Token.UINT32_BE.put(buf, 0, 0xff); 20 | util.checkBuffer(buf, '000000ff'); 21 | 22 | Token.UINT32_BE.put(buf, 0, 0xaabbccdd); 23 | util.checkBuffer(buf, 'aabbccdd'); 24 | }); 25 | 26 | it('should decode', () => { 27 | assert.equal(Token.UINT32_BE.get(decbuf, 4), 0x1a001a00); 28 | assert.equal(Token.UINT32_BE.get(decbuf, 12), 0x1a001a00); 29 | }); 30 | }); 31 | 32 | describe('little-endian', () => { 33 | 34 | it('should encode', () => { 35 | const buf = new Uint8Array(4); 36 | 37 | Token.UINT32_LE.put(buf, 0, 0x00); 38 | util.checkBuffer(buf, '00000000'); 39 | 40 | Token.UINT32_LE.put(buf, 0, 0xff); 41 | util.checkBuffer(buf, 'ff000000'); 42 | 43 | Token.UINT32_LE.put(buf, 0, 0xaabbccdd); 44 | util.checkBuffer(buf, 'ddccbbaa'); 45 | }); 46 | 47 | it('should decode', () => { 48 | assert.equal(Token.UINT32_LE.get(decbuf, 0), 0x001a001a); 49 | assert.equal(Token.UINT32_LE.get(decbuf, 8), 0x001a001a); 50 | }); 51 | }); 52 | 53 | describe('should decode', () => { 54 | 55 | it('big-endian', () => { 56 | assert.equal(Token.UINT32_BE.get(decbuf, 4), 0x1a001a00); 57 | assert.equal(Token.UINT32_BE.get(decbuf, 12), 0x1a001a00); 58 | }); 59 | 60 | it('little-endian', () => { 61 | assert.equal(Token.UINT32_LE.get(decbuf, 0), 0x001a001a); 62 | assert.equal(Token.UINT32_LE.get(decbuf, 8), 0x001a001a); 63 | }); 64 | }); 65 | 66 | }); 67 | -------------------------------------------------------------------------------- /test/test-uint64.ts: -------------------------------------------------------------------------------- 1 | // Test writing and reading uint32 values in different endiannesses. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 64-bit unsigned integer', () => { 8 | 9 | describe('big-endian', () => { 10 | 11 | it('should encode', () => { 12 | 13 | const buf = new Uint8Array(8); 14 | 15 | Token.UINT64_BE.put(buf, 0, BigInt(0x00)); 16 | util.checkBuffer(buf, '0000000000000000'); 17 | 18 | Token.UINT64_BE.put(buf, 0, BigInt(0xff)); 19 | util.checkBuffer(buf, '00000000000000ff'); 20 | 21 | Token.UINT64_BE.put(buf, 0, BigInt(0xaabbccddeeff)); 22 | util.checkBuffer(buf, '0000aabbccddeeff'); 23 | 24 | Token.UINT64_BE.put(buf, 0, BigInt(0x00123456789ABCDE)); 25 | util.checkBuffer(buf, '00123456789abcde'); 26 | }); 27 | 28 | it('should decode', () => { 29 | const buf = new Uint8Array([0x00, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x02]); 30 | 31 | assert.strictEqual(Token.UINT64_BE.get(buf, 0), BigInt(0x00001a001a001a01)); 32 | assert.strictEqual(Token.UINT64_BE.get(buf, 8), BigInt(0x00001a001a001a02)); 33 | }); 34 | 35 | }); 36 | 37 | describe('litle-endian', () => { 38 | 39 | it('should encode', () => { 40 | const buf = new Uint8Array(8); 41 | 42 | Token.UINT64_LE.put(buf, 0, BigInt(0x00)); 43 | util.checkBuffer(buf, '0000000000000000'); 44 | 45 | Token.UINT64_LE.put(buf, 0, BigInt(0xff)); 46 | util.checkBuffer(buf, 'ff00000000000000'); 47 | 48 | Token.UINT64_LE.put(buf, 0, BigInt(0xaabbccddeeff)); 49 | util.checkBuffer(buf, 'ffeeddccbbaa0000'); 50 | 51 | Token.UINT64_LE.put(buf, 0, BigInt(0x00123456789ABCDE)); 52 | util.checkBuffer(buf, 'debc9a7856341200'); 53 | }); 54 | 55 | it('should decode', () => { 56 | 57 | const buf = new Uint8Array([0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x00]); 58 | 59 | it('little-endian', () => { 60 | assert.strictEqual(Token.UINT64_LE.get(buf, 0), BigInt(0x001a001a)); 61 | assert.strictEqual(Token.UINT64_LE.get(buf, 8), BigInt(0x001a001a)); 62 | }); 63 | 64 | }); 65 | 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /test/test-uint8.ts: -------------------------------------------------------------------------------- 1 | // Test writing and reading uint8 values. 2 | 3 | import { assert } from 'chai'; 4 | import * as Token from '../lib/index.js'; 5 | import * as util from './util.js'; 6 | 7 | describe('Parse 8-bit unsigned integer (UINT8)', () => { 8 | 9 | it('should encode', () => { 10 | 11 | const buf = new Uint8Array(1); 12 | 13 | Token.UINT8.put(buf, 0, 0x00); 14 | util.checkBuffer(buf, '00'); 15 | 16 | Token.UINT8.put(buf, 0, 0x22); 17 | util.checkBuffer(buf, '22'); 18 | 19 | Token.UINT8.put(buf, 0, 0xff); 20 | util.checkBuffer(buf, 'ff'); 21 | }); 22 | 23 | it('should decode', () => { 24 | 25 | const buf = new Uint8Array([0x00, 0x1a, 0x01, 0xff]); 26 | 27 | assert.equal(Token.UINT8.get(buf, 0), 0); 28 | assert.equal(Token.UINT8.get(buf, 1), 26); 29 | assert.equal(Token.UINT8.get(buf, 2), 1); 30 | assert.equal(Token.UINT8.get(buf, 3), 255); 31 | 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json" 3 | } 4 | 5 | -------------------------------------------------------------------------------- /test/util.ts: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | export const checkBuffer = (uint8Array: Uint8Array, hexStr: string) => { 4 | assert.equal(Buffer.from(uint8Array).toString('hex'), hexStr); 5 | }; 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "skipLibCheck": true, 4 | "inlineSources": false, 5 | "module": "node16", 6 | "moduleResolution": "node16", 7 | "target": "ES2019", 8 | "esModuleInterop": true, 9 | "strict": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:latest", 3 | "rules": { 4 | "curly": false, 5 | "max-classes-per-file": [false], 6 | "semicolon": [true, "always", "ignore-interfaces"], 7 | "quotemark": [false, "double", "avoid-escape"], 8 | "no-bitwise": false, 9 | "trailing-comma": [true, {"multiline": "never", "singleline": "never"}], 10 | "object-literal-key-quotes": [true, "as-needed"], 11 | "variable-name": [true, "ban-keywords"], 12 | "object-literal-sort-keys": [false], 13 | "max-line-length": false, 14 | "switch-default": false, 15 | "prefer-for-of": false, 16 | "ordered-imports": false, 17 | "forin": false, 18 | "no-implicit-dependencies": false, 19 | "no-conditional-assignment": false, 20 | "no-empty": [true, "allow-empty-functions"], 21 | "no-submodule-imports": [true, "strtok3"] 22 | }, 23 | "jsRules": { 24 | "curly": false 25 | }, 26 | "rulesDirectory": [ 27 | ] 28 | } 29 | --------------------------------------------------------------------------------