├── .eslintrc.json
├── .github
├── dependabot.yml
└── workflows
│ └── npm-publish.yml
├── .gitignore
├── .npmignore
├── .remembrance.json
├── CDN.md
├── LICENSE
├── README.md
├── cjs
├── base-ex.cjs
└── base-ex.cjs.map
├── dist
├── base-ex.esm.js
├── base-ex.esm.min.js
├── base-ex.iife.js
├── base-ex.iife.min.js
└── converters
│ ├── Base1
│ ├── base-1.esm.js
│ ├── base-1.esm.min.js
│ ├── base-1.iife.js
│ └── base-1.iife.min.js
│ ├── Base16
│ ├── base-16.esm.js
│ ├── base-16.esm.min.js
│ ├── base-16.iife.js
│ └── base-16.iife.min.js
│ ├── Base2048
│ ├── base-2048.esm.js
│ ├── base-2048.esm.min.js
│ ├── base-2048.iife.js
│ └── base-2048.iife.min.js
│ ├── Base32
│ ├── base-32.esm.js
│ ├── base-32.esm.min.js
│ ├── base-32.iife.js
│ └── base-32.iife.min.js
│ ├── Base58
│ ├── base-58.esm.js
│ ├── base-58.esm.min.js
│ ├── base-58.iife.js
│ └── base-58.iife.min.js
│ ├── Base64
│ ├── base-64.esm.js
│ ├── base-64.esm.min.js
│ ├── base-64.iife.js
│ └── base-64.iife.min.js
│ ├── Base85
│ ├── base-85.esm.js
│ ├── base-85.esm.min.js
│ ├── base-85.iife.js
│ └── base-85.iife.min.js
│ ├── Base91
│ ├── base-91.esm.js
│ ├── base-91.esm.min.js
│ ├── base-91.iife.js
│ └── base-91.iife.min.js
│ ├── BasePhi
│ ├── base-phi.esm.js
│ ├── base-phi.esm.min.js
│ ├── base-phi.iife.js
│ └── base-phi.iife.min.js
│ ├── ByteConverter
│ ├── byte-converter.esm.js
│ ├── byte-converter.esm.min.js
│ ├── byte-converter.iife.js
│ └── byte-converter.iife.min.js
│ ├── Ecoji
│ ├── ecoji.esm.js
│ ├── ecoji.esm.min.js
│ ├── ecoji.iife.js
│ └── ecoji.iife.min.js
│ ├── LEB128
│ ├── leb-128.esm.js
│ ├── leb-128.esm.min.js
│ ├── leb-128.iife.js
│ └── leb-128.iife.min.js
│ ├── SimpleBase
│ ├── simple-base.esm.js
│ ├── simple-base.esm.min.js
│ ├── simple-base.iife.js
│ └── simple-base.iife.min.js
│ └── UUencode
│ ├── uuencode.esm.js
│ ├── uuencode.esm.min.js
│ ├── uuencode.iife.js
│ └── uuencode.iife.min.js
├── examples
├── assets
│ ├── prism.css
│ └── prism.js
├── demo.html
└── live-examples.html
├── lib
└── big.js
│ ├── big.min.js
│ └── big.mjs
├── package-lock.json
├── package.json
├── rollup.config.mjs
├── src
├── base-ex.js
├── converters
│ ├── base-1.js
│ ├── base-16.js
│ ├── base-2048.js
│ ├── base-32.js
│ ├── base-58.js
│ ├── base-64.js
│ ├── base-85.js
│ ├── base-91.js
│ ├── base-phi.js
│ ├── byte-converter.js
│ ├── ecoji.js
│ ├── leb-128.js
│ ├── simple-base.js
│ └── uuencode.js
├── core.js
├── io-handlers.js
└── utils.js
├── test
├── base-1.test.js
├── ecoji-orig.test.js
├── fixtures
│ ├── ecoji
│ │ ├── ascii.garbage
│ │ ├── concat_v1_1.enc
│ │ ├── concat_v1_1.plaind
│ │ ├── concat_v1_2.enc
│ │ ├── concat_v1_2.plaind
│ │ ├── concat_v2_1.enc
│ │ ├── concat_v2_1.plaind
│ │ ├── concat_v2_2.enc
│ │ ├── concat_v2_2.plaind
│ │ ├── eight_byte.ev1
│ │ ├── eight_byte.ev2
│ │ ├── eight_byte.plain
│ │ ├── exhaustive.ev1
│ │ ├── exhaustive.ev2
│ │ ├── exhaustive.plain
│ │ ├── five_byte.ev1
│ │ ├── five_byte.ev2
│ │ ├── five_byte.plain
│ │ ├── four_byte_1.ev1
│ │ ├── four_byte_1.ev2
│ │ ├── four_byte_1.plain
│ │ ├── four_byte_2.ev1
│ │ ├── four_byte_2.ev2
│ │ ├── four_byte_2.plain
│ │ ├── four_byte_3.ev1
│ │ ├── four_byte_3.ev2
│ │ ├── four_byte_3.plain
│ │ ├── four_byte_4.ev1
│ │ ├── four_byte_4.ev2
│ │ ├── four_byte_4.plain
│ │ ├── incorrect_v1_padding.garbage
│ │ ├── misplaced_padding_1.garbage
│ │ ├── misplaced_padding_2.garbage
│ │ ├── misplaced_padding_3.garbage
│ │ ├── misplaced_padding_4.garbage
│ │ ├── misplaced_padding_5.garbage
│ │ ├── misplaced_padding_6.garbage
│ │ ├── misplaced_padding_7.garbage
│ │ ├── missing_padding_1.garbage
│ │ ├── missing_padding_2.garbage
│ │ ├── mixed_1.garbage
│ │ ├── mixed_2.garbage
│ │ ├── mixed_3.garbage
│ │ ├── mixed_4.garbage
│ │ ├── mixed_5.garbage
│ │ ├── mixed_6.garbage
│ │ ├── mixed_7.garbage
│ │ ├── nine_byte_0.ev1
│ │ ├── nine_byte_0.ev2
│ │ ├── nine_byte_0.plain
│ │ ├── nine_byte_1.ev1
│ │ ├── nine_byte_1.ev2
│ │ ├── nine_byte_1.plain
│ │ ├── nine_byte_2.ev1
│ │ ├── nine_byte_2.ev2
│ │ ├── nine_byte_2.plain
│ │ ├── nine_byte_3.ev1
│ │ ├── nine_byte_3.ev2
│ │ ├── nine_byte_3.plain
│ │ ├── non_ecoji_emoji.garbage
│ │ ├── one_byte.ev1
│ │ ├── one_byte.ev2
│ │ ├── one_byte.plain
│ │ ├── phrase.ev1
│ │ ├── phrase.ev2
│ │ ├── phrase.plain
│ │ ├── seven_byte.ev1
│ │ ├── seven_byte.ev2
│ │ ├── seven_byte.plain
│ │ ├── six_byte.ev1
│ │ ├── six_byte.ev2
│ │ ├── six_byte.plain
│ │ ├── three_byte.ev1
│ │ ├── three_byte.ev2
│ │ ├── three_byte.plain
│ │ ├── two_byte.ev1
│ │ ├── two_byte.ev2
│ │ ├── two_byte.plain
│ │ ├── windows_newline_v2_1.enc
│ │ ├── windows_newline_v2_1.plaind
│ │ ├── windows_newline_v2_2.enc
│ │ ├── windows_newline_v2_2.plaind
│ │ ├── zero_byte.ev1
│ │ ├── zero_byte.ev2
│ │ └── zero_byte.plain
│ ├── encoding-map.json
│ ├── helpers.js
│ └── load-json.js
├── map.test.js
├── number-mode.test.js
├── random-io.test.js
└── simple-base.test.js
└── third-party-licenses
├── BASE2048-LICENSE
├── BASE91-LICENSE
├── BIG.JS-LICENCE.md
└── ECOJI-LICENSE
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2022": true,
5 | "node": true
6 | },
7 | "extends": "eslint:recommended",
8 | "parserOptions": {
9 | "ecmaVersion": "latest",
10 | "sourceType": "module"
11 | },
12 | "rules": {
13 | "accessor-pairs": "error",
14 | "array-bracket-newline": "error",
15 | "array-bracket-spacing": "off",
16 | "array-callback-return": "error",
17 | "array-element-newline": "off",
18 | "arrow-body-style": "error",
19 | "arrow-parens": "off",
20 | "arrow-spacing": "off",
21 | "block-scoped-var": "error",
22 | "block-spacing": [
23 | "error",
24 | "never"
25 | ],
26 | "brace-style": "off",
27 | "capitalized-comments": "off",
28 | "class-methods-use-this": "off",
29 | "comma-dangle": "off",
30 | "comma-spacing": "off",
31 | "comma-style": [
32 | "error",
33 | "last"
34 | ],
35 | "complexity": ["warn", 28],
36 | "computed-property-spacing": [
37 | "error",
38 | "never"
39 | ],
40 | "consistent-return": "error",
41 | "consistent-this": "error",
42 | "curly": "off",
43 | "default-case": "error",
44 | "default-case-last": "error",
45 | "default-param-last": "error",
46 | "dot-location": ["error", "property"],
47 | "dot-notation": "error",
48 | "eol-last": "error",
49 | "eqeqeq": "off",
50 | "func-call-spacing": "error",
51 | "func-name-matching": "error",
52 | "func-names": "off",
53 | "func-style": [
54 | "error",
55 | "declaration",
56 | {
57 | "allowArrowFunctions": true
58 | }
59 | ],
60 | "function-paren-newline": "off",
61 | "generator-star-spacing": "error",
62 | "grouped-accessor-pairs": "error",
63 | "guard-for-in": "off",
64 | "id-denylist": "error",
65 | "id-length": "off",
66 | "id-match": "error",
67 | "implicit-arrow-linebreak": [
68 | "error",
69 | "beside"
70 | ],
71 | "indent": "off",
72 | "init-declarations": "off",
73 | "jsx-quotes": "error",
74 | "key-spacing": "off",
75 | "keyword-spacing": "off",
76 | "line-comment-position": "off",
77 | "linebreak-style": [
78 | "error",
79 | "unix"
80 | ],
81 | "lines-around-comment": "off",
82 | "lines-between-class-members": [
83 | "error",
84 | "always",
85 | {
86 | "exceptAfterSingleLine": true
87 | }
88 | ],
89 | "max-classes-per-file": "off",
90 | "max-depth": "off",
91 | "max-len": "off",
92 | "max-lines": "off",
93 | "max-lines-per-function": "off",
94 | "max-nested-callbacks": "error",
95 | "max-params": "off",
96 | "max-statements": "off",
97 | "max-statements-per-line": "off",
98 | "multiline-comment-style": "off",
99 | "new-parens": "off",
100 | "newline-per-chained-call": "error",
101 | "no-alert": "error",
102 | "no-array-constructor": "off",
103 | "no-await-in-loop": "error",
104 | "no-bitwise": "off",
105 | "no-caller": "error",
106 | "no-cond-assign": [
107 | "error",
108 | "except-parens"
109 | ],
110 | "no-confusing-arrow": "off",
111 | "no-console": "off",
112 | "no-constructor-return": "error",
113 | "no-continue": "error",
114 | "no-div-regex": "error",
115 | "no-duplicate-imports": "error",
116 | "no-else-return": "off",
117 | "no-empty-function": "error",
118 | "no-eq-null": "error",
119 | "no-eval": "error",
120 | "no-extend-native": "error",
121 | "no-extra-bind": "error",
122 | "no-extra-label": "error",
123 | "no-extra-parens": "off",
124 | "no-floating-decimal": "error",
125 | "no-implicit-coercion": "error",
126 | "no-implicit-globals": "error",
127 | "no-implied-eval": "error",
128 | "no-inline-comments": "off",
129 | "no-invalid-this": "error",
130 | "no-iterator": "error",
131 | "no-label-var": "error",
132 | "no-labels": "error",
133 | "no-lone-blocks": "error",
134 | "no-lonely-if": "error",
135 | "no-loop-func": "error",
136 | "no-loss-of-precision": "error",
137 | "no-magic-numbers": "off",
138 | "no-mixed-operators": "off",
139 | "no-multi-assign": "error",
140 | "no-multi-spaces": "off",
141 | "no-multi-str": "error",
142 | "no-multiple-empty-lines": "error",
143 | "no-negated-condition": "off",
144 | "no-nested-ternary": "off",
145 | "no-new": "error",
146 | "no-new-func": "error",
147 | "no-new-object": "off",
148 | "no-new-wrappers": "error",
149 | "no-nonoctal-decimal-escape": "error",
150 | "no-octal-escape": "error",
151 | "no-param-reassign": "off",
152 | "no-plusplus": "off",
153 | "no-promise-executor-return": "error",
154 | "no-proto": "error",
155 | "no-restricted-exports": "error",
156 | "no-restricted-globals": "error",
157 | "no-restricted-imports": "error",
158 | "no-restricted-properties": "error",
159 | "no-restricted-syntax": "error",
160 | "no-return-assign": "off",
161 | "no-return-await": "error",
162 | "no-script-url": "error",
163 | "no-self-compare": "error",
164 | "no-sequences": "off",
165 | "no-shadow": "off",
166 | "no-tabs": "error",
167 | "no-template-curly-in-string": "error",
168 | "no-ternary": "off",
169 | "no-throw-literal": "error",
170 | "no-trailing-spaces": "off",
171 | "no-undef-init": "error",
172 | "no-undefined": "error",
173 | "no-underscore-dangle": "error",
174 | "no-unmodified-loop-condition": "error",
175 | "no-unneeded-ternary": "error",
176 | "no-unreachable-loop": "error",
177 | "no-unsafe-optional-chaining": "error",
178 | "no-unused-expressions": "off",
179 | "no-use-before-define": "off",
180 | "no-useless-backreference": "error",
181 | "no-useless-call": "error",
182 | "no-useless-computed-key": "error",
183 | "no-useless-concat": "error",
184 | "no-useless-constructor": "error",
185 | "no-useless-rename": "error",
186 | "no-useless-return": "error",
187 | "no-var": "off",
188 | "no-void": "error",
189 | "no-warning-comments": "error",
190 | "no-whitespace-before-property": "error",
191 | "nonblock-statement-body-position": "error",
192 | "object-curly-newline": "error",
193 | "object-curly-spacing": "off",
194 | "object-shorthand": "error",
195 | "one-var": "off",
196 | "one-var-declaration-per-line": "off",
197 | "operator-assignment": [
198 | "error",
199 | "always"
200 | ],
201 | "operator-linebreak": "error",
202 | "padded-blocks": "off",
203 | "padding-line-between-statements": "error",
204 | "prefer-arrow-callback": "error",
205 | "prefer-const": "off",
206 | "prefer-destructuring": "off",
207 | "prefer-exponentiation-operator": "error",
208 | "prefer-named-capture-group": "error",
209 | "prefer-numeric-literals": "error",
210 | "prefer-object-spread": "error",
211 | "prefer-promise-reject-errors": "error",
212 | "prefer-regex-literals": "error",
213 | "prefer-rest-params": "error",
214 | "prefer-spread": "error",
215 | "prefer-template": "error",
216 | "quote-props": "off",
217 | "quotes": "off",
218 | "radix": [
219 | "error",
220 | "always"
221 | ],
222 | "require-atomic-updates": "error",
223 | "require-await": "off",
224 | "require-unicode-regexp": "off",
225 | "rest-spread-spacing": [
226 | "error",
227 | "never"
228 | ],
229 | "semi": "off",
230 | "semi-spacing": "off",
231 | "semi-style": [
232 | "error",
233 | "last"
234 | ],
235 | "sort-imports": "error",
236 | "sort-keys": "off",
237 | "sort-vars": "off",
238 | "space-before-blocks": "off",
239 | "space-before-function-paren": "off",
240 | "space-in-parens": [
241 | "error",
242 | "never"
243 | ],
244 | "space-infix-ops": "off",
245 | "space-unary-ops": "error",
246 | "spaced-comment": "off",
247 | "strict": "off",
248 | "switch-colon-spacing": "error",
249 | "symbol-description": "error",
250 | "template-curly-spacing": [
251 | "error",
252 | "never"
253 | ],
254 | "template-tag-spacing": "error",
255 | "unicode-bom": [
256 | "error",
257 | "never"
258 | ],
259 | "vars-on-top": "error",
260 | "wrap-iife": "off",
261 | "wrap-regex": "error",
262 | "yield-star-spacing": "error",
263 | "yoda": "off"
264 | }
265 | }
266 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 |
--------------------------------------------------------------------------------
/.github/workflows/npm-publish.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
3 |
4 | name: Node.js Package
5 |
6 | on:
7 | release:
8 | types: [created]
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v3
15 | - uses: actions/setup-node@v3
16 | with:
17 | node-version: 16
18 | - run: npm ci
19 | - run: npm test
20 |
21 | publish-npm:
22 | needs: build
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: actions/checkout@v3
26 | - uses: actions/setup-node@v3
27 | with:
28 | node-version: 16
29 | registry-url: https://registry.npmjs.org/
30 | - run: npm ci
31 | - run: npm publish
32 | env:
33 | NODE_AUTH_TOKEN: ${{secrets.npm_key}}
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | BaseEx.code-workspace
2 | node_modules
3 | .vscode/*
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | BaseEx.code-workspace
2 | .vscode/*
3 | .github
--------------------------------------------------------------------------------
/.remembrance.json:
--------------------------------------------------------------------------------
1 | {
2 | "src": "./src/**",
3 | "dist": [
4 | "./cjs/**",
5 | "./dist/**"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/CDN.md:
--------------------------------------------------------------------------------
1 | # CDN links (jsdelivr)
2 |
3 | ### Full Build
4 |
5 | ##### BaseEx
6 | ###### esm
7 | ```js
8 | import BaseEx from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/base-ex.esm.min.js";
9 | ```
10 | ###### iife
11 | ```html
12 |
13 | ```
14 |
15 |
16 | ### Standalone Builds
17 |
18 | ##### Base1
19 | ###### esm
20 | ```js
21 | import Base1 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base1/base-1.esm.min.js";
22 | ```
23 | ###### iife
24 | ```html
25 |
26 | ```
27 |
28 |
29 | ##### Base16
30 | ###### esm
31 | ```js
32 | import Base16 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base16/base-16.esm.min.js";
33 | ```
34 | ###### iife
35 | ```html
36 |
37 | ```
38 |
39 |
40 | ##### Base32
41 | ###### esm
42 | ```js
43 | import Base32 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base32/base-32.esm.min.js";
44 | ```
45 | ###### iife
46 | ```html
47 |
48 | ```
49 |
50 |
51 | ##### Base58
52 | ###### esm
53 | ```js
54 | import Base58 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base58/base-58.esm.min.js";
55 | ```
56 | ###### iife
57 | ```html
58 |
59 | ```
60 |
61 |
62 | ##### Base64
63 | ###### esm
64 | ```js
65 | import Base64 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base64/base-64.esm.min.js";
66 | ```
67 | ###### iife
68 | ```html
69 |
70 | ```
71 |
72 |
73 | ##### UUencode
74 | ###### esm
75 | ```js
76 | import UUencode from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/UUencode/uuencode.esm.min.js";
77 | ```
78 | ###### iife
79 | ```html
80 |
81 | ```
82 |
83 |
84 | ##### Base85
85 | ###### esm
86 | ```js
87 | import Base85 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base85/base-85.esm.min.js";
88 | ```
89 | ###### iife
90 | ```html
91 |
92 | ```
93 |
94 |
95 | ##### Base91
96 | ###### esm
97 | ```js
98 | import Base91 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base91/base-91.esm.min.js";
99 | ```
100 | ###### iife
101 | ```html
102 |
103 | ```
104 |
105 |
106 | ##### LEB128
107 | ###### esm
108 | ```js
109 | import LEB128 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/LEB128/leb-128.esm.min.js";
110 | ```
111 | ###### iife
112 | ```html
113 |
114 | ```
115 |
116 |
117 | ##### Ecoji
118 | ###### esm
119 | ```js
120 | import Ecoji from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Ecoji/ecoji.esm.min.js";
121 | ```
122 | ###### iife
123 | ```html
124 |
125 | ```
126 |
127 |
128 | ##### Base2048
129 | ###### esm
130 | ```js
131 | import Base2048 from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/Base2048/base-2048.esm.min.js";
132 | ```
133 | ###### iife
134 | ```html
135 |
136 | ```
137 |
138 |
139 | ##### SimpleBase
140 | ###### esm
141 | ```js
142 | import SimpleBase from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/SimpleBase/simple-base.esm.min.js";
143 | ```
144 | ###### iife
145 | ```html
146 |
147 | ```
148 |
149 |
150 | ##### BasePhi
151 | ###### esm
152 | ```js
153 | import BasePhi from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/BasePhi/base-phi.esm.min.js";
154 | ```
155 | ###### iife
156 | ```html
157 |
158 | ```
159 |
160 |
161 | ##### ByteConverter
162 | ###### esm
163 | ```js
164 | import ByteConverter from "https://cdn.jsdelivr.net/npm/base-ex@latest/dist/converters/ByteConverter/byte-converter.esm.min.js";
165 | ```
166 | ###### iife
167 | ```html
168 |
169 | ```
170 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 UmamiAppearance
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/dist/converters/Base16/base-16.esm.min.js:
--------------------------------------------------------------------------------
1 | class t{static toBytes(t){return!ArrayBuffer.isView(t)||"undefined"!=typeof Buffer&&t instanceof Buffer||(t=t.buffer),[new Uint8Array(t),!1,"bytes"]}}class e{static get typeList(){return["buffer","bytes","uint8","view"]}static getType(t){if(!e.typeList.includes(t))throw new TypeError(`Unknown output type: '${t}'`);return t}static compile(t,n){let i;return i="buffer"===(n=e.getType(n))?t.buffer:"view"===n?new DataView(t.buffer):t,i}}class n{static makeDataView(t){const e=new ArrayBuffer(t);return new DataView(e)}static floatingPoints(t,e=!1){const n=this.makeDataView(8);return n.setFloat64(0,t,e),n}static numbers(t,e=!1){let n,i;if(Number.isInteger(t)){if(i="int",!Number.isSafeInteger(t)){let e,n,i;throw t<0?(e=Number.MIN_SAFE_INTEGER,n="smaller",i="MIN"):(e=Number.MAX_SAFE_INTEGER,n="bigger",i="MAX"),new RangeError(`The provided integer is ${n} than ${i}_SAFE_INTEGER: '${e}'\nData integrity is not guaranteed. Use a BigInt to avoid this issue.\n(If you see this error although a float was provided, the input has to many digits before the decimal point to store the decimal places in a float with 64 bits.)`)}t<0?t<-2147483648?(n=this.makeDataView(8),n.setBigInt64(0,BigInt(t),e)):t<-32768?(n=this.makeDataView(4),n.setInt32(0,t,e)):(n=this.makeDataView(2),n.setInt16(0,t,e)):t>0?t>4294967295?(n=this.makeDataView(8),n.setBigUint64(0,BigInt(t),e)):t>65535?(n=this.makeDataView(4),n.setUint32(0,t,e)):(n=this.makeDataView(2),n.setInt16(0,t,e)):n=new Uint16Array([0])}else i="float",n=this.floatingPoints(t,e);return[new Uint8Array(n.buffer),i]}static bigInts(t,e=!1){const n=new Array,i=e?"push":"unshift",r=18446744073709551616n;if(t<0)for(;t<-9223372036854775808n;)n[i](t%r),t>>=64n;else for(;t>=r;)n[i](t%r),t>>=64n;n[i](t);const s=8*n.length,o=this.makeDataView(s);return n.forEach(((t,n)=>{const i=8*n;o.setBigUint64(i,t,e)})),new Uint8Array(o.buffer)}static toBytes(t,e){let n,i=!1,r="bytes";if(t instanceof ArrayBuffer)n=new Uint8Array(t.slice());else if(ArrayBuffer.isView(t))n="undefined"!=typeof Buffer&&t instanceof Buffer?new Uint8Array(t):new Uint8Array(t.buffer.slice());else if("string"==typeof t||t instanceof String)n=(new TextEncoder).encode(t);else if("number"==typeof t){if(isNaN(t))throw new TypeError("Cannot proceed. Input is NaN.");if(t==1/0)throw new TypeError("Cannot proceed. Input is Infinity.");if(e.signed&&t<0&&(i=!0,t=-t),e.numberMode){const i=this.floatingPoints(t,e.littleEndian);n=new Uint8Array(i.buffer),r="float"}else[n,r]=this.numbers(t,e.littleEndian)}else if("bigint"==typeof t)e.signed&&t<0&&(i=!0,t*=-1n),n=this.bigInts(t,e.littleEndian),r="int";else{if(!Array.isArray(t))throw new TypeError("The provided input type can not be processed.");{const i=new Array;for(const n of t)i.push(...this.toBytes(n,e)[0]);n=Uint8Array.from(i)}}return[n,i,r]}}const i=n,r=class{static get typeList(){return["bigint64","bigint_n","biguint64","buffer","bytes","float32","float64","float_n","int8","int16","int32","int_n","str","uint8","uint16","uint32","uint_n","view"]}static getType(t){if(!this.typeList.includes(t))throw new TypeError(`Unknown output type: '${t}'`);return t}static makeTypedArrayBuffer(t,e,n,i){const r=t.byteLength,s=(e-t.byteLength%e)%e,o=i&&r>1?255:0;let a=t;if(s){a=new Uint8Array(r+s),a.fill(o);const e=n?0:s;a.set(t,e)}return a.buffer}static makeTypedArray(t,e,n,i){let r;if("int16"===e||"uint16"===e){const s=this.makeTypedArrayBuffer(t,2,n,i);r="int16"===e?new Int16Array(s):new Uint16Array(s)}else if("int32"===e||"uint32"===e||"float32"===e){const s=this.makeTypedArrayBuffer(t,4,n,i);r="int32"===e?new Int32Array(s):"uint32"===e?new Uint32Array(s):new Float32Array(s)}else if("bigint64"===e||"biguint64"===e||"float64"===e){const s=this.makeTypedArrayBuffer(t,8,n,i);r="bigint64"===e?new BigInt64Array(s):"biguint64"===e?new BigUint64Array(s):new Float64Array(s)}return r}static compile(t,e,i=!1,r=!1){let s;if(e=this.getType(e),r){let r;if(r=e.match(/^float/)?-this.compile(t,"float_n",i):-this.compile(t,"uint_n",i),"float_n"===e)return r;t=n.toBytes(r,{littleEndian:i,numberMode:!1,signed:!1})[0]}if("buffer"===e)s=t.buffer;else if("bytes"===e||"uint8"===e)s=t;else if("int8"===e)s=new Int8Array(t.buffer);else if("view"===e)s=new DataView(t.buffer);else if("str"===e)s=(new TextDecoder).decode(t);else if("uint_n"===e||"int_n"===e||"bigint_n"===e){if(1===t.length){const e=this.makeTypedArrayBuffer(t,2,i,r);t=new Uint8Array(e)}i&&t.reverse();let n=0n;t.forEach((t=>n=(n<<8n)+BigInt(t))),"uint_n"!==e&&(n=BigInt.asIntN(8*t.length,n)),s="bigint_n"!==e&&n>=Number.MIN_SAFE_INTEGER&&n<=Number.MAX_SAFE_INTEGER?Number(n):n}else if("float_n"===e)if(t.length<=4){let e;e=4===t.length?t:this.makeTypedArray(t,"float32",!1,r);s=new DataView(e.buffer).getFloat32(0,i)}else{if(!(t.length<=8))throw new RangeError("The provided input is to complex to be converted into a floating point.");{let e;e=8===t.length?t:this.makeTypedArray(t,"float64",!1,r);s=new DataView(e.buffer).getFloat64(0,i)}}else if("number"===e){if(8!==t.length)throw new TypeError("Type mismatch. Cannot convert into number.");const e=new Float64Array(t.buffer);s=Number(e)}else s=this.makeTypedArray(t,e,i,r);return s}};class s extends TypeError{constructor(){super("The input is signed but the converter is not set to treat input as signed.\nYou can pass the string 'signed' to the decode function or when constructing the converter."),this.name="SignError"}}class o extends TypeError{constructor(t,e=null){null===e&&(e=`Character '${t}' is not part of the charset.`),super(e),this.name="DecodingError"}}class a{constructor(t){this.root=t,this.converterArgs={},this.#t()}setIOHandlers(t=i,e=r){this.inputHandler=t,this.outputHandler=e}#t(){this.root.addCharset=(t,e,n=[],i=!0)=>{const r=(t,n,i)=>{if(0===i&&n.length)return console.warn(`This converter has no ${t}. The following argument was ignored:\n'${n}'`),[];let r=i;if("string"==typeof n&&(n=[...n]),Array.isArray(n))r=n.length,n=new Set(n);else if(!(n instanceof Set))throw new TypeError(`The ${t} must be one of the types:\n'str', 'set', 'array'."`);if(n.size===i)return[...n];if(r!==i)throw new Error(`Your ${t} has a length of ${r}. The converter requires a length of ${i}.`);{const n={};(e=[...e]).forEach((t=>{t in n?n[t]++:n[t]=1}));let r="";i<100&&(r=`${e.join("")}\n`,e.forEach((t=>{n[t]>1?r+="^":r+=" "})));const s=Object.keys(n).filter((t=>n[t]>1));throw new Error(`You have repetitive char(s) [ ${s.join(" | ")} ] in your ${t}. Make sure each character is unique.\n${r}`)}};if(this.root.frozenCharsets)throw new Error("The charsets of this converter cannot be changed.");if("string"!=typeof t)throw new TypeError("The charset name must be a string.");i&&t in this.root.charsets&&console.warn(`An existing charset with name ${t} will get replaced.`);const s=r("charset",e,this.root.converter.radix),o=r("padding set",n,this.root.padCharAmount);this.root.charsets[t]=s,o.length&&(this.root.padChars[t]=o),i&&console.info(`New charset '${t}' was added and is ready to use`)},this.root.setDefaultCharset=t=>{if(!(t in this.root.charsets)){const e=Object.keys(this.root.charsets).join("\n * ");throw new TypeError(`Charset ${t} was not found. Available charsets are:\n * ${e}`)}this.root.version=t}}#e(t){return t.map((t=>`'${t}'`)).join(", ")}toSignedStr(t,e){return t=t.replace(/^0+(?!$)/,""),e&&(t="-".concat(t)),t}extractSign(t){let e=!1;return"-"===t[0]&&(e=!0,t=t.slice(1)),[t,e]}#n(t,e,n,i){throw new TypeError([`'${t}'\n\nParameters:`,i?"\n * valid declarations for IO handlers are 'bytesOnly', 'bytesIn', 'bytesOut'":"",this.root.isMutable.signed?"\n * pass 'signed' to disable, 'unsigned' to enable the use of the twos's complement for negative integers":"",this.root.isMutable.littleEndian?"\n * 'be' for big , 'le' for little endian byte order for case conversion":"",this.root.isMutable.padding?"\n * pass 'pad' to fill up, 'nopad' to not fill up the output with the particular padding":"",this.root.isMutable.upper?"\n * valid args for changing the encoded output case are 'upper' and 'lower'":"",`\n * valid args for the output type are ${this.#e(n)}`,e?`\n * the option(s) for version/charset are: ${this.#e(e)}`:"","\n * valid args for integrity check are: 'integrity' and 'nointegrity'",this.root.hasDecimalMode?"\n * 'decimal' for decimal-mode (directly converts Numbers including decimal values, without byte-conversion)":"","\n * 'number' for number-mode (converts every number into a Float64Array to keep the natural js number type)",Object.keys(this.converterArgs).length?`\n * converter specific args:\n - ${(()=>Object.keys(this.converterArgs).map((t=>this.converterArgs[t].map((t=>`'${t}'`)).join(" and "))).join("\n - "))()}`:"","\n\nTraceback:"].join(""))}validateArgs(n,s=!1){const o={decimalMode:this.root.decimalMode,integrity:this.root.integrity,littleEndian:this.root.littleEndian,numberMode:this.root.numberMode,options:this.root.options,outputType:this.root.outputType,padding:this.root.padding,signed:this.root.signed,upper:this.root.upper,version:this.root.version};for(const t in this.converterArgs)o[t]=this.root[t];if(!n.length)return s&&this.setIOHandlers(),o;const a=t=>!!n.includes(t)&&(n.splice(n.indexOf(t),1),!0),l=Object.keys(this.root.charsets),h={integrity:["nointegrity","integrity"],littleEndian:["be","le"],padding:["nopad","pad"],signed:["unsigned","signed"],upper:["lower","upper"],...this.converterArgs};if(s)if(a("bytes_only"))this.setIOHandlers(t,e);else{const n=a("bytes_in")?t:i,s=a("bytes_out")?e:r;this.setIOHandlers(n,s)}const u=this.outputHandler.typeList;if(a("number")&&(o.numberMode=!0,o.outputType="float_n"),a("decimal")){if(!this.root.hasDecimalMode)throw TypeError("Argument 'decimal' is only allowed for converters with a non-integer base.");o.decimalMode=!0,o.outputType="decimal",o.numberMode&&(o.numberMode=!1,console.warn("-> number-mode was disabled due to the decimal-mode"))}if(n.forEach((t=>{if("object"!=typeof t)if(t=String(t).toLowerCase(),l.includes(t))o.version=t;else if(u.includes(t))o.outputType=t;else{let e=!0;for(const n in h)if(h[n].includes(t)){if(e=!1,!this.root.isMutable[n])throw TypeError(`Argument '${t}' is not allowed for this type of converter.`);o[n]=Boolean(h[n].indexOf(t))}e&&this.#n(t,l,u,s)}else o.options={...o.options,...t}})),o.padding&&o.signed&&(o.padding=!1,console.warn("-> padding was set to false due to the signed conversion")),s)for(const t in o)this.root[t]=o[t];return o}signError(){throw new s}wrapOutput(t,e=0){if(!e)return t;const n=new RegExp(`.{1,${e}}`,"gu");return t.match(n).join("\n")}normalizeInput(t,e=!1){return e?String(t):String(t).replace(/\s/g,"")}}class l{constructor(t,e=null,n=null,i=0){this.radix=t,null!==e&&null!==n?(this.bsEnc=e,this.bsDec=n):[this.bsEnc,this.bsDec]=this.constructor.guessBS(t),this.decPadVal=i,this.powers={}}static guessBS(t){let e=t<8?t:Math.ceil(256/t);for(;e>8&&!(e%8);)e/=8;let n=0;for(;8*n*Math.log(2)/Math.log(t)=this.radix;)[u,h]=this.divmod(u,this.radix),a.unshift(parseInt(h,10));for(a.unshift(parseInt(u,10));a.lengthc=c.concat(e[t]))),i&&(c=i(c,o)),s=s.concat(c)}return[s,o]}decode(t,e,n=[],i=!0,r=!1){if(!t)return new Uint8Array(0);let s=this.bsDec;const a=[];let l;if([...t].forEach((t=>{const r=e.indexOf(t);if(r>-1)a.push(r);else if(i&&-1===n.indexOf(t))throw new o(t)})),0===s)s=a.length;else{l=(s-a.length%s)%s;const t=new Array(l).fill(this.decPadVal);r?a.unshift(...t):a.push(...t)}let h=new Array;for(let t=0,e=a.length;t(this.powers[i]=BigInt(this.pow(i)),this.powers[i]))();e+=BigInt(a[t+n])*r}const n=[];let i,r=e;for(;r>=256;)[r,i]=this.divmod(r,256),n.unshift(parseInt(i,10));for(n.unshift(parseInt(r,10));n.length1){for(;!h[0];)h.shift();h.length||h.push(0),h.reverse()}}else if(this.bsDec){const t=this.padChars(l);h.splice(h.length-t)}return Uint8Array.from(h)}padBytes(t){return Math.floor(t*this.bsDec/this.bsEnc)}padChars(t){return Math.ceil(t*this.bsEnc/this.bsDec)}pow(t){return BigInt(this.radix)**BigInt(t)}divmod(t,e){return[t,e]=[BigInt(t),BigInt(e)],[t/e,t%e]}}class h{constructor(t=!0){this.charsets={},this.decimalMode=!1,this.frozenCharsets=!1,this.hasDecimalMode=!1,this.hasSignedMode=!1,this.integrity=!0,this.littleEndian=!1,this.numberMode=!1,this.outputType="buffer",this.padding=!1,this.padCharAmount=0,this.padChars={},this.nonASCII=!1,this.signed=!1,this.upper=null,t&&(this.utils=new a(this)),this.version="default",this.options={lineWrap:0},this.isMutable={integrity:!0,littleEndian:!1,padding:!1,signed:!1,upper:!1}}encode(t,e,n,...i){const r=this.utils.validateArgs(i);let[s,o,a]=this.utils.inputHandler.toBytes(t,r),l=null;e&&(l=e(r));let[h,u]=this.converter.encode(s,this.charsets[r.version],r.littleEndian,l);return r.signed&&(h=this.utils.toSignedStr(h,o)),r.upper&&(h=h.toUpperCase()),n&&(h=n({inputBytes:s,output:h,settings:r,zeroPadding:u,type:a})),this.utils.wrapOutput(h,r.options.lineWrap)}decode(t,e,n,i,...r){const s=this.utils.validateArgs(r);t=this.utils.normalizeInput(t,i);let o=!1;this.hasSignedMode&&([t,o]=this.utils.extractSign(t),o&&!s.signed&&this.utils.signError()),this.isMutable.upper&&(t=t.toLowerCase()),e&&(t=e({input:t,settings:s}));let a=this.converter.decode(t,this.charsets[s.version],this.padChars[s.version],s.integrity,s.littleEndian);return n&&(a=n({input:t,output:a,settings:s})),this.utils.outputHandler.compile(a,s.outputType,s.littleEndian,o)}}
2 | /**
3 | * [BaseEx|Base16 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-16.js}
4 | *
5 | * @version 0.8.1
6 | * @author UmamiAppearance [mail@umamiappearance.eu]
7 | * @license MIT
8 | */class u extends h{constructor(...t){super(),this.converter=new l(16,1,2),this.charsets.default=[..."0123456789abcdef"],this.padChars.default=[],this.hasSignedMode=!0,this.isMutable.signed=!0,this.isMutable.upper=!0,this.utils.validateArgs(t,!0)}encode(t,...e){return super.encode(t,null,null,...e)}decode(t,...e){return super.decode(t,(({input:t,settings:e})=>(t=t.replace(/^0x/,""),e.integrity||(t=t.toLowerCase().replace(/[^0-9a-f]/g,"")),t.length%2&&(t="0".concat(t)),t)),null,!1,...e)}}export{u as default};
9 |
--------------------------------------------------------------------------------
/dist/converters/Base91/base-91.esm.min.js:
--------------------------------------------------------------------------------
1 | class t{static toBytes(t){return!ArrayBuffer.isView(t)||"undefined"!=typeof Buffer&&t instanceof Buffer||(t=t.buffer),[new Uint8Array(t),!1,"bytes"]}}class e{static get typeList(){return["buffer","bytes","uint8","view"]}static getType(t){if(!e.typeList.includes(t))throw new TypeError(`Unknown output type: '${t}'`);return t}static compile(t,i){let n;return n="buffer"===(i=e.getType(i))?t.buffer:"view"===i?new DataView(t.buffer):t,n}}class i{static makeDataView(t){const e=new ArrayBuffer(t);return new DataView(e)}static floatingPoints(t,e=!1){const i=this.makeDataView(8);return i.setFloat64(0,t,e),i}static numbers(t,e=!1){let i,n;if(Number.isInteger(t)){if(n="int",!Number.isSafeInteger(t)){let e,i,n;throw t<0?(e=Number.MIN_SAFE_INTEGER,i="smaller",n="MIN"):(e=Number.MAX_SAFE_INTEGER,i="bigger",n="MAX"),new RangeError(`The provided integer is ${i} than ${n}_SAFE_INTEGER: '${e}'\nData integrity is not guaranteed. Use a BigInt to avoid this issue.\n(If you see this error although a float was provided, the input has to many digits before the decimal point to store the decimal places in a float with 64 bits.)`)}t<0?t<-2147483648?(i=this.makeDataView(8),i.setBigInt64(0,BigInt(t),e)):t<-32768?(i=this.makeDataView(4),i.setInt32(0,t,e)):(i=this.makeDataView(2),i.setInt16(0,t,e)):t>0?t>4294967295?(i=this.makeDataView(8),i.setBigUint64(0,BigInt(t),e)):t>65535?(i=this.makeDataView(4),i.setUint32(0,t,e)):(i=this.makeDataView(2),i.setInt16(0,t,e)):i=new Uint16Array([0])}else n="float",i=this.floatingPoints(t,e);return[new Uint8Array(i.buffer),n]}static bigInts(t,e=!1){const i=new Array,n=e?"push":"unshift",r=18446744073709551616n;if(t<0)for(;t<-9223372036854775808n;)i[n](t%r),t>>=64n;else for(;t>=r;)i[n](t%r),t>>=64n;i[n](t);const s=8*i.length,o=this.makeDataView(s);return i.forEach(((t,i)=>{const n=8*i;o.setBigUint64(n,t,e)})),new Uint8Array(o.buffer)}static toBytes(t,e){let i,n=!1,r="bytes";if(t instanceof ArrayBuffer)i=new Uint8Array(t.slice());else if(ArrayBuffer.isView(t))i="undefined"!=typeof Buffer&&t instanceof Buffer?new Uint8Array(t):new Uint8Array(t.buffer.slice());else if("string"==typeof t||t instanceof String)i=(new TextEncoder).encode(t);else if("number"==typeof t){if(isNaN(t))throw new TypeError("Cannot proceed. Input is NaN.");if(t==1/0)throw new TypeError("Cannot proceed. Input is Infinity.");if(e.signed&&t<0&&(n=!0,t=-t),e.numberMode){const n=this.floatingPoints(t,e.littleEndian);i=new Uint8Array(n.buffer),r="float"}else[i,r]=this.numbers(t,e.littleEndian)}else if("bigint"==typeof t)e.signed&&t<0&&(n=!0,t*=-1n),i=this.bigInts(t,e.littleEndian),r="int";else{if(!Array.isArray(t))throw new TypeError("The provided input type can not be processed.");{const n=new Array;for(const i of t)n.push(...this.toBytes(i,e)[0]);i=Uint8Array.from(n)}}return[i,n,r]}}const n=i,r=class{static get typeList(){return["bigint64","bigint_n","biguint64","buffer","bytes","float32","float64","float_n","int8","int16","int32","int_n","str","uint8","uint16","uint32","uint_n","view"]}static getType(t){if(!this.typeList.includes(t))throw new TypeError(`Unknown output type: '${t}'`);return t}static makeTypedArrayBuffer(t,e,i,n){const r=t.byteLength,s=(e-t.byteLength%e)%e,o=n&&r>1?255:0;let a=t;if(s){a=new Uint8Array(r+s),a.fill(o);const e=i?0:s;a.set(t,e)}return a.buffer}static makeTypedArray(t,e,i,n){let r;if("int16"===e||"uint16"===e){const s=this.makeTypedArrayBuffer(t,2,i,n);r="int16"===e?new Int16Array(s):new Uint16Array(s)}else if("int32"===e||"uint32"===e||"float32"===e){const s=this.makeTypedArrayBuffer(t,4,i,n);r="int32"===e?new Int32Array(s):"uint32"===e?new Uint32Array(s):new Float32Array(s)}else if("bigint64"===e||"biguint64"===e||"float64"===e){const s=this.makeTypedArrayBuffer(t,8,i,n);r="bigint64"===e?new BigInt64Array(s):"biguint64"===e?new BigUint64Array(s):new Float64Array(s)}return r}static compile(t,e,n=!1,r=!1){let s;if(e=this.getType(e),r){let r;if(r=e.match(/^float/)?-this.compile(t,"float_n",n):-this.compile(t,"uint_n",n),"float_n"===e)return r;t=i.toBytes(r,{littleEndian:n,numberMode:!1,signed:!1})[0]}if("buffer"===e)s=t.buffer;else if("bytes"===e||"uint8"===e)s=t;else if("int8"===e)s=new Int8Array(t.buffer);else if("view"===e)s=new DataView(t.buffer);else if("str"===e)s=(new TextDecoder).decode(t);else if("uint_n"===e||"int_n"===e||"bigint_n"===e){if(1===t.length){const e=this.makeTypedArrayBuffer(t,2,n,r);t=new Uint8Array(e)}n&&t.reverse();let i=0n;t.forEach((t=>i=(i<<8n)+BigInt(t))),"uint_n"!==e&&(i=BigInt.asIntN(8*t.length,i)),s="bigint_n"!==e&&i>=Number.MIN_SAFE_INTEGER&&i<=Number.MAX_SAFE_INTEGER?Number(i):i}else if("float_n"===e)if(t.length<=4){let e;e=4===t.length?t:this.makeTypedArray(t,"float32",!1,r);s=new DataView(e.buffer).getFloat32(0,n)}else{if(!(t.length<=8))throw new RangeError("The provided input is to complex to be converted into a floating point.");{let e;e=8===t.length?t:this.makeTypedArray(t,"float64",!1,r);s=new DataView(e.buffer).getFloat64(0,n)}}else if("number"===e){if(8!==t.length)throw new TypeError("Type mismatch. Cannot convert into number.");const e=new Float64Array(t.buffer);s=Number(e)}else s=this.makeTypedArray(t,e,n,r);return s}};class s extends TypeError{constructor(){super("The input is signed but the converter is not set to treat input as signed.\nYou can pass the string 'signed' to the decode function or when constructing the converter."),this.name="SignError"}}class o extends TypeError{constructor(t,e=null){null===e&&(e=`Character '${t}' is not part of the charset.`),super(e),this.name="DecodingError"}}class a{constructor(t){this.root=t,this.converterArgs={},this.#t()}setIOHandlers(t=n,e=r){this.inputHandler=t,this.outputHandler=e}#t(){this.root.addCharset=(t,e,i=[],n=!0)=>{const r=(t,i,n)=>{if(0===n&&i.length)return console.warn(`This converter has no ${t}. The following argument was ignored:\n'${i}'`),[];let r=n;if("string"==typeof i&&(i=[...i]),Array.isArray(i))r=i.length,i=new Set(i);else if(!(i instanceof Set))throw new TypeError(`The ${t} must be one of the types:\n'str', 'set', 'array'."`);if(i.size===n)return[...i];if(r!==n)throw new Error(`Your ${t} has a length of ${r}. The converter requires a length of ${n}.`);{const i={};(e=[...e]).forEach((t=>{t in i?i[t]++:i[t]=1}));let r="";n<100&&(r=`${e.join("")}\n`,e.forEach((t=>{i[t]>1?r+="^":r+=" "})));const s=Object.keys(i).filter((t=>i[t]>1));throw new Error(`You have repetitive char(s) [ ${s.join(" | ")} ] in your ${t}. Make sure each character is unique.\n${r}`)}};if(this.root.frozenCharsets)throw new Error("The charsets of this converter cannot be changed.");if("string"!=typeof t)throw new TypeError("The charset name must be a string.");n&&t in this.root.charsets&&console.warn(`An existing charset with name ${t} will get replaced.`);const s=r("charset",e,this.root.converter.radix),o=r("padding set",i,this.root.padCharAmount);this.root.charsets[t]=s,o.length&&(this.root.padChars[t]=o),n&&console.info(`New charset '${t}' was added and is ready to use`)},this.root.setDefaultCharset=t=>{if(!(t in this.root.charsets)){const e=Object.keys(this.root.charsets).join("\n * ");throw new TypeError(`Charset ${t} was not found. Available charsets are:\n * ${e}`)}this.root.version=t}}#e(t){return t.map((t=>`'${t}'`)).join(", ")}toSignedStr(t,e){return t=t.replace(/^0+(?!$)/,""),e&&(t="-".concat(t)),t}extractSign(t){let e=!1;return"-"===t[0]&&(e=!0,t=t.slice(1)),[t,e]}#i(t,e,i,n){throw new TypeError([`'${t}'\n\nParameters:`,n?"\n * valid declarations for IO handlers are 'bytesOnly', 'bytesIn', 'bytesOut'":"",this.root.isMutable.signed?"\n * pass 'signed' to disable, 'unsigned' to enable the use of the twos's complement for negative integers":"",this.root.isMutable.littleEndian?"\n * 'be' for big , 'le' for little endian byte order for case conversion":"",this.root.isMutable.padding?"\n * pass 'pad' to fill up, 'nopad' to not fill up the output with the particular padding":"",this.root.isMutable.upper?"\n * valid args for changing the encoded output case are 'upper' and 'lower'":"",`\n * valid args for the output type are ${this.#e(i)}`,e?`\n * the option(s) for version/charset are: ${this.#e(e)}`:"","\n * valid args for integrity check are: 'integrity' and 'nointegrity'",this.root.hasDecimalMode?"\n * 'decimal' for decimal-mode (directly converts Numbers including decimal values, without byte-conversion)":"","\n * 'number' for number-mode (converts every number into a Float64Array to keep the natural js number type)",Object.keys(this.converterArgs).length?`\n * converter specific args:\n - ${(()=>Object.keys(this.converterArgs).map((t=>this.converterArgs[t].map((t=>`'${t}'`)).join(" and "))).join("\n - "))()}`:"","\n\nTraceback:"].join(""))}validateArgs(i,s=!1){const o={decimalMode:this.root.decimalMode,integrity:this.root.integrity,littleEndian:this.root.littleEndian,numberMode:this.root.numberMode,options:this.root.options,outputType:this.root.outputType,padding:this.root.padding,signed:this.root.signed,upper:this.root.upper,version:this.root.version};for(const t in this.converterArgs)o[t]=this.root[t];if(!i.length)return s&&this.setIOHandlers(),o;const a=t=>!!i.includes(t)&&(i.splice(i.indexOf(t),1),!0),l=Object.keys(this.root.charsets),u={integrity:["nointegrity","integrity"],littleEndian:["be","le"],padding:["nopad","pad"],signed:["unsigned","signed"],upper:["lower","upper"],...this.converterArgs};if(s)if(a("bytes_only"))this.setIOHandlers(t,e);else{const i=a("bytes_in")?t:n,s=a("bytes_out")?e:r;this.setIOHandlers(i,s)}const h=this.outputHandler.typeList;if(a("number")&&(o.numberMode=!0,o.outputType="float_n"),a("decimal")){if(!this.root.hasDecimalMode)throw TypeError("Argument 'decimal' is only allowed for converters with a non-integer base.");o.decimalMode=!0,o.outputType="decimal",o.numberMode&&(o.numberMode=!1,console.warn("-> number-mode was disabled due to the decimal-mode"))}if(i.forEach((t=>{if("object"!=typeof t)if(t=String(t).toLowerCase(),l.includes(t))o.version=t;else if(h.includes(t))o.outputType=t;else{let e=!0;for(const i in u)if(u[i].includes(t)){if(e=!1,!this.root.isMutable[i])throw TypeError(`Argument '${t}' is not allowed for this type of converter.`);o[i]=Boolean(u[i].indexOf(t))}e&&this.#i(t,l,h,s)}else o.options={...o.options,...t}})),o.padding&&o.signed&&(o.padding=!1,console.warn("-> padding was set to false due to the signed conversion")),s)for(const t in o)this.root[t]=o[t];return o}signError(){throw new s}wrapOutput(t,e=0){if(!e)return t;const i=new RegExp(`.{1,${e}}`,"gu");return t.match(i).join("\n")}normalizeInput(t,e=!1){return e?String(t):String(t).replace(/\s/g,"")}}class l{constructor(t=!0){this.charsets={},this.decimalMode=!1,this.frozenCharsets=!1,this.hasDecimalMode=!1,this.hasSignedMode=!1,this.integrity=!0,this.littleEndian=!1,this.numberMode=!1,this.outputType="buffer",this.padding=!1,this.padCharAmount=0,this.padChars={},this.nonASCII=!1,this.signed=!1,this.upper=null,t&&(this.utils=new a(this)),this.version="default",this.options={lineWrap:0},this.isMutable={integrity:!0,littleEndian:!1,padding:!1,signed:!1,upper:!1}}encode(t,e,i,...n){const r=this.utils.validateArgs(n);let[s,o,a]=this.utils.inputHandler.toBytes(t,r),l=null;e&&(l=e(r));let[u,h]=this.converter.encode(s,this.charsets[r.version],r.littleEndian,l);return r.signed&&(u=this.utils.toSignedStr(u,o)),r.upper&&(u=u.toUpperCase()),i&&(u=i({inputBytes:s,output:u,settings:r,zeroPadding:h,type:a})),this.utils.wrapOutput(u,r.options.lineWrap)}decode(t,e,i,n,...r){const s=this.utils.validateArgs(r);t=this.utils.normalizeInput(t,n);let o=!1;this.hasSignedMode&&([t,o]=this.utils.extractSign(t),o&&!s.signed&&this.utils.signError()),this.isMutable.upper&&(t=t.toLowerCase()),e&&(t=e({input:t,settings:s}));let a=this.converter.decode(t,this.charsets[s.version],this.padChars[s.version],s.integrity,s.littleEndian);return i&&(a=i({input:t,output:a,settings:s})),this.utils.outputHandler.compile(a,s.outputType,s.littleEndian,o)}}
2 | /**
3 | * [BaseEx|Base91 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-91.js}
4 | *
5 | * @version 0.8.1
6 | * @author UmamiAppearance [mail@umamiappearance.eu]
7 | * @license MIT AND BSD-3-Clause (Base91, Copyright (c) 2000-2006 Joachim Henke)
8 | */class u extends l{constructor(...t){super(),this.converter={radix:91,bsEnc:0,bsDec:0},this.charsets.default=[...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"'],this.version="default",this.utils.validateArgs(t,!0)}encode(t,...e){const i=this.utils.validateArgs(e),n=this.utils.inputHandler.toBytes(t,i)[0];let r=0,s=0,o="";const a=this.charsets[i.version];if(n.forEach((t=>{if(s+=t<13){let t,e,i=13,n=s%8192;n<89&&(i=14,n=s%16384),s>>=i,r-=i,[t,e]=this.#n(n,91),o=`${o}${a[e]}${a[t]}`}})),r){let t,e;[t,e]=this.#n(s,91),o=o.concat(a[e]),(r>7||s>90)&&(o=o.concat(a[t]))}return this.utils.wrapOutput(o,i.options.lineWrap)}decode(t,...e){const i=this.utils.validateArgs(e),n=this.charsets[i.version];t=this.utils.normalizeInput(t);let r=[...t];i.integrity||(r=r.filter((t=>n.includes(t))));let s=r.length,a=!1;s%2&&(a=!0,s--);let l=0,u=0;const h=new Array;for(let t=0;t88?13:14;do{h.push(l%256),l>>=8,u-=8}while(u>7)}if(a){const t=r.at(s),e=n.indexOf(t);h.push(((e<0?t>4294967295?(i=this.makeDataView(8),i.setBigUint64(0,BigInt(t),e)):t>65535?(i=this.makeDataView(4),i.setUint32(0,t,e)):(i=this.makeDataView(2),i.setInt16(0,t,e)):i=new Uint16Array([0])}else n="float",i=this.floatingPoints(t,e);return[new Uint8Array(i.buffer),n]}static bigInts(t,e=!1){const i=new Array,n=e?"push":"unshift",r=18446744073709551616n;if(t<0)for(;t<-9223372036854775808n;)i[n](t%r),t>>=64n;else for(;t>=r;)i[n](t%r),t>>=64n;i[n](t);const s=8*i.length,o=this.makeDataView(s);return i.forEach(((t,i)=>{const n=8*i;o.setBigUint64(n,t,e)})),new Uint8Array(o.buffer)}static toBytes(t,e){let i,n=!1,r="bytes";if(t instanceof ArrayBuffer)i=new Uint8Array(t.slice());else if(ArrayBuffer.isView(t))i="undefined"!=typeof Buffer&&t instanceof Buffer?new Uint8Array(t):new Uint8Array(t.buffer.slice());else if("string"==typeof t||t instanceof String)i=(new TextEncoder).encode(t);else if("number"==typeof t){if(isNaN(t))throw new TypeError("Cannot proceed. Input is NaN.");if(t==1/0)throw new TypeError("Cannot proceed. Input is Infinity.");if(e.signed&&t<0&&(n=!0,t=-t),e.numberMode){const n=this.floatingPoints(t,e.littleEndian);i=new Uint8Array(n.buffer),r="float"}else[i,r]=this.numbers(t,e.littleEndian)}else if("bigint"==typeof t)e.signed&&t<0&&(n=!0,t*=-1n),i=this.bigInts(t,e.littleEndian),r="int";else{if(!Array.isArray(t))throw new TypeError("The provided input type can not be processed.");{const n=new Array;for(const i of t)n.push(...this.toBytes(i,e)[0]);i=Uint8Array.from(n)}}return[i,n,r]}}const n=i,r=class{static get typeList(){return["bigint64","bigint_n","biguint64","buffer","bytes","float32","float64","float_n","int8","int16","int32","int_n","str","uint8","uint16","uint32","uint_n","view"]}static getType(t){if(!this.typeList.includes(t))throw new TypeError(`Unknown output type: '${t}'`);return t}static makeTypedArrayBuffer(t,e,i,n){const r=t.byteLength,s=(e-t.byteLength%e)%e,o=n&&r>1?255:0;let a=t;if(s){a=new Uint8Array(r+s),a.fill(o);const e=i?0:s;a.set(t,e)}return a.buffer}static makeTypedArray(t,e,i,n){let r;if("int16"===e||"uint16"===e){const s=this.makeTypedArrayBuffer(t,2,i,n);r="int16"===e?new Int16Array(s):new Uint16Array(s)}else if("int32"===e||"uint32"===e||"float32"===e){const s=this.makeTypedArrayBuffer(t,4,i,n);r="int32"===e?new Int32Array(s):"uint32"===e?new Uint32Array(s):new Float32Array(s)}else if("bigint64"===e||"biguint64"===e||"float64"===e){const s=this.makeTypedArrayBuffer(t,8,i,n);r="bigint64"===e?new BigInt64Array(s):"biguint64"===e?new BigUint64Array(s):new Float64Array(s)}return r}static compile(t,e,n=!1,r=!1){let s;if(e=this.getType(e),r){let r;if(r=e.match(/^float/)?-this.compile(t,"float_n",n):-this.compile(t,"uint_n",n),"float_n"===e)return r;t=i.toBytes(r,{littleEndian:n,numberMode:!1,signed:!1})[0]}if("buffer"===e)s=t.buffer;else if("bytes"===e||"uint8"===e)s=t;else if("int8"===e)s=new Int8Array(t.buffer);else if("view"===e)s=new DataView(t.buffer);else if("str"===e)s=(new TextDecoder).decode(t);else if("uint_n"===e||"int_n"===e||"bigint_n"===e){if(1===t.length){const e=this.makeTypedArrayBuffer(t,2,n,r);t=new Uint8Array(e)}n&&t.reverse();let i=0n;t.forEach((t=>i=(i<<8n)+BigInt(t))),"uint_n"!==e&&(i=BigInt.asIntN(8*t.length,i)),s="bigint_n"!==e&&i>=Number.MIN_SAFE_INTEGER&&i<=Number.MAX_SAFE_INTEGER?Number(i):i}else if("float_n"===e)if(t.length<=4){let e;e=4===t.length?t:this.makeTypedArray(t,"float32",!1,r);s=new DataView(e.buffer).getFloat32(0,n)}else{if(!(t.length<=8))throw new RangeError("The provided input is to complex to be converted into a floating point.");{let e;e=8===t.length?t:this.makeTypedArray(t,"float64",!1,r);s=new DataView(e.buffer).getFloat64(0,n)}}else if("number"===e){if(8!==t.length)throw new TypeError("Type mismatch. Cannot convert into number.");const e=new Float64Array(t.buffer);s=Number(e)}else s=this.makeTypedArray(t,e,n,r);return s}};class s extends TypeError{constructor(){super("The input is signed but the converter is not set to treat input as signed.\nYou can pass the string 'signed' to the decode function or when constructing the converter."),this.name="SignError"}}class o extends TypeError{constructor(t,e=null){null===e&&(e=`Character '${t}' is not part of the charset.`),super(e),this.name="DecodingError"}}class a{constructor(t){this.root=t,this.converterArgs={},this.#t()}setIOHandlers(t=n,e=r){this.inputHandler=t,this.outputHandler=e}#t(){this.root.addCharset=(t,e,i=[],n=!0)=>{const r=(t,i,n)=>{if(0===n&&i.length)return console.warn(`This converter has no ${t}. The following argument was ignored:\n'${i}'`),[];let r=n;if("string"==typeof i&&(i=[...i]),Array.isArray(i))r=i.length,i=new Set(i);else if(!(i instanceof Set))throw new TypeError(`The ${t} must be one of the types:\n'str', 'set', 'array'."`);if(i.size===n)return[...i];if(r!==n)throw new Error(`Your ${t} has a length of ${r}. The converter requires a length of ${n}.`);{const i={};(e=[...e]).forEach((t=>{t in i?i[t]++:i[t]=1}));let r="";n<100&&(r=`${e.join("")}\n`,e.forEach((t=>{i[t]>1?r+="^":r+=" "})));const s=Object.keys(i).filter((t=>i[t]>1));throw new Error(`You have repetitive char(s) [ ${s.join(" | ")} ] in your ${t}. Make sure each character is unique.\n${r}`)}};if(this.root.frozenCharsets)throw new Error("The charsets of this converter cannot be changed.");if("string"!=typeof t)throw new TypeError("The charset name must be a string.");n&&t in this.root.charsets&&console.warn(`An existing charset with name ${t} will get replaced.`);const s=r("charset",e,this.root.converter.radix),o=r("padding set",i,this.root.padCharAmount);this.root.charsets[t]=s,o.length&&(this.root.padChars[t]=o),n&&console.info(`New charset '${t}' was added and is ready to use`)},this.root.setDefaultCharset=t=>{if(!(t in this.root.charsets)){const e=Object.keys(this.root.charsets).join("\n * ");throw new TypeError(`Charset ${t} was not found. Available charsets are:\n * ${e}`)}this.root.version=t}}#e(t){return t.map((t=>`'${t}'`)).join(", ")}toSignedStr(t,e){return t=t.replace(/^0+(?!$)/,""),e&&(t="-".concat(t)),t}extractSign(t){let e=!1;return"-"===t[0]&&(e=!0,t=t.slice(1)),[t,e]}#i(t,e,i,n){throw new TypeError([`'${t}'\n\nParameters:`,n?"\n * valid declarations for IO handlers are 'bytesOnly', 'bytesIn', 'bytesOut'":"",this.root.isMutable.signed?"\n * pass 'signed' to disable, 'unsigned' to enable the use of the twos's complement for negative integers":"",this.root.isMutable.littleEndian?"\n * 'be' for big , 'le' for little endian byte order for case conversion":"",this.root.isMutable.padding?"\n * pass 'pad' to fill up, 'nopad' to not fill up the output with the particular padding":"",this.root.isMutable.upper?"\n * valid args for changing the encoded output case are 'upper' and 'lower'":"",`\n * valid args for the output type are ${this.#e(i)}`,e?`\n * the option(s) for version/charset are: ${this.#e(e)}`:"","\n * valid args for integrity check are: 'integrity' and 'nointegrity'",this.root.hasDecimalMode?"\n * 'decimal' for decimal-mode (directly converts Numbers including decimal values, without byte-conversion)":"","\n * 'number' for number-mode (converts every number into a Float64Array to keep the natural js number type)",Object.keys(this.converterArgs).length?`\n * converter specific args:\n - ${(()=>Object.keys(this.converterArgs).map((t=>this.converterArgs[t].map((t=>`'${t}'`)).join(" and "))).join("\n - "))()}`:"","\n\nTraceback:"].join(""))}validateArgs(i,s=!1){const o={decimalMode:this.root.decimalMode,integrity:this.root.integrity,littleEndian:this.root.littleEndian,numberMode:this.root.numberMode,options:this.root.options,outputType:this.root.outputType,padding:this.root.padding,signed:this.root.signed,upper:this.root.upper,version:this.root.version};for(const t in this.converterArgs)o[t]=this.root[t];if(!i.length)return s&&this.setIOHandlers(),o;const a=t=>!!i.includes(t)&&(i.splice(i.indexOf(t),1),!0),l=Object.keys(this.root.charsets),u={integrity:["nointegrity","integrity"],littleEndian:["be","le"],padding:["nopad","pad"],signed:["unsigned","signed"],upper:["lower","upper"],...this.converterArgs};if(s)if(a("bytes_only"))this.setIOHandlers(t,e);else{const i=a("bytes_in")?t:n,s=a("bytes_out")?e:r;this.setIOHandlers(i,s)}const h=this.outputHandler.typeList;if(a("number")&&(o.numberMode=!0,o.outputType="float_n"),a("decimal")){if(!this.root.hasDecimalMode)throw TypeError("Argument 'decimal' is only allowed for converters with a non-integer base.");o.decimalMode=!0,o.outputType="decimal",o.numberMode&&(o.numberMode=!1,console.warn("-> number-mode was disabled due to the decimal-mode"))}if(i.forEach((t=>{if("object"!=typeof t)if(t=String(t).toLowerCase(),l.includes(t))o.version=t;else if(h.includes(t))o.outputType=t;else{let e=!0;for(const i in u)if(u[i].includes(t)){if(e=!1,!this.root.isMutable[i])throw TypeError(`Argument '${t}' is not allowed for this type of converter.`);o[i]=Boolean(u[i].indexOf(t))}e&&this.#i(t,l,h,s)}else o.options={...o.options,...t}})),o.padding&&o.signed&&(o.padding=!1,console.warn("-> padding was set to false due to the signed conversion")),s)for(const t in o)this.root[t]=o[t];return o}signError(){throw new s}wrapOutput(t,e=0){if(!e)return t;const i=new RegExp(`.{1,${e}}`,"gu");return t.match(i).join("\n")}normalizeInput(t,e=!1){return e?String(t):String(t).replace(/\s/g,"")}}class l{constructor(t=!0){this.charsets={},this.decimalMode=!1,this.frozenCharsets=!1,this.hasDecimalMode=!1,this.hasSignedMode=!1,this.integrity=!0,this.littleEndian=!1,this.numberMode=!1,this.outputType="buffer",this.padding=!1,this.padCharAmount=0,this.padChars={},this.nonASCII=!1,this.signed=!1,this.upper=null,t&&(this.utils=new a(this)),this.version="default",this.options={lineWrap:0},this.isMutable={integrity:!0,littleEndian:!1,padding:!1,signed:!1,upper:!1}}encode(t,e,i,...n){const r=this.utils.validateArgs(n);let[s,o,a]=this.utils.inputHandler.toBytes(t,r),l=null;e&&(l=e(r));let[u,h]=this.converter.encode(s,this.charsets[r.version],r.littleEndian,l);return r.signed&&(u=this.utils.toSignedStr(u,o)),r.upper&&(u=u.toUpperCase()),i&&(u=i({inputBytes:s,output:u,settings:r,zeroPadding:h,type:a})),this.utils.wrapOutput(u,r.options.lineWrap)}decode(t,e,i,n,...r){const s=this.utils.validateArgs(r);t=this.utils.normalizeInput(t,n);let o=!1;this.hasSignedMode&&([t,o]=this.utils.extractSign(t),o&&!s.signed&&this.utils.signError()),this.isMutable.upper&&(t=t.toLowerCase()),e&&(t=e({input:t,settings:s}));let a=this.converter.decode(t,this.charsets[s.version],this.padChars[s.version],s.integrity,s.littleEndian);return i&&(a=i({input:t,output:a,settings:s})),this.utils.outputHandler.compile(a,s.outputType,s.littleEndian,o)}}
2 | /**
3 | * [BaseEx|Base91 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-91.js}
4 | *
5 | * @version 0.8.1
6 | * @author UmamiAppearance [mail@umamiappearance.eu]
7 | * @license MIT AND BSD-3-Clause (Base91, Copyright (c) 2000-2006 Joachim Henke)
8 | */return class extends l{constructor(...t){super(),this.converter={radix:91,bsEnc:0,bsDec:0},this.charsets.default=[...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"'],this.version="default",this.utils.validateArgs(t,!0)}encode(t,...e){const i=this.utils.validateArgs(e),n=this.utils.inputHandler.toBytes(t,i)[0];let r=0,s=0,o="";const a=this.charsets[i.version];if(n.forEach((t=>{if(s+=t<13){let t,e,i=13,n=s%8192;n<89&&(i=14,n=s%16384),s>>=i,r-=i,[t,e]=this.#n(n,91),o=`${o}${a[e]}${a[t]}`}})),r){let t,e;[t,e]=this.#n(s,91),o=o.concat(a[e]),(r>7||s>90)&&(o=o.concat(a[t]))}return this.utils.wrapOutput(o,i.options.lineWrap)}decode(t,...e){const i=this.utils.validateArgs(e),n=this.charsets[i.version];t=this.utils.normalizeInput(t);let r=[...t];i.integrity||(r=r.filter((t=>n.includes(t))));let s=r.length,a=!1;s%2&&(a=!0,s--);let l=0,u=0;const h=new Array;for(let t=0;t88?13:14;do{h.push(l%256),l>>=8,u-=8}while(u>7)}if(a){const t=r.at(s),e=n.indexOf(t);h.push(((e<0?t>4294967295?(n=this.makeDataView(8),n.setBigUint64(0,BigInt(t),e)):t>65535?(n=this.makeDataView(4),n.setUint32(0,t,e)):(n=this.makeDataView(2),n.setInt16(0,t,e)):n=new Uint16Array([0])}else i="float",n=this.floatingPoints(t,e);return[new Uint8Array(n.buffer),i]}static bigInts(t,e=!1){const n=new Array,i=e?"push":"unshift",r=18446744073709551616n;if(t<0)for(;t<-9223372036854775808n;)n[i](t%r),t>>=64n;else for(;t>=r;)n[i](t%r),t>>=64n;n[i](t);const a=8*n.length,s=this.makeDataView(a);return n.forEach(((t,n)=>{const i=8*n;s.setBigUint64(i,t,e)})),new Uint8Array(s.buffer)}static toBytes(t,e){let n,i=!1,r="bytes";if(t instanceof ArrayBuffer)n=new Uint8Array(t.slice());else if(ArrayBuffer.isView(t))n="undefined"!=typeof Buffer&&t instanceof Buffer?new Uint8Array(t):new Uint8Array(t.buffer.slice());else if("string"==typeof t||t instanceof String)n=(new TextEncoder).encode(t);else if("number"==typeof t){if(isNaN(t))throw new TypeError("Cannot proceed. Input is NaN.");if(t==1/0)throw new TypeError("Cannot proceed. Input is Infinity.");if(e.signed&&t<0&&(i=!0,t=-t),e.numberMode){const i=this.floatingPoints(t,e.littleEndian);n=new Uint8Array(i.buffer),r="float"}else[n,r]=this.numbers(t,e.littleEndian)}else if("bigint"==typeof t)e.signed&&t<0&&(i=!0,t*=-1n),n=this.bigInts(t,e.littleEndian),r="int";else{if(!Array.isArray(t))throw new TypeError("The provided input type can not be processed.");{const i=new Array;for(const n of t)i.push(...this.toBytes(n,e)[0]);n=Uint8Array.from(i)}}return[n,i,r]}}class e{static get typeList(){return["bigint64","bigint_n","biguint64","buffer","bytes","float32","float64","float_n","int8","int16","int32","int_n","str","uint8","uint16","uint32","uint_n","view"]}static getType(t){if(!this.typeList.includes(t))throw new TypeError(`Unknown output type: '${t}'`);return t}static makeTypedArrayBuffer(t,e,n,i){const r=t.byteLength,a=(e-t.byteLength%e)%e,s=i&&r>1?255:0;let o=t;if(a){o=new Uint8Array(r+a),o.fill(s);const e=n?0:a;o.set(t,e)}return o.buffer}static makeTypedArray(t,e,n,i){let r;if("int16"===e||"uint16"===e){const a=this.makeTypedArrayBuffer(t,2,n,i);r="int16"===e?new Int16Array(a):new Uint16Array(a)}else if("int32"===e||"uint32"===e||"float32"===e){const a=this.makeTypedArrayBuffer(t,4,n,i);r="int32"===e?new Int32Array(a):"uint32"===e?new Uint32Array(a):new Float32Array(a)}else if("bigint64"===e||"biguint64"===e||"float64"===e){const a=this.makeTypedArrayBuffer(t,8,n,i);r="bigint64"===e?new BigInt64Array(a):"biguint64"===e?new BigUint64Array(a):new Float64Array(a)}return r}static compile(e,n,i=!1,r=!1){let a;if(n=this.getType(n),r){let r;if(r=n.match(/^float/)?-this.compile(e,"float_n",i):-this.compile(e,"uint_n",i),"float_n"===n)return r;e=t.toBytes(r,{littleEndian:i,numberMode:!1,signed:!1})[0]}if("buffer"===n)a=e.buffer;else if("bytes"===n||"uint8"===n)a=e;else if("int8"===n)a=new Int8Array(e.buffer);else if("view"===n)a=new DataView(e.buffer);else if("str"===n)a=(new TextDecoder).decode(e);else if("uint_n"===n||"int_n"===n||"bigint_n"===n){if(1===e.length){const t=this.makeTypedArrayBuffer(e,2,i,r);e=new Uint8Array(t)}i&&e.reverse();let t=0n;e.forEach((e=>t=(t<<8n)+BigInt(e))),"uint_n"!==n&&(t=BigInt.asIntN(8*e.length,t)),a="bigint_n"!==n&&t>=Number.MIN_SAFE_INTEGER&&t<=Number.MAX_SAFE_INTEGER?Number(t):t}else if("float_n"===n)if(e.length<=4){let t;t=4===e.length?e:this.makeTypedArray(e,"float32",!1,r);a=new DataView(t.buffer).getFloat32(0,i)}else{if(!(e.length<=8))throw new RangeError("The provided input is to complex to be converted into a floating point.");{let t;t=8===e.length?e:this.makeTypedArray(e,"float64",!1,r);a=new DataView(t.buffer).getFloat64(0,i)}}else if("number"===n){if(8!==e.length)throw new TypeError("Type mismatch. Cannot convert into number.");const t=new Float64Array(e.buffer);a=Number(t)}else a=this.makeTypedArray(e,n,i,r);return a}}
2 | /**
3 | * [BaseEx|Byte Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/byte-converter.js}
4 | *
5 | * @version 0.8.1
6 | * @author UmamiAppearance [mail@umamiappearance.eu]
7 | * @license MIT
8 | */const n=(()=>{const t=new Uint16Array([1]),e=new Uint8Array(t.buffer);return Boolean(e.at(0))})();class i{constructor(...t){this.littleEndian=n,this.numberMode=!1,this.outputType="buffer",this.utils={validateArgs:(t,n=!1)=>{const i={littleEndian:this.littleEndian,numberMode:this.numberMode,outputType:this.outputType,signed:!1};if(!t.length)return i;t.includes("number")&&(t.splice(t.indexOf("number"),1),i.numberMode=!0,i.outputType="float_n");const r=e.typeList.map((t=>`'${t}'`)).join(", ");if(t.forEach((t=>{if("le"===(t=String(t).toLowerCase()))i.littleEndian=!0;else if("be"===t)i.littleEndian=!1;else{if(!e.typeList.includes(t))throw new TypeError(`Invalid argument: '${t}.\nValid arguments are:\n'le', 'be', ${r}`);i.outputType=t}})),n)for(const t in i)this[t]=i[t];return i}},this.utils.validateArgs(t,!0)}encode(e,...n){const i=this.utils.validateArgs(n);return t.toBytes(e,i)[0]}decode(t,...n){const i=this.utils.validateArgs(n);return e.compile(t,i.outputType,i.littleEndian)}}export{i as default};
9 |
--------------------------------------------------------------------------------
/dist/converters/ByteConverter/byte-converter.iife.min.js:
--------------------------------------------------------------------------------
1 | var ByteConverter=function(){"use strict";class t{static makeDataView(t){const e=new ArrayBuffer(t);return new DataView(e)}static floatingPoints(t,e=!1){const n=this.makeDataView(8);return n.setFloat64(0,t,e),n}static numbers(t,e=!1){let n,i;if(Number.isInteger(t)){if(i="int",!Number.isSafeInteger(t)){let e,n,i;throw t<0?(e=Number.MIN_SAFE_INTEGER,n="smaller",i="MIN"):(e=Number.MAX_SAFE_INTEGER,n="bigger",i="MAX"),new RangeError(`The provided integer is ${n} than ${i}_SAFE_INTEGER: '${e}'\nData integrity is not guaranteed. Use a BigInt to avoid this issue.\n(If you see this error although a float was provided, the input has to many digits before the decimal point to store the decimal places in a float with 64 bits.)`)}t<0?t<-2147483648?(n=this.makeDataView(8),n.setBigInt64(0,BigInt(t),e)):t<-32768?(n=this.makeDataView(4),n.setInt32(0,t,e)):(n=this.makeDataView(2),n.setInt16(0,t,e)):t>0?t>4294967295?(n=this.makeDataView(8),n.setBigUint64(0,BigInt(t),e)):t>65535?(n=this.makeDataView(4),n.setUint32(0,t,e)):(n=this.makeDataView(2),n.setInt16(0,t,e)):n=new Uint16Array([0])}else i="float",n=this.floatingPoints(t,e);return[new Uint8Array(n.buffer),i]}static bigInts(t,e=!1){const n=new Array,i=e?"push":"unshift",r=18446744073709551616n;if(t<0)for(;t<-9223372036854775808n;)n[i](t%r),t>>=64n;else for(;t>=r;)n[i](t%r),t>>=64n;n[i](t);const a=8*n.length,s=this.makeDataView(a);return n.forEach(((t,n)=>{const i=8*n;s.setBigUint64(i,t,e)})),new Uint8Array(s.buffer)}static toBytes(t,e){let n,i=!1,r="bytes";if(t instanceof ArrayBuffer)n=new Uint8Array(t.slice());else if(ArrayBuffer.isView(t))n="undefined"!=typeof Buffer&&t instanceof Buffer?new Uint8Array(t):new Uint8Array(t.buffer.slice());else if("string"==typeof t||t instanceof String)n=(new TextEncoder).encode(t);else if("number"==typeof t){if(isNaN(t))throw new TypeError("Cannot proceed. Input is NaN.");if(t==1/0)throw new TypeError("Cannot proceed. Input is Infinity.");if(e.signed&&t<0&&(i=!0,t=-t),e.numberMode){const i=this.floatingPoints(t,e.littleEndian);n=new Uint8Array(i.buffer),r="float"}else[n,r]=this.numbers(t,e.littleEndian)}else if("bigint"==typeof t)e.signed&&t<0&&(i=!0,t*=-1n),n=this.bigInts(t,e.littleEndian),r="int";else{if(!Array.isArray(t))throw new TypeError("The provided input type can not be processed.");{const i=new Array;for(const n of t)i.push(...this.toBytes(n,e)[0]);n=Uint8Array.from(i)}}return[n,i,r]}}class e{static get typeList(){return["bigint64","bigint_n","biguint64","buffer","bytes","float32","float64","float_n","int8","int16","int32","int_n","str","uint8","uint16","uint32","uint_n","view"]}static getType(t){if(!this.typeList.includes(t))throw new TypeError(`Unknown output type: '${t}'`);return t}static makeTypedArrayBuffer(t,e,n,i){const r=t.byteLength,a=(e-t.byteLength%e)%e,s=i&&r>1?255:0;let o=t;if(a){o=new Uint8Array(r+a),o.fill(s);const e=n?0:a;o.set(t,e)}return o.buffer}static makeTypedArray(t,e,n,i){let r;if("int16"===e||"uint16"===e){const a=this.makeTypedArrayBuffer(t,2,n,i);r="int16"===e?new Int16Array(a):new Uint16Array(a)}else if("int32"===e||"uint32"===e||"float32"===e){const a=this.makeTypedArrayBuffer(t,4,n,i);r="int32"===e?new Int32Array(a):"uint32"===e?new Uint32Array(a):new Float32Array(a)}else if("bigint64"===e||"biguint64"===e||"float64"===e){const a=this.makeTypedArrayBuffer(t,8,n,i);r="bigint64"===e?new BigInt64Array(a):"biguint64"===e?new BigUint64Array(a):new Float64Array(a)}return r}static compile(e,n,i=!1,r=!1){let a;if(n=this.getType(n),r){let r;if(r=n.match(/^float/)?-this.compile(e,"float_n",i):-this.compile(e,"uint_n",i),"float_n"===n)return r;e=t.toBytes(r,{littleEndian:i,numberMode:!1,signed:!1})[0]}if("buffer"===n)a=e.buffer;else if("bytes"===n||"uint8"===n)a=e;else if("int8"===n)a=new Int8Array(e.buffer);else if("view"===n)a=new DataView(e.buffer);else if("str"===n)a=(new TextDecoder).decode(e);else if("uint_n"===n||"int_n"===n||"bigint_n"===n){if(1===e.length){const t=this.makeTypedArrayBuffer(e,2,i,r);e=new Uint8Array(t)}i&&e.reverse();let t=0n;e.forEach((e=>t=(t<<8n)+BigInt(e))),"uint_n"!==n&&(t=BigInt.asIntN(8*e.length,t)),a="bigint_n"!==n&&t>=Number.MIN_SAFE_INTEGER&&t<=Number.MAX_SAFE_INTEGER?Number(t):t}else if("float_n"===n)if(e.length<=4){let t;t=4===e.length?e:this.makeTypedArray(e,"float32",!1,r);a=new DataView(t.buffer).getFloat32(0,i)}else{if(!(e.length<=8))throw new RangeError("The provided input is to complex to be converted into a floating point.");{let t;t=8===e.length?e:this.makeTypedArray(e,"float64",!1,r);a=new DataView(t.buffer).getFloat64(0,i)}}else if("number"===n){if(8!==e.length)throw new TypeError("Type mismatch. Cannot convert into number.");const t=new Float64Array(e.buffer);a=Number(t)}else a=this.makeTypedArray(e,n,i,r);return a}}
2 | /**
3 | * [BaseEx|Byte Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/byte-converter.js}
4 | *
5 | * @version 0.8.1
6 | * @author UmamiAppearance [mail@umamiappearance.eu]
7 | * @license MIT
8 | */const n=(()=>{const t=new Uint16Array([1]),e=new Uint8Array(t.buffer);return Boolean(e.at(0))})();return class{constructor(...t){this.littleEndian=n,this.numberMode=!1,this.outputType="buffer",this.utils={validateArgs:(t,n=!1)=>{const i={littleEndian:this.littleEndian,numberMode:this.numberMode,outputType:this.outputType,signed:!1};if(!t.length)return i;t.includes("number")&&(t.splice(t.indexOf("number"),1),i.numberMode=!0,i.outputType="float_n");const r=e.typeList.map((t=>`'${t}'`)).join(", ");if(t.forEach((t=>{if("le"===(t=String(t).toLowerCase()))i.littleEndian=!0;else if("be"===t)i.littleEndian=!1;else{if(!e.typeList.includes(t))throw new TypeError(`Invalid argument: '${t}.\nValid arguments are:\n'le', 'be', ${r}`);i.outputType=t}})),n)for(const t in i)this[t]=i[t];return i}},this.utils.validateArgs(t,!0)}encode(e,...n){const i=this.utils.validateArgs(n);return t.toBytes(e,i)[0]}decode(t,...n){const i=this.utils.validateArgs(n);return e.compile(t,i.outputType,i.littleEndian)}}}();
9 |
--------------------------------------------------------------------------------
/examples/assets/prism.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Prism.js Custom Theme for https://github.com/UmamiAppearance/JSLiveExamples
3 | *
4 | * Based on:
5 | * Coldark Theme for Prism.js (variation: Cold)
6 | * from: Armand Philippot
7 | * homepage: https://github.com/ArmandPhilippot/coldark-prism
8 | * license: MIT
9 | *
10 | * variations inspired by:
11 | * JavaScript code prettifier
12 | * from: Google
13 | * homepage: https://github.com/googlearchive/code-prettify
14 | *
15 | * NOTE: This is not a fully featured Theme for Prism.js
16 | */
17 |
18 | code[class*="language-"],
19 | pre[class*="language-"] {
20 | color: #111b27;
21 | font-family: monospace;
22 | text-align: left;
23 | white-space: pre;
24 | word-spacing: normal;
25 | word-break: normal;
26 | word-wrap: normal;
27 | line-height: 1.5;
28 | -moz-tab-size: 4;
29 | -o-tab-size: 4;
30 | tab-size: 4;
31 | -webkit-hyphens: none;
32 | -moz-hyphens: none;
33 | -ms-hyphens: none;
34 | hyphens: none;
35 | }
36 |
37 | /* Code blocks */
38 | pre[class*="language-"] {
39 | padding: 1em;
40 | margin: 0.5em 0;
41 | overflow: auto;
42 | }
43 |
44 | /* Inline code */
45 | :not(pre) > code[class*="language-"] {
46 | white-space: normal;
47 | }
48 |
49 | .token.comment,
50 | .token.prolog,
51 | .token.doctype,
52 | .token.cdata {
53 | color: #800;
54 | }
55 |
56 | .token.punctuation {
57 | color: #111b27;
58 | }
59 |
60 | .token.delimiter.important,
61 | .token.selector .parent,
62 | .token.tag,
63 | .token.tag .token.punctuation {
64 | color: #006d6d;
65 | }
66 |
67 | .token.attr-name,
68 | .token.boolean,
69 | .token.boolean.important,
70 | .token.number,
71 | .token.constant,
72 | .token.selector .token.attribute {
73 | color: #755f00;
74 | }
75 |
76 | .token.class-name,
77 | .token.key,
78 | .token.parameter,
79 | .token.property,
80 | .token.property-access,
81 | .token.variable {
82 | color: #005a8e;
83 | }
84 |
85 | .token.attr-value,
86 | .token.inserted,
87 | .token.color,
88 | .token.selector .token.value,
89 | .token.string,
90 | .token.string .token.url-link {
91 | color: #080;
92 | }
93 |
94 | .token.builtin,
95 | .token.keyword-array,
96 | .token.package,
97 | .token.regex {
98 | color: #af00af;
99 | }
100 |
101 | .token.function,
102 | .token.selector .token.class,
103 | .token.selector .token.id {
104 | color: #7c00aa;
105 | }
106 |
107 | .token.atrule .token.rule,
108 | .token.combinator,
109 | .token.keyword,
110 | .token.operator,
111 | .token.pseudo-class,
112 | .token.pseudo-element,
113 | .token.selector,
114 | .token.unit {
115 | color: #008;
116 | }
117 |
118 | .token.deleted,
119 | .token.important {
120 | color: #c22f2e;
121 | }
122 |
123 | .token.keyword-this,
124 | .token.this {
125 | color: #005a8e;
126 | }
127 |
128 | .token.important,
129 | .token.keyword-this,
130 | .token.this,
131 | .token.bold {
132 | font-weight: bold;
133 | }
134 |
135 | .token.delimiter.important {
136 | font-weight: inherit;
137 | }
138 |
139 | .token.italic {
140 | font-style: italic;
141 | }
142 |
143 | .token.entity {
144 | cursor: help;
145 | }
146 |
147 | .language-markdown .token.title,
148 | .language-markdown .token.title .token.punctuation {
149 | color: #005a8e;
150 | font-weight: bold;
151 | }
152 |
153 | .language-markdown .token.blockquote.punctuation {
154 | color: #af00af;
155 | }
156 |
157 | .language-markdown .token.code {
158 | color: #006d6d;
159 | }
160 |
161 | .language-markdown .token.hr.punctuation {
162 | color: #005a8e;
163 | }
164 |
165 | .language-markdown .token.url > .token.content {
166 | color: #116b00;
167 | }
168 |
169 | .language-markdown .token.url-link {
170 | color: #755f00;
171 | }
172 |
173 | .language-markdown .token.list.punctuation {
174 | color: #af00af;
175 | }
176 |
177 | .language-markdown .token.table-header {
178 | color: #111b27;
179 | }
180 |
181 | .language-json .token.operator {
182 | color: #111b27;
183 | }
184 |
185 | .language-scss .token.variable {
186 | color: #006d6d;
187 | }
188 |
--------------------------------------------------------------------------------
/lib/big.js/big.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * big.js v6.2.1 // Copyright (c) 2022 Michael Mclaughlin // https://github.com/MikeMcl/big.js/LICENCE.md // Modified (reduced) and minified for BaseEx
3 | */
4 | let DP=20,RM=1,MAX_DP=1e6,NE=-7,PE=21,STRICT=!1,NAME="[big.js] ",INVALID=NAME+"Invalid ",INVALID_DP=INVALID+"decimal places",INVALID_RM=INVALID+"rounding mode",P={},NUMERIC=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i;function _Big_(){function Big(n){let x=this;if(!(x instanceof Big))return void 0===n?_Big_():new Big(n);if(n instanceof Big)x.s=n.s,x.e=n.e,x.c=n.c.slice();else{if("string"!=typeof n){if(!0===Big.strict&&"bigint"!=typeof n)throw TypeError(INVALID+"value");n=0===n&&1/n<0?"-0":String(n)}parse(x,n)}x.constructor=Big}return Big.prototype=P,Big.DP=DP,Big.RM=RM,Big.NE=NE,Big.PE=PE,Big.strict=STRICT,Big.roundDown=0,Big.roundHalfUp=1,Big.roundHalfEven=2,Big.roundUp=3,Big}function parse(x,n){let e,i,nl;if(!NUMERIC.test(n))throw Error(`${INVALID}number`);for(x.s="-"==n.charAt(0)?(n=n.slice(1),-1):1,(e=n.indexOf("."))>-1&&(n=n.replace(".","")),(i=n.search(/e/i))>0?(e<0&&(e=i),e+=+n.slice(i+1),n=n.substring(0,i)):e<0&&(e=n.length),nl=n.length,i=0;i0&&"0"==n.charAt(--nl););for(x.e=e-i-1,x.c=[],e=0;i<=nl;)x.c[e++]=+n.charAt(i++)}return x}function round(x,sd,rm,more){let xc=x.c;if(void 0===rm&&(rm=x.constructor.RM),0!==rm&&1!==rm&&2!==rm&&3!==rm)throw Error(INVALID_RM);if(sd<1)more=3===rm&&(more||!!xc[0])||0===sd&&(1===rm&&xc[0]>=5||2===rm&&(xc[0]>5||5===xc[0]&&(more||void 0!==xc[1]))),xc.length=1,more?(x.e=x.e-sd+1,xc[0]=1):xc[0]=x.e=0;else if(sd=5||2===rm&&(xc[sd]>5||5===xc[sd]&&(more||void 0!==xc[sd+1]||1&xc[sd-1]))||3===rm&&(more||!!xc[0]),xc.length=sd,more)for(;++xc[--sd]>9;)if(xc[sd]=0,0===sd){++x.e,xc.unshift(1);break}for(sd=xc.length;!xc[--sd];)xc.pop()}return x}function stringify(x,doExponential,isNonzero){let e=x.e,s=x.c.join(""),n=s.length;if(doExponential)s=s.charAt(0)+(n>1?"."+s.slice(1):"")+(e<0?"e":"e+")+e;else if(e<0){for(;++e;)s="0"+s;s="0."+s}else if(e>0)if(++e>n)for(e-=n;e--;)s+="0";else e1&&(s=s.charAt(0)+"."+s.slice(1));return x.s<0&&isNonzero?"-"+s:s}P.abs=function(){let x=new this.constructor(this);return x.s=1,x},P.cmp=function(y){let isneg,x=this,xc=x.c,yc=(y=new x.constructor(y)).c,i=x.s,j=y.s,k=x.e,l=y.e;if(!xc[0]||!yc[0])return xc[0]?i:yc[0]?-j:0;if(i!=j)return i;if(isneg=i<0,k!=l)return k>l^isneg?1:-1;for(j=(k=xc.length)<(l=yc.length)?k:l,i=-1;++iyc[i]^isneg?1:-1;return k==l?0:k>l^isneg?1:-1},P.eq=function(y){return 0===this.cmp(y)},P.gt=function(y){return this.cmp(y)>0},P.gte=function(y){return this.cmp(y)>-1},P.lt=function(y){return this.cmp(y)<0},P.lte=function(y){return this.cmp(y)<1},P.minus=P.sub=function(y){let i,j,t,xlty,x=this,Big=x.constructor,a=x.s,b=(y=new Big(y)).s;if(a!=b)return y.s=-b,x.plus(y);let xc=x.c.slice(),xe=x.e,yc=y.c,ye=y.e;if(!xc[0]||!yc[0])return yc[0]?y.s=-b:xc[0]?y=new Big(x):y.s=1,y;if(a=xe-ye){for((xlty=a<0)?(a=-a,t=xc):(ye=xe,t=yc),t.reverse(),b=a;b--;)t.push(0);t.reverse()}else for(j=((xlty=xc.length0)for(;b--;)xc[i++]=0;for(b=i;j>a;){if(xc[--j]0?(ye=xe,t=yc):(e=-e,t=xc),t.reverse();e--;)t.push(0);t.reverse()}for(xc.length-yc.length<0&&(t=yc,yc=xc,xc=t),e=yc.length,k=0;e;xc[e]%=10)k=(xc[--e]=xc[e]+yc[e]+k)/10|0;for(k&&(xc.unshift(k),++ye),e=xc.length;0===xc[--e];)xc.pop();return y.c=xc,y.e=ye,y},P.round=function(dp,rm){if(void 0===dp)dp=0;else if(dp!==~~dp||dp<-MAX_DP||dp>MAX_DP)throw Error(INVALID_DP);return round(new this.constructor(this),dp+this.e+1,rm)},P.toFixed=function(dp,rm){let x=this,n=x.c[0];if(void 0!==dp){if(dp!==~~dp||dp<0||dp>MAX_DP)throw Error(INVALID_DP);for(x=round(new x.constructor(x),dp+x.e+1,rm),dp=dp+x.e+1;x.c.length=Big.PE,!!x.c[0])},P.toNumber=function(){let n=Number(stringify(this,!0,!0));if(!0===this.constructor.strict&&!this.eq(n.toString()))throw Error(NAME+"Imprecise conversion");return n};export const Big=_Big_();export default Big;
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "base-ex",
3 | "version": "0.8.1",
4 | "description": "A collection of classes for data representation written in JavaScript.",
5 | "main": "./cjs/base-ex.cjs",
6 | "module": "./src/base-ex.js",
7 | "exports": {
8 | "import": "./src/base-ex.js",
9 | "require": "./cjs/base-ex.cjs"
10 | },
11 | "type": "module",
12 | "directories": {
13 | "examples": "examples",
14 | "cjs": "cjs",
15 | "dist": "dist",
16 | "test": "test",
17 | "src": "src"
18 | },
19 | "scripts": {
20 | "build": "rollup -c",
21 | "build:bytes": "rollup -c --environment BYTES_ONLY",
22 | "build:cjs": "rollup src/base-ex.js --file cjs/base-ex.cjs --format cjs -m",
23 | "lint": "eslint ./src/*",
24 | "lint:fix": "eslint ./src/* --fix",
25 | "start": "http-server -a localhost -o ./examples/demo.html",
26 | "start:lan": "http-server -o ./examples/demo.html",
27 | "test": "remembrance && ava",
28 | "test:dev": "ava"
29 | },
30 | "repository": {
31 | "type": "git",
32 | "url": "git+https://github.com/UmamiAppearance/BaseExJS.git"
33 | },
34 | "keywords": [
35 | "unary",
36 | "binary",
37 | "bytes",
38 | "base conversion",
39 | "Base2",
40 | "Base8",
41 | "Base10",
42 | "Base16",
43 | "Base32",
44 | "Base36",
45 | "Base58",
46 | "Base62",
47 | "Base64",
48 | "UUencode",
49 | "Base85",
50 | "Base91",
51 | "LEB128",
52 | "Ecoji",
53 | "Base2048",
54 | "BasePhi",
55 | "Golden Ratio Base"
56 | ],
57 | "author": "UmamiAppearance",
58 | "license": "MIT",
59 | "bugs": {
60 | "url": "https://github.com/UmamiAppearance/BaseExJS/issues",
61 | "email": "mail@umamiappearance.eu"
62 | },
63 | "homepage": "https://github.com/UmamiAppearance/BaseExJS#readme",
64 | "devDependencies": {
65 | "@rollup/plugin-terser": "^0.4.3",
66 | "ava": "^5.3.1",
67 | "big.js": "^6.2.1",
68 | "eslint": "^8.44.0",
69 | "http-server": "^14.1.1",
70 | "remembrance": "^0.3.1",
71 | "rollup": "^3.26.1",
72 | "rollup-plugin-your-function": "^0.5.3"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/rollup.config.mjs:
--------------------------------------------------------------------------------
1 | import { readdirSync } from "fs";
2 | import terser from "@rollup/plugin-terser";
3 | import { yourFunction } from "rollup-plugin-your-function";
4 |
5 | const toInitCap = str => {
6 | if (str === "uuencode") {
7 | return "UUencode";
8 | }
9 |
10 | if (str === "leb-128") {
11 | return "LEB128";
12 | }
13 |
14 | return str
15 | .at(0)
16 | .toUpperCase()
17 | .concat(
18 | str.slice(1))
19 | .replaceAll(/-./g, (s) => s
20 | .at(1)
21 | .toUpperCase()
22 | );
23 | }
24 | const converters = new Array();
25 | const bytesOnly = process.argv.includes("BYTES_ONLY");
26 |
27 | const makeConverter = (inputFile, srcDir, distDir, useGroupDir, t=terser()) => {
28 | const filename = inputFile.replace(/\.js$/, "");
29 | const modName = toInitCap(filename);
30 | const groupDir = (useGroupDir) ? `${modName}/`: "";
31 |
32 | const converter = {
33 | input: `${srcDir}${inputFile}`,
34 | output: [
35 | {
36 | format: "iife",
37 | name: modName,
38 | file: `${distDir}${groupDir}${filename}.iife.js`
39 | },
40 | {
41 | format: "iife",
42 | name: modName,
43 | file: `${distDir}${groupDir}${filename}.iife.min.js`,
44 | plugins: [t]
45 | },
46 | {
47 | format: "es",
48 | name: modName,
49 | file: `${distDir}${groupDir}${filename}.esm.js`
50 | },
51 | {
52 | format: "es",
53 | name: modName,
54 | file: `${distDir}${groupDir}${filename}.esm.min.js`,
55 | plugins: [t]
56 | },
57 | ]
58 | };
59 |
60 | if (bytesOnly) {
61 | converter.plugins = [
62 | yourFunction({
63 | include: "**/utils.js",
64 | fn: source => {
65 | const code = source
66 | .replace(
67 | /DEFAULT_INPUT_HANDLER ?= ?SmartInput/,
68 | "DEFAULT_INPUT_HANDLER = BytesInput"
69 | )
70 | .replace(
71 | /DEFAULT_OUTPUT_HANDLER ?= ?SmartOutput/,
72 | "DEFAULT_OUTPUT_HANDLER = BytesOutput"
73 | );
74 | return code;
75 | }
76 | })
77 | ]
78 | }
79 |
80 | converters.push(converter);
81 | }
82 |
83 | // allow only the main license for base-ex class
84 | const selectiveTerser = terser({
85 | format: {
86 | comments: (_, comment) => {
87 | const text = comment.value;
88 | const type = comment.type;
89 | return (
90 | type === "comment2" &&
91 | !(/BaseEx\|\w+/).test(text) &&
92 | (/@license/i).test(text)
93 | );
94 | }
95 | }
96 | });
97 |
98 | makeConverter("base-ex.js", "src/", "dist/", false, selectiveTerser);
99 |
100 | readdirSync("./src/converters").forEach(inputFile => {
101 | makeConverter(inputFile, "src/converters/", "dist/converters/", true)
102 | });
103 |
104 |
105 | export default converters;
106 |
--------------------------------------------------------------------------------
/src/base-ex.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx]{@link https://github.com/UmamiAppearance/BaseExJS}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | /* eslint-disable sort-imports */
10 |
11 | import Base1 from "./converters/base-1.js";
12 | import Base16 from "./converters/base-16.js";
13 | import Base32 from "./converters/base-32.js";
14 | import Base58 from "./converters/base-58.js";
15 | import Base64 from "./converters/base-64.js";
16 | import UUencode from "./converters/uuencode.js";
17 | import Base85 from "./converters/base-85.js";
18 | import Base91 from "./converters/base-91.js";
19 | import LEB128 from "./converters/leb-128.js";
20 | import Ecoji from "./converters/ecoji.js";
21 | import Base2048 from "./converters/base-2048.js";
22 | import SimpleBase from "./converters/simple-base.js";
23 | import BasePhi from "./converters/base-phi.js";
24 | import ByteConverter from "./converters/byte-converter.js";
25 |
26 | import { DEFAULT_OUTPUT_HANDLER } from "./utils.js";
27 |
28 | /**
29 | * BaseEx Converter Collection.
30 | * ---------------------------
31 | * This class holds almost any available converter
32 | * of the whole BaseEx converter collection. The
33 | * instances are ready to use. Various input can be
34 | * converted to a base string or the base string can be
35 | * decoded into various formats.
36 | */
37 | class BaseEx {
38 |
39 | /**
40 | * BaseEx Base Collection Constructor.
41 | * @param {string} [outputType] - Output type.
42 | */
43 | constructor(outputType="buffer") {
44 |
45 | if (!DEFAULT_OUTPUT_HANDLER.typeList.includes(outputType)) {
46 | let message = `Invalid argument '${outputType}' for output type. Allowed types are:\n`;
47 | message = message.concat(DEFAULT_OUTPUT_HANDLER.typeList.join(", "));
48 |
49 | throw new TypeError(message);
50 | }
51 |
52 | this.base1 = new Base1("default", outputType);
53 | this.base16 = new Base16("default", outputType);
54 | this.base32_crockford = new Base32("rfc4648", outputType);
55 | this.base32_rfc3548 = new Base32("rfc3548", outputType);
56 | this.base32_rfc4648 = new Base32("rfc4648", outputType);
57 | this.base32_zbase32 = new Base32("zbase32", outputType);
58 | this.base58 = new Base58("default", outputType);
59 | this.base58_bitcoin = new Base58("bitcoin", outputType);
60 | this.base58_flickr = new Base58("flickr", outputType);
61 | this.base64 = new Base64("default", outputType);
62 | this.base64_urlsafe = new Base64("urlsafe", outputType);
63 | this.uuencode = new UUencode("default", outputType);
64 | this.uuencode_original = new UUencode("original", outputType);
65 | this.xxencode = new UUencode("xx", outputType);
66 | this.base85_adobe = new Base85("adobe", outputType);
67 | this.base85_ascii = new Base85("ascii85", outputType);
68 | this.base85_z85 = new Base85("z85", outputType);
69 | this.base91 = new Base91("default",outputType);
70 | this.leb128 = new LEB128("default", outputType);
71 | this.ecoji_v1 = new Ecoji("emojis_v1", outputType);
72 | this.ecoji_v2 = new Ecoji("emojis_v2", outputType);
73 | this.base2048 = new Base2048("default", outputType);
74 | this.basePhi = new BasePhi("default", outputType);
75 | this.byteConverter = new ByteConverter(outputType);
76 |
77 | this.simpleBase = {};
78 | for (let i=2; i<=62; i++) {
79 | this.simpleBase[`base${i}`] = new SimpleBase(i, outputType);
80 | }
81 | }
82 | }
83 |
84 | export {
85 | Base1,
86 | Base16,
87 | Base32,
88 | Base58,
89 | Base64,
90 | UUencode,
91 | Base85,
92 | Base91,
93 | LEB128,
94 | Ecoji,
95 | Base2048,
96 | SimpleBase,
97 | BasePhi,
98 | ByteConverter,
99 | BaseEx
100 | };
101 |
--------------------------------------------------------------------------------
/src/converters/base-1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Base1 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-1.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 |
11 | /**
12 | * BaseEx Base 1 Converter.
13 | * -----------------------
14 | * This is a unary/base1 converter. It is converting input
15 | * to a decimal number, which is converted into an unary
16 | * string. Due to the limitations on string (or array) length
17 | * it is only suitable for the conversions of numbers up to
18 | * roughly 2^28.
19 | */
20 | export default class Base1 extends BaseTemplate {
21 |
22 | /**
23 | * BaseEx Base1 Constructor.
24 | * @param {...string} [args] - Converter settings.
25 | */
26 | constructor(...args) {
27 | super();
28 |
29 | // All chars in the string are used and picked randomly (prob. suitable for obfuscation)
30 | this.charsets.all = [..." !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"];
31 |
32 | // The sequence is used from left to right again and again
33 | this.charsets.sequence = [..."Hello World!"];
34 |
35 | // Standard unary string with one character
36 | this.charsets.default = ["1"];
37 |
38 | // Telly Mark string, using hash for 5 and vertical bar for 1
39 | this.charsets.tmark = ["|", "#"];
40 |
41 | // Base 10 converter
42 | this.converter = new BaseConverter(10, 0, 0);
43 |
44 | // converter settings
45 | this.hasSignedMode = true;
46 | this.littleEndian = true;
47 | this.signed = true;
48 |
49 | // mutable extra args
50 | this.isMutable.charsets = false;
51 | this.isMutable.signed = true;
52 | this.isMutable.upper = true;
53 |
54 | // apply user settings
55 | this.utils.validateArgs(args, true);
56 | }
57 |
58 |
59 | /**
60 | * BaseEx Base1 Encoder.
61 | * @param {*} input - Input according to the used byte converter.
62 | * @param {...str} [args] - Converter settings.
63 | * @returns {string} - Base1 encoded string.
64 | */
65 | encode(input, ...args) {
66 |
67 | // argument validation and input settings
68 | const settings = this.utils.validateArgs(args);
69 |
70 | let inputBytes, negative;
71 | [inputBytes, negative,] = this.utils.inputHandler.toBytes(input, settings);
72 |
73 | // Convert to BaseRadix string
74 | let base10 = this.converter.encode(inputBytes, null, settings.littleEndian)[0];
75 |
76 | let n = BigInt(base10);
77 |
78 | // Limit the input before it even starts.
79 | // The executing engine will most likely
80 | // give up much earlier.
81 | // (2**29-24 during tests)
82 |
83 | if (n > Number.MAX_SAFE_INTEGER) {
84 | throw new RangeError("Invalid string length.");
85 | } else if (n > 16777216) {
86 | console.warn("The string length is really long. The JavaScript engine may have memory issues generating the output string.");
87 | }
88 |
89 | n = Number(n);
90 |
91 | const charset = this.charsets[settings.version];
92 | const charAmount = charset.length;
93 | let output = "";
94 |
95 | // Convert to unary in respect to the version differences
96 | if (charAmount === 1) {
97 | output = charset.at(0).repeat(n)
98 | } else if (settings.version === "all") {
99 | for (let i=0; i 4) {
106 | output = charset.at(1).repeat((n - singulars) / 5);
107 | }
108 | output += charset.at(0).repeat(singulars);
109 | } else {
110 | for (let i=0; i {
67 |
68 | // Remove "0x" if present
69 | normInput = normInput.replace(/^0x/, "");
70 |
71 | // remove non-charset characters if integrity
72 | // check is disabled
73 | if (!settings.integrity) {
74 | normInput = normInput
75 | .toLowerCase()
76 | .replace(/[^0-9a-f]/g, "");
77 | }
78 |
79 | // Ensure even number of characters
80 | if (normInput.length % 2) {
81 | normInput = "0".concat(normInput);
82 | }
83 |
84 | return normInput;
85 | }
86 |
87 | return super.decode(input, normalizeInput, null, false, ...args);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/converters/base-2048.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Base2048 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-2048.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseTemplate } from "../core.js";
10 | import { DecodingError } from "../utils.js";
11 |
12 | /**
13 | * BaseEx Base 2048 Converter.
14 | * ------------------------
15 | * This is a base2048/converter. Various input can be
16 | * converted to a hex string or a hex string can be
17 | * decoded into various formats. It is possible to
18 | * convert in both signed and unsigned mode.
19 | *
20 | * @see https://github.com/qntm/base2048
21 | */
22 | export default class Base2048 extends BaseTemplate {
23 |
24 | /**
25 | * BaseEx Base2048 Constructor.
26 | * @param {...string} [args] - Converter settings.
27 | */
28 | constructor(...args) {
29 | super();
30 |
31 | // converter (properties only)
32 | this.converter = {
33 | radix: 2048,
34 | bsEnc: 11,
35 | bsEncPad: 3,
36 | bsDec: 8
37 | }
38 |
39 | // default settings
40 | this.charsets.default = [..."89ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÆÐØÞßæðøþĐđĦħıĸŁłŊŋŒœŦŧƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƢƣƤƥƦƧƨƩƪƫƬƭƮƱƲƳƴƵƶƷƸƹƺƻƼƽƾƿǀǁǂǃǝǤǥǶǷȜȝȠȡȢȣȤȥȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯͰͱͲͳͶͷͻͼͽͿΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρςστυφχψωϏϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϳϷϸϺϻϼϽϾϿЂЄЅІЈЉЊЋЏАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзиклмнопрстуфхцчшщъыьэюяђєѕіјљњћџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѸѹѺѻѼѽѾѿҀҁҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӃӄӅӆӇӈӉӊӋӌӍӎӏӔӕӘәӠӡӨөӶӷӺӻӼӽӾӿԀԁԂԃԄԅԆԇԈԉԊԋԌԍԎԏԐԑԒԓԔԕԖԗԘԙԚԛԜԝԞԟԠԡԢԣԤԥԦԧԨԩԪԫԬԭԮԯԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՒՓՔՕՖաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆאבגדהוזחטיךכלםמןנסעףפץצקרשתװױײؠءابةتثجحخدذرزسشصضطظعغػؼؽؾؿفقكلمنهوىي٠١٢٣٤٥٦٧٨٩ٮٯٱٲٳٴٹٺٻټٽپٿڀځڂڃڄڅچڇڈډڊڋڌڍڎڏڐڑڒړڔڕږڗژڙښڛڜڝڞڟڠڡڢڣڤڥڦڧڨکڪګڬڭڮگڰڱڲڳڴڵڶڷڸڹںڻڼڽھڿہۃۄۅۆۇۈۉۊۋیۍێۏېۑےەۮۯ۰۱۲۳۴۵۶۷۸۹ۺۻۼۿܐܒܓܔܕܖܗܘܙܚܛܜܝܞܟܠܡܢܣܤܥܦܧܨܩܪܫܬܭܮܯݍݎݏݐݑݒݓݔݕݖݗݘݙݚݛݜݝݞݟݠݡݢݣݤݥݦݧݨݩݪݫݬݭݮݯݰݱݲݳݴݵݶݷݸݹݺݻݼݽݾݿހށނރބޅކއވމފދތލގޏސޑޒޓޔޕޖޗޘޙޚޛޜޝޞޟޠޡޢޣޤޥޱ߀߁߂߃߄߅߆߇߈߉ߊߋߌߍߎߏߐߑߒߓߔߕߖߗߘߙߚߛߜߝߞߟߠߡߢߣߤߥߦߧߨߩߪࠀࠁࠂࠃࠄࠅࠆࠇࠈࠉࠊࠋࠌࠍࠎࠏࠐࠑࠒࠓࠔࠕࡀࡁࡂࡃࡄࡅࡆࡇࡈࡉࡊࡋࡌࡍࡎࡏࡐࡑࡒࡓࡔࡕࡖࡗࡘࡠࡡࡢࡣࡤࡥࡦࡧࡨࡩࡪࢠࢡࢢࢣࢤࢥࢦࢧࢨࢩࢪࢫࢬࢭࢮࢯࢰࢱࢲࢳࢴࢶࢷࢸࢹࢺࢻࢼࢽऄअआइईउऊऋऌऍऎएऐऑऒओऔकखगघङचछजझञटठडढणतथदधनपफबभमयरलळवशषसहऽॐॠॡ०१२३४५६७८९ॲॳॴॵॶॷॸॹॺॻॼॽॾॿঀঅআইঈউঊঋঌএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহঽৎৠৡ০১২৩৪৫৬৭৮৯ৰৱ৴৵৶৷৸৹ৼਅਆਇਈਉਊਏਐਓਔਕਖਗਘਙਚਛਜਝਞਟਠਡਢਣਤਥਦਧਨਪਫਬਭਮਯਰਲਵਸਹੜ੦੧੨੩੪੫੬੭੮੯ੲੳੴઅઆઇઈઉઊઋઌઍએઐઑઓઔકખગઘઙચછજઝઞટઠડઢણતથદધનપફબભમયરલળવશષસહઽૐૠૡ૦૧૨૩૪૫૬૭૮૯ૹଅଆଇଈଉଊଋଌଏଐଓଔକଖଗଘଙଚଛଜଝଞଟଠଡଢଣତଥଦଧନପଫବଭମଯରଲଳଵଶଷସହଽୟୠୡ୦୧୨୩୪୫୬୭୮୯ୱ୲୳୴୵୶୷ஃஅஆஇஈஉஊஎஏஐஒஓகஙசஜஞடணதநனபமயரறலளழவஶஷஸஹௐ௦௧௨௩௪௫௬௭௮௯௰௱௲అఆఇఈఉఊఋఌఎఏఐఒఓఔకఖగఘఙచఛజఝఞటఠడఢణతథదధనపఫబభమయరఱలళఴవశషసహఽౘౙౚౠౡ౦౧౨౩౪౫౬౭౮౯౸౹౺౻౼౽౾ಀಅಆಇಈಉಊಋಌಎಏಐಒಓಔಕಖಗಘಙಚಛಜಝಞಟಠಡಢಣತಥದಧನಪಫಬಭಮಯರಱಲಳವಶಷಸಹಽೞೠೡ೦೧೨೩೪೫೬೭೮೯ೱೲഅആഇഈഉഊഋഌഎഏഐഒഓഔകഖഗഘങചഛജഝഞടഠഡഢണതഥദധനഩപഫബഭമയരറലളഴവശഷസഹഺഽൎൔൕൖ൘൙൚൛൜൝൞ൟൠൡ൦൧൨൩൪൫൬൭൮൯൰൱൲൳൴൵൶൷൸ൺൻർൽൾൿඅආඇඈඉඊඋඌඍඎඏඐඑඒඓඔඕඖකඛගඝඞඟචඡජඣඤඥඦටඨඩඪණඬතථදධනඳපඵබභමඹයරලවශෂසහළෆ෦෧෨෩෪෫෬෭෮෯กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะาเแโใไๅ๐๑๒๓๔๕๖๗๘๙ກຂຄງຈຊຍດຕຖທນບປຜຝພຟມຢຣລວສຫອຮຯະາຽເແໂໃໄ໐໑໒໓໔໕໖໗໘໙ໞໟༀ༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳ཀཁགངཅཆཇཉཊཋཌཎཏཐདནཔཕབམཙཚཛཝཞཟའཡརལཤཥསཧཨཪཫཬྈྉྊྋྌကခဂဃငစဆဇဈဉညဋဌဍဎဏတထဒဓနပဖဗဘမယရလဝသဟဠအဢဣဤဥဧဨဩဪဿ၀၁၂၃၄၅၆၇၈၉ၐၑၒၓၔၕ"];
41 | this.padChars.default = [..."01234567"];
42 |
43 | this.padCharAmount = 8;
44 | this.hasSignedMode = true;
45 | this.littleEndian = false;
46 | this.nonASCII = true;
47 |
48 | // apply user settings
49 | this.utils.validateArgs(args, true);
50 | }
51 |
52 |
53 | /**
54 | * BaseEx Base2048 Encoder.
55 | * @param {*} input - Input according to the used byte converter.
56 | * @param {...str} [args] - Converter settings.
57 | * @returns {string} - Base2048 encoded string.
58 | */
59 | encode(input, ...args) {
60 |
61 | const settings = this.utils.validateArgs(args);
62 | let inputBytes = this.utils.inputHandler.toBytes(input, settings).at(0);
63 |
64 | const charset = this.charsets[settings.version];
65 | const padChars = this.padChars[settings.version];
66 |
67 | let output = "";
68 | let z = 0;
69 | let numZBits = 0;
70 |
71 | inputBytes.forEach(uint8 => {
72 |
73 | for (let i=this.converter.bsDec-1; i>=0; i--) {
74 |
75 | z = (z << 1) + ((uint8 >> i) & 1);
76 | numZBits++;
77 |
78 | if (numZBits === this.converter.bsEnc) {
79 | output += charset.at(z);
80 | z = 0
81 | numZBits = 0
82 | }
83 | }
84 | });
85 |
86 | if (numZBits !== 0) {
87 |
88 | let bitCount;
89 | let isPadding;
90 |
91 | if (numZBits <= this.converter.bsEncPad) {
92 | bitCount = this.converter.bsEncPad;
93 | isPadding = true;
94 | } else {
95 | bitCount = this.converter.bsEnc
96 | isPadding = false;
97 | }
98 |
99 | while (numZBits !== bitCount) {
100 | z = (z << 1) + 1
101 | numZBits++
102 | if (numZBits > this.converter.bsEnc) {
103 | throw new Error("Cannot process input. This is a bug!");
104 | }
105 | }
106 |
107 | if (isPadding) {
108 | output += padChars.at(z);
109 | } else {
110 | output += charset.at(z);
111 | }
112 | }
113 |
114 | return this.utils.wrapOutput(output, settings.options.lineWrap);
115 | }
116 |
117 |
118 | /**
119 | * BaseEx Base2048 Decoder.
120 | * @param {string} input - Base2048/Hex String.
121 | * @param {...any} [args] - Converter settings.
122 | * @returns {*} - Output according to converter settings.
123 | */
124 | decode(input, ...args) {
125 |
126 | // apply settings
127 | const settings = this.utils.validateArgs(args);
128 |
129 | // ensure a string input
130 | input = this.utils.normalizeInput(input);
131 | const inArray = [...input];
132 |
133 | const charset = this.charsets[settings.version];
134 | const padChars = this.padChars[settings.version];
135 |
136 | const byteArray = new Array();
137 | let uint8 = 0;
138 | let numUint8Bits = 0;
139 |
140 | inArray.forEach((c, i) => {
141 |
142 | let numZBits;
143 | let z = charset.indexOf(c);
144 | if (z > -1) {
145 | numZBits = this.converter.bsEnc;
146 | } else {
147 | z = padChars.indexOf(c);
148 |
149 | if (z > -1) {
150 | if (i+1 !== inArray.length) {
151 | throw new DecodingError(null, `Secondary character found before end of input, index: ${i}`);
152 | }
153 |
154 | numZBits = this.converter.bsEncPad;
155 | }
156 |
157 | else if (settings.integrity) {
158 | throw new DecodingError(c);
159 | }
160 | }
161 |
162 | // Take most significant bit first
163 | for (let j=numZBits-1; j>=0; j--) {
164 |
165 | uint8 = (uint8 << 1) + ((z >> j) & 1);
166 | numUint8Bits++
167 |
168 | if (numUint8Bits === this.converter.bsDec) {
169 | byteArray.push(uint8);
170 | uint8 = 0;
171 | numUint8Bits = 0;
172 | }
173 | }
174 | });
175 |
176 | return this.utils.outputHandler.compile(
177 | Uint8Array.from(byteArray),
178 | settings.outputType
179 | );
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/src/converters/base-32.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Base32 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-32.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 |
11 | /**
12 | * BaseEx Base 32 Converter.
13 | * ------------------------
14 | *
15 | * This is a base32 converter. Various input can be
16 | * converted to a base32 string or a base32 string
17 | * can be decoded into various formats. It is possible
18 | * to convert in both signed and unsigned mode in little
19 | * and big endian byte order.
20 | *
21 | * Available charsets are:
22 | * - RFC 3548
23 | * - RFC 4648
24 | * - crockford
25 | * - zbase32
26 | */
27 | export default class Base32 extends BaseTemplate {
28 |
29 | /**
30 | * BaseEx Base32 Constructor.
31 | * @param {...string} [args] - Converter settings.
32 | */
33 | constructor(...args) {
34 | super();
35 | this.converter = new BaseConverter(32, 5, 8);
36 |
37 | // charsets
38 | this.charsets.crockford = [ ..."0123456789abcdefghjkmnpqrstvwxyz" ];
39 | this.padChars.crockford = ["="],
40 |
41 | this.charsets.rfc3548 = [..."abcdefghijklmnopqrstuvwxyz234567"];
42 | this.padChars.rfc3548 = ["="];
43 |
44 | this.charsets.rfc4648 = [..."0123456789abcdefghijklmnopqrstuv"];
45 | this.padChars.rfc4648 = ["="];
46 |
47 | this.charsets.zbase32 = [..."ybndrfg8ejkmcpqxot1uwisza345h769"];
48 | this.padChars.zbase32 = ["="];
49 |
50 | // predefined settings
51 | this.padCharAmount = 1;
52 | this.hasSignedMode = true;
53 | this.version = "rfc4648";
54 |
55 | // mutable extra args
56 | this.isMutable.littleEndian = true;
57 | this.isMutable.padding = true;
58 | this.isMutable.signed = true;
59 | this.isMutable.upper = true;
60 |
61 | // apply user settings
62 | this.utils.validateArgs(args, true);
63 | this.padding = (/rfc3548|rfc4648/).test(this.version);
64 | this.upper = this.version === "crockford";
65 | }
66 |
67 |
68 | /**
69 | * BaseEx Base32 Encoder.
70 | * @param {*} input - Input according to the used byte converter.
71 | * @param {...str} [args] - Converter settings.
72 | * @returns {string} - Base32 encoded string.
73 | */
74 | encode(input, ...args) {
75 |
76 | const applyPadding = ({ output, settings, zeroPadding }) => {
77 |
78 | if (!settings.littleEndian) {
79 | // Cut of redundant chars and append padding if set
80 | if (zeroPadding) {
81 | const padValue = this.converter.padBytes(zeroPadding);
82 | const padChar = this.padChars[settings.version].at(0);
83 | output = output.slice(0, -padValue);
84 | if (settings.padding) {
85 | output = output.concat(padChar.repeat(padValue));
86 | }
87 | }
88 | }
89 |
90 | return output;
91 | }
92 |
93 | return super.encode(input, null, applyPadding, ...args);
94 | }
95 |
96 |
97 | /**
98 | * BaseEx Base32 Decoder.
99 | * @param {string} input - Base32 String.
100 | * @param {...any} [args] - Converter settings.
101 | * @returns {*} - Output according to converter settings.
102 | */
103 | decode(input, ...args) {
104 | return super.decode(input, null, null, false, ...args);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/converters/base-58.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Base58 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-58.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 |
11 | /**
12 | * BaseEx Base 58 Converter.
13 | * ------------------------
14 | *
15 | * This is a base58 converter. Various input can be
16 | * converted to a base58 string or a base58 string
17 | * can be decoded into various formats.
18 | *
19 | * Available charsets are:
20 | * - default
21 | * - bitcoin
22 | * - flickr
23 | */
24 | export default class Base58 extends BaseTemplate{
25 |
26 | /**
27 | * BaseEx Base58 Constructor.
28 | * @param {...string} [args] - Converter settings.
29 | */
30 | constructor(...args) {
31 | super();
32 | this.converter = new BaseConverter(58, 0, 0);
33 |
34 | // charsets
35 | this.charsets.default = [..."123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"];
36 | Object.defineProperty(this.padChars, "default", {
37 | get: () => [ this.charsets.default.at(0) ]
38 | });
39 |
40 | this.charsets.bitcoin = [..."123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"];
41 | Object.defineProperty(this.padChars, "bitcoin", {
42 | get: () => [ this.charsets.bitcoin.at(0) ]
43 | });
44 |
45 | this.charsets.flickr = [..."123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"];
46 | Object.defineProperty(this.padChars, "flickr", {
47 | get: () => [ this.charsets.flickr.at(0) ]
48 | });
49 |
50 |
51 | // predefined settings
52 | this.padding = true;
53 | this.version = "bitcoin";
54 |
55 | // mutable extra args
56 | this.isMutable.padding = true;
57 | this.isMutable.signed = true;
58 |
59 | // apply user settings
60 | this.utils.validateArgs(args, true);
61 | }
62 |
63 |
64 | /**
65 | * BaseEx Base58 Encoder.
66 | * @param {*} input - Input according to the used byte converter.
67 | * @param {...str} [args] - Converter settings.
68 | * @returns {string} - Base58 encoded string.
69 | */
70 | encode(input, ...args) {
71 |
72 | const applyPadding = ({ inputBytes, output, settings, type }) => {
73 |
74 | if (settings.padding && type !== "int") {
75 |
76 | // Count all null bytes at the start of the array
77 | // stop if a byte with a value is reached. If it goes
78 | // all the way through it, reset index and stop.
79 | let i = 0;
80 | const end = inputBytes.length;
81 |
82 | // pad char is always! the first char in the set
83 | const padChar = this.charsets[settings.version].at(0);
84 |
85 | // only proceed if input has a length at all
86 | if (end) {
87 | while (!inputBytes[i]) {
88 | i++;
89 | if (i === end) {
90 | i = 0;
91 | break;
92 | }
93 | }
94 |
95 | // The value for zero padding is the index of the
96 | // first byte with a value plus one.
97 | const zeroPadding = i;
98 |
99 | // Set a one for every leading null byte
100 | if (zeroPadding) {
101 | output = (padChar.repeat(zeroPadding)).concat(output);
102 | }
103 | }
104 | }
105 |
106 | return output;
107 | }
108 |
109 | return super.encode(input, null, applyPadding, ...args);
110 | }
111 |
112 |
113 | /**
114 | * BaseEx Base58 Decoder.
115 | * @param {string} input - Base58 String.
116 | * @param {...any} [args] - Converter settings.
117 | * @returns {*} - Output according to converter settings.
118 | */
119 | decode(input, ...args) {
120 |
121 | // post decoding function
122 | const applyPadding = ({ input, output, settings }) => {
123 |
124 | // pad char is always! the first char in the set
125 | const padChar = this.charsets[settings.version].at(0);
126 |
127 | if (settings.padding && input.length > 1) {
128 |
129 | // Count leading padding (char should be 1)
130 | let i = 0;
131 | while (input[i] === padChar) {
132 | i++;
133 | }
134 |
135 | // The counter becomes the zero padding value
136 | const zeroPadding = i;
137 |
138 | // Create a new Uint8Array with leading null bytes
139 | // with the amount of zeroPadding
140 | if (zeroPadding) {
141 | output = Uint8Array.from([...new Array(zeroPadding).fill(0), ...output]);
142 | }
143 |
144 | }
145 |
146 | return output;
147 | }
148 |
149 | return super.decode(input, null, applyPadding, false, ...args);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/converters/base-64.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Base64 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-64.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 |
11 | /**
12 | * BaseEx Base 64 Converter.
13 | * ------------------------
14 | *
15 | * This is a base64 converter. Various input can be
16 | * converted to a base64 string or a base64 string
17 | * can be decoded into various formats.
18 | *
19 | * Available charsets are:
20 | * - default
21 | * - urlsafe
22 | */
23 | export default class Base64 extends BaseTemplate {
24 |
25 | /**this.padChars.
26 | * BaseEx Base64 Constructor.
27 | * @param {...string} [args] - Converter settings.
28 | */
29 | constructor(...args) {
30 | super();
31 | this.converter = new BaseConverter(64, 3, 4);
32 |
33 | // charsets
34 | this.charsets.default = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"];
35 | this.padChars.default = ["="];
36 |
37 | this.charsets.urlsafe = this.charsets.default.slice(0, -2).concat(["-", "_"]);
38 | this.padChars.urlsafe = ["="];
39 |
40 |
41 | // predefined settings
42 | this.padCharAmount = 1;
43 | this.padding = true;
44 |
45 | // mutable extra args
46 | this.isMutable.padding = true;
47 |
48 | // apply user settings
49 | this.utils.validateArgs(args, true);
50 | }
51 |
52 |
53 | /**
54 | * BaseEx Base64 Encoder.
55 | * @param {*} input - Input according to the used byte converter.
56 | * @param {...str} [args] - Converter settings.
57 | * @returns {string} - Base64 encoded string.
58 | */
59 | encode(input, ...args) {
60 |
61 | const applyPadding = ({ output, settings, zeroPadding }) => {
62 |
63 | // Cut of redundant chars and append padding if set
64 | if (zeroPadding) {
65 | const padValue = this.converter.padBytes(zeroPadding);
66 | const padChar = this.padChars[settings.version].at(0);
67 | output = output.slice(0, -padValue);
68 | if (settings.padding) {
69 | output = output.concat(padChar.repeat(padValue));
70 | }
71 | }
72 |
73 | return output;
74 | }
75 |
76 | return super.encode(input, null, applyPadding, ...args);
77 | }
78 |
79 |
80 | /**
81 | * BaseEx Base64 Decoder.
82 | * @param {string} input - Base64 String.
83 | * @param {...any} [args] - Converter settings.
84 | * @returns {*} - Output according to converter settings.
85 | */
86 | decode(input, ...args) {
87 | return super.decode(input, null, null, false, ...args);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/converters/base-85.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Base85 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-85.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 |
11 | /**
12 | * BaseEx Base 85 Converter.
13 | * ------------------------
14 | *
15 | * This is a base85 converter. Various input can be
16 | * converted to a base85 string or a base85 string
17 | * can be decoded into various formats.
18 | *
19 | * Available charsets are:
20 | * - adobe
21 | * - ascii85
22 | * - rfc1924
23 | * - z85
24 | *
25 | * Adobe and ascii85 are the basically the same.
26 | * Adobe will produce the same output, apart from
27 | * the <~wrapping~>.
28 | *
29 | * Z85 is an important variant, because of the
30 | * more interpreter-friendly character set.
31 | *
32 | * The RFC 1924 version is a hybrid. It is not using
33 | * the mandatory 128 bit calculation. Instead only
34 | * the charset is getting used.
35 | */
36 | export default class Base85 extends BaseTemplate {
37 |
38 | /**
39 | * BaseEx Base85 Constructor.
40 | * @param {...string} [args] - Converter settings.
41 | */
42 | constructor(...args) {
43 | super();
44 | this.converter = new BaseConverter(85, 4, 5, 84);
45 |
46 | // charsets
47 | this.charsets.adobe = [..."!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu"];
48 | this.charsets.ascii85 = this.charsets.adobe.slice();
49 | this.charsets.rfc1924 = [..."0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"];
50 | this.charsets.z85 = [..."0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#"];
51 |
52 | // predefined settings
53 | this.version = "ascii85";
54 |
55 | // apply user settings
56 | this.utils.validateArgs(args, true);
57 | }
58 |
59 |
60 | /**
61 | * BaseEx Base85 Encoder.
62 | * @param {*} input - Input according to the used byte converter.
63 | * @param {...str} [args] - Converter settings.
64 | * @returns {string} - Base85 encoded string.
65 | */
66 | encode(input, ...args) {
67 |
68 | // Replace five consecutive "!" with a "z"
69 | // for adobe and ascii85
70 | const replacerFN = (settings) => {
71 | let replacer;
72 | if (settings.version.match(/adobe|ascii85/)) {
73 | replacer = (frame, zPad) => (!zPad && frame === "!!!!!") ? "z" : frame;
74 | }
75 | return replacer;
76 | }
77 |
78 | // Remove padded values and add a frame for the
79 | // adobe variant
80 | const framesAndPadding = ({ output, settings, zeroPadding }) => {
81 |
82 | // Cut of redundant chars
83 | if (zeroPadding) {
84 | const padValue = this.converter.padBytes(zeroPadding);
85 | output = output.slice(0, -padValue);
86 | }
87 |
88 | // Adobes variant gets its <~framing~>
89 | if (settings.version === "adobe") {
90 | output = `<~${output}~>`;
91 | }
92 |
93 | return output;
94 | }
95 |
96 | return super.encode(input, replacerFN, framesAndPadding, ...args);
97 | }
98 |
99 |
100 | /**
101 | * BaseEx Base85 Decoder.
102 | * @param {string} input - Base85 String.
103 | * @param {...any} [args] - Converter settings.
104 | * @returns {*} - Output according to converter settings.
105 | */
106 | decode(input, ...args) {
107 |
108 | const prepareInput = ({ input, settings }) => {
109 |
110 | // For default ascii85 convert "z" back to "!!!!!"
111 | // Remove the adobe <~frame~>
112 | if (settings.version.match(/adobe|ascii85/)) {
113 | input = input.replace(/z/g, "!!!!!");
114 | if (settings.version === "adobe") {
115 | input = input.replace(/^<~|~>$/g, "");
116 | }
117 | }
118 |
119 | return input
120 | }
121 |
122 | return super.decode(input, prepareInput, null, false, ...args);
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/converters/base-91.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Base91 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-91.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT AND BSD-3-Clause (Base91, Copyright (c) 2000-2006 Joachim Henke)
7 | */
8 |
9 | import { BaseTemplate } from "../core.js";
10 | import { DecodingError } from "../utils.js";
11 |
12 | /**
13 | * BaseEx Base 91 Converter.
14 | * ------------------------
15 | *
16 | * This is a base91 converter. Various input can be
17 | * converted to a base91 string or a base91 string
18 | * can be decoded into various formats.
19 | *
20 | * It is an implementation of Joachim Henkes method
21 | * to encode binary data as ASCII characters -> basE91
22 | * http://base91.sourceforge.net/
23 | *
24 | * As this method requires to split the bytes, the
25 | * default conversion class "BaseConverter" is not
26 | * getting used in this case.
27 | */
28 | export default class Base91 extends BaseTemplate {
29 |
30 | /**
31 | * BaseEx basE91 Constructor.
32 | * @param {...string} [args] - Converter settings.
33 | */
34 | constructor(...args) {
35 | super();
36 |
37 | // converter (properties only)
38 | this.converter = {
39 | radix: 91,
40 | bsEnc: 0,
41 | bsDec: 0
42 | }
43 |
44 | // charsets
45 | this.charsets.default = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~\""];
46 | this.version = "default";
47 |
48 | // apply user settings
49 | this.utils.validateArgs(args, true);
50 | }
51 |
52 |
53 | /**
54 | * BaseEx basE91 Encoder.
55 | * @param {*} input - Input according to the used byte converter.
56 | * @param {...str} [args] - Converter settings.
57 | * @returns {string} - basE91 encoded string.
58 | */
59 | encode(input, ...args) {
60 |
61 | // argument validation and input settings
62 | const settings = this.utils.validateArgs(args);
63 | const inputBytes = this.utils.inputHandler.toBytes(input, settings)[0];
64 |
65 | // As this base representation splits the bytes
66 | // the read bits need to be stores somewhere.
67 | // This is done in "bitCount". "n", similar to
68 | // other solutions here, holds the integer which
69 | // is converted to the desired base.
70 |
71 | let bitCount = 0;
72 | let n = 0;
73 | let output = "";
74 |
75 | const charset = this.charsets[settings.version];
76 |
77 | inputBytes.forEach(byte => {
78 | //n = n + byte * 2^bitcount;
79 | n += (byte << bitCount);
80 |
81 | // Add 8 bits forEach byte
82 | bitCount += 8;
83 |
84 | // If the count exceeds 13 bits, base convert the
85 | // current frame.
86 |
87 | if (bitCount > 13) {
88 |
89 | // Set bit amount "count" to 13, check the
90 | // remainder of n % 2^13. If it is 88 or
91 | // lower. Take one more bit from the stream
92 | // and calculate the remainder for n % 2^14.
93 |
94 | let count = 13;
95 | let rN = n % 8192;
96 |
97 | if (rN < 89) {
98 | count = 14;
99 | rN = n % 16384;
100 | }
101 |
102 | // Remove 13 or 14 bits from the integer,
103 | // decrease the bitCount by the same amount.
104 | n >>= count;
105 | bitCount -= count;
106 |
107 | // Calculate quotient and remainder from
108 | // the before calculated remainder of n
109 | // -> "rN"
110 | let q, r;
111 | [q, r] = this.#divmod(rN, 91);
112 |
113 | // Lookup the corresponding characters for
114 | // "r" and "q" in the set, append it to the
115 | // output string.
116 | output = `${output}${charset[r]}${charset[q]}`;
117 | }
118 | });
119 |
120 | // If the bitCount is not zero at the end,
121 | // calculate quotient and remainder of 91
122 | // once more.
123 | if (bitCount) {
124 | let q, r;
125 | [q, r] = this.#divmod(n, 91);
126 |
127 | // The remainder is concatenated in any case
128 | output = output.concat(charset[r]);
129 |
130 | // The quotient is also appended, but only
131 | // if the bitCount still has the size of a byte
132 | // or n can still represent 91 conditions.
133 | if (bitCount > 7 || n > 90) {
134 | output = output.concat(charset[q]);
135 | }
136 | }
137 |
138 | return this.utils.wrapOutput(output, settings.options.lineWrap);
139 | }
140 |
141 |
142 | /**
143 | * BaseEx basE91 Decoder.
144 | * @param {string} input - basE91 String.
145 | * @param {...any} [args] - Converter settings.
146 | * @returns {*} - Output according to converter settings.
147 | */
148 | decode(input, ...args) {
149 |
150 | // Argument validation and output settings
151 | const settings = this.utils.validateArgs(args);
152 | const charset = this.charsets[settings.version];
153 |
154 | // Make it a string, whatever goes in
155 | input = this.utils.normalizeInput(input);
156 | let inArray = [...input];
157 |
158 | // remove unwanted characters if integrity is false
159 | if (!settings.integrity) {
160 | inArray = inArray.filter(c => charset.includes(c));
161 | }
162 |
163 |
164 | let l = inArray.length;
165 |
166 | // For starters leave the last char behind
167 | // if the length of the input string is odd.
168 |
169 | let odd = false;
170 | if (l % 2) {
171 | odd = true;
172 | l--;
173 | }
174 |
175 | // Set again integer n for base conversion.
176 | // Also initialize a bitCount(er)
177 |
178 | let n = 0;
179 | let bitCount = 0;
180 |
181 | // Initialize an ordinary array
182 | const b256Array = new Array();
183 |
184 | // Walk through the string in steps of two
185 | // (aka collect remainder- and quotient-pairs)
186 | for (let i=0; i 88) ? 13 : 14;
202 |
203 | // calculate back the individual bytes (base256)
204 | do {
205 | b256Array.push(n % 256);
206 | n >>= 8;
207 | bitCount -= 8;
208 | } while (bitCount > 7);
209 | }
210 |
211 | // Calculate the last byte if the input is odd
212 | // and add it
213 | if (odd) {
214 | const lastChar = inArray.at(l);
215 | const rN = charset.indexOf(lastChar);
216 | b256Array.push(((rN << bitCount) + n) % 256);
217 | }
218 |
219 | const output = Uint8Array.from(b256Array);
220 |
221 | // Return the output
222 | return this.utils.outputHandler.compile(output, settings.outputType);
223 | }
224 |
225 |
226 | /**
227 | * Divmod Function.
228 | * @param {*} x - number 1
229 | * @param {*} y - number 2
230 | * @returns {number} Modulo y of x
231 | */
232 | #divmod (x, y) {
233 | return [Math.floor(x/y), x%y];
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/src/converters/base-phi.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|BasePhi Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/base-phi.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 | import Big from "../../lib/big.js/big.min.js";
11 | import { DecodingError } from "../utils.js";
12 |
13 | /**
14 | * BaseEx Base Phi Converter.
15 | * ------------------------
16 | *
17 | * This is a base phi converter. Various input can be
18 | * converted to a base phi string or a base phi string
19 | * can be decoded into various formats.
20 | *
21 | */
22 | export default class BasePhi extends BaseTemplate {
23 |
24 | #Phi = Big("1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137484754088075386891752");
25 |
26 | /**
27 | * BaseEx basE91 Constructor.
28 | * @param {...string} [args] - Converter settings.
29 | */
30 | constructor(...args) {
31 | super();
32 |
33 | // converter (properties only)
34 | this.converter = {
35 | radix: 2, // radix is Phi, but the normalized representation allows two chars
36 | bsEnc: 0,
37 | bsDec: 0
38 | }
39 |
40 | // base10 converter to have always have a numerical input
41 | this.b10 = new BaseConverter(10, 0, 0);
42 |
43 | // charsets
44 | this.charsets.default = ["0", "1"];
45 |
46 | this.version = "default";
47 | this.signed = true;
48 | this.hasDecimalMode = true;
49 |
50 | // apply user settings
51 | this.utils.validateArgs(args, true);
52 | }
53 |
54 |
55 | /**
56 | * BaseEx BasePhi Encoder.
57 | * @param {*} input - Input according to the used byte converter.
58 | * @param {...string} [args] - Converter settings.
59 | * @returns {string} - BasePhi encoded string.
60 | */
61 | encode(input, ...args) {
62 |
63 | // argument validation and input settings
64 | const settings = this.utils.validateArgs(args);
65 | const charset = this.charsets[settings.version];
66 |
67 | let inputBytes;
68 | let negative;
69 | let n;
70 | let output = "";
71 |
72 | // Base Phi allows direct encoding of rational
73 | // and irrational numbers, which can be enabled
74 | // by using the special type "decimal". Input
75 | // type must be "Number" for this mode.
76 | if (settings.decimalMode) {
77 | if (Number.isFinite(input)) {
78 | if (input < 0) {
79 | negative = true;
80 | n = Big(-input);
81 | } else {
82 | negative = false;
83 | n = Big(input);
84 | }
85 | }
86 |
87 | else {
88 | throw new TypeError("When running the converter in decimal-mode, only input of type 'Number' is allowed.")
89 | }
90 | }
91 |
92 | // Every other type first converts the byte representation
93 | // of the input to base 10.
94 | else {
95 | [ inputBytes, negative, ] = this.utils.inputHandler.toBytes(input, settings);
96 | n = Big(
97 | this.b10.encode(inputBytes, null, settings.littleEndian)[0]
98 | );
99 | }
100 |
101 | // if "n" if 0 or 1 stop here and return 0 or 1 (according to the charset)
102 | if (n.eq(0) || n.eq(1)) {
103 | output = charset[n.toNumber()];
104 | if (negative) {
105 | output = `-${output}`;
106 | }
107 | return output;
108 | }
109 |
110 | // create two arrays to store all exponents
111 | const exponents = [];
112 | const decExponents = [];
113 |
114 |
115 | // The very first step is to find the highest exponent
116 | // of Phi which fits into "n" (the rounded highest exponent
117 | // is also the highest Lucas number which fits into "n")
118 | // To find the highest fitting exponent start with
119 | // Phi^0 (1) and Phi^1 (Phi).
120 |
121 | let last = Big(1);
122 | let cur = this.#Phi;
123 | let exp = 0;
124 |
125 | // Now add the result with the last higher value "cur",
126 | // util "cur" is bigger than "n"
127 | while (cur.lt(n)) {
128 | [ last, cur ] = this.#nextPhiExp(last, cur);
129 | exp++;
130 | }
131 |
132 | /**
133 | * Recursive reduction function for "n". Finds the largest
134 | * fitting exponent of Phi (Lucas index), stores that index
135 | * in the exponent arrays and reduces "n" by the current exponents
136 | * power.
137 | * Once started, it calls itself until "n" is zero.
138 | * @param {Object} cur - Current result of Phi^exp as a Big.js object.
139 | * @param {Object} prev - Previous result of Phi^exp as a Big.js object.
140 | * @param {number} exp - Exponent of Phi/Lucas index.
141 | */
142 | const reduceN = (cur, prev, exp) => {
143 |
144 | // Due to the high floating point precision "n" should
145 | // be exactly zero, but if not, an approximation is
146 | // sufficient.
147 | if (this.#approxNull(n)) return;
148 |
149 | // Reduce the exponents of Phi until it power fits into "n"
150 | while (cur.gt(n)) {
151 | [ cur, prev ] = this.#prevPhiExp(cur, prev);
152 |
153 | // if "cur" gets negative return immediately
154 | // prevent an infinite loop
155 | if (cur.lte(0)) {
156 | console.warn("Could not find an exact base-phi representation. Value is approximated.");
157 | return;
158 | }
159 | exp--;
160 | }
161 |
162 | // Store the exponents
163 | if (exp > -1) {
164 | exponents.unshift(exp);
165 | } else {
166 | decExponents.push(exp);
167 | }
168 |
169 | // Reduce "n"
170 | n = n.minus(cur);
171 |
172 | reduceN(cur, prev, exp);
173 | }
174 |
175 | // Initial call of the reduction function
176 | reduceN(last, cur, exp);
177 |
178 |
179 | // Create a BasePhi string by setting a "1" at every
180 | // index stored in the "exponent" array. for every
181 | // number between two indices a zero is added.
182 | exp = 0;
183 | exponents.forEach(nExp => {
184 | while (exp < nExp) {
185 | output = `${charset[0]}${output}`;
186 | exp++;
187 | }
188 | output = `${charset[1]}${output}`;
189 | exp++;
190 | });
191 |
192 | // Add a decimal point
193 | if (!output) {
194 | output = "0.";
195 | } else {
196 | output += ".";
197 | }
198 |
199 | // Proceed with the decimal exponents
200 | exp = -1;
201 | decExponents.forEach(nExp => {
202 | while (exp > nExp) {
203 | output += charset[0];
204 | exp--;
205 | }
206 | output += charset[1];
207 | exp--;
208 | });
209 |
210 | // Add a "-" if the input is negative.
211 | if (negative) {
212 | output = `-${output}`;
213 | }
214 |
215 | return output;
216 | }
217 |
218 |
219 | /**
220 | * BaseEx Base Phi Decoder.
221 | * @param {string} input - Base Phi String.
222 | * @param {...any} [args] - Converter settings.
223 | * @returns {*} - Output according to converter settings.
224 | */
225 | decode(input, ...args) {
226 |
227 | // Argument validation and output settings
228 | const settings = this.utils.validateArgs(args);
229 | const charset = this.charsets[settings.version];
230 |
231 | let negative;
232 | [ input, negative ] = this.utils.extractSign(
233 | this.utils.normalizeInput(input)
234 | );
235 |
236 | // remove unwanted characters if integrity is false
237 | if (!settings.integrity) {
238 | const testChars = [...charset, "."];
239 | input = [...input].filter(c => testChars.includes(c)).join("");
240 | }
241 |
242 | // Split the input String at the decimal sign
243 | // and initialize a big.js-object with value 0
244 | const inputSplit = input.split(".");
245 | if (settings.integrity && inputSplit.length > 2) {
246 | throw new DecodingError(null, "There are multiple decimal points in the input.");
247 | }
248 |
249 | const [ posExpStr, decExpStr ] = inputSplit;
250 | let n = Big(0);
251 |
252 | // Initialize two variables "last" and "cur"
253 | // for Phi^exp-1 and Phi^exp
254 | let last = this.#Phi.minus(1);
255 | let cur = Big(1);
256 |
257 | // Convert the left side of the input string
258 | // to an array of chars and reverse it. Raise
259 | // the exponent of Phi and its values until a
260 | // one is found in the array, if a "1" was found
261 | // add the value "cur" to number "n" (one can
262 | // also be another corresponding char of the set
263 | // which represents 1).
264 | [...posExpStr].reverse().forEach((char) => {
265 | const charIndex = charset.indexOf(char);
266 | if (charIndex === 1) {
267 | n = n.plus(cur);
268 | } else if (charIndex !== 0) {
269 | throw new DecodingError(char);
270 | }
271 | [ last, cur ] = this.#nextPhiExp(last, cur);
272 | });
273 |
274 | // Now also add the values for the decimal places.
275 | if (decExpStr) {
276 | let prev = Big(1);
277 | cur = this.#Phi.minus(prev);
278 |
279 | [...decExpStr].forEach((char) => {
280 | const charIndex = charset.indexOf(char);
281 | if (charIndex === 1) {
282 | n = n.plus(cur);
283 | } else if (charIndex !== 0) {
284 | throw new DecodingError(char);
285 | }
286 | [ cur, prev ] = this.#prevPhiExp(cur, prev);
287 | });
288 | }
289 |
290 | // If running in decimal mode return n as a Number
291 | if (settings.decimalMode) {
292 | return n.toNumber();
293 | }
294 |
295 | // For every other case round "n" and turn it
296 | // into a string of an integer.
297 | n = n.round().toFixed();
298 |
299 | // Use the base 10 decoder to get the byte
300 | // representation of "n".
301 | const output = this.b10.decode(n, [..."0123456789"], [], settings.integrity, settings.littleEndian);
302 |
303 | // Return the output according to the settings.
304 | return this.utils.outputHandler.compile(output, settings.outputType, settings.littleEndian, negative);
305 | }
306 |
307 | /**
308 | * Test if n is approximately zero.
309 | * @param {Object} n - Big.js Object.
310 | * @returns {Boolean}
311 | */
312 | #approxNull(n) {
313 | return !(n.round(50)
314 | .abs()
315 | .toNumber()
316 | );
317 | }
318 |
319 | /**
320 | * Get the results of of the following exponents of Phi
321 | * from the predecessors.
322 | * @param {Object} last - Phi^exp-1 as a big.js-object
323 | * @param {Object} cur - Phi^exp as a big.js-object
324 | * @returns {Object[]} - Array with Phi^exp and Phi^exp+1
325 | */
326 | #nextPhiExp(last, cur) {
327 | return [ cur, last.plus(cur) ];
328 | }
329 |
330 | /**
331 | * Get the results of of the previous exponents of Phi
332 | * from the predecessors.
333 | * @param {Object} cur - Phi^exp as a big.js-object
334 | * @param {Object} prev - Phi^exp-1 as a big.js-object
335 | * @returns {Object[]} - Array with Phi^exp-1 and Phi^exp
336 | */
337 | #prevPhiExp(cur, prev) {
338 | return [ prev.minus(cur), cur ];
339 | }
340 | }
341 |
--------------------------------------------------------------------------------
/src/converters/byte-converter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|Byte Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/byte-converter.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { SmartInput, SmartOutput } from "../io-handlers.js";
10 |
11 | // Endianness of the system
12 | const LITTLE_ENDIAN = (() => {
13 | const testInt = new Uint16Array([1]);
14 | const byteRepresentation = new Uint8Array(testInt.buffer);
15 | return Boolean(byteRepresentation.at(0));
16 | })();
17 |
18 |
19 | /**
20 | * BaseEx Byte Converter.
21 | * ---------------------
22 | *
23 | * This is a byte converter. Various input can be
24 | * converted to a bytes or bytes can be decoded into
25 | * various formats.
26 | *
27 | * As en- and decoder were already available, for the
28 | * use of converting in- and output for the base
29 | * converters, this is just a little extra tool, which
30 | * was fast and easy to create.
31 | */
32 | export default class ByteConverter {
33 |
34 | /**
35 | * BaseEx ByteConverter Constructor.
36 | * @param {...string} [args] - Converter settings.
37 | */
38 | constructor(...args) {
39 |
40 | // predefined settings
41 | this.littleEndian = LITTLE_ENDIAN;
42 | this.numberMode = false;
43 | this.outputType = "buffer";
44 |
45 | // simplified utils
46 | this.utils = {
47 | validateArgs: (args, initial=false) => {
48 |
49 | const parameters = {
50 | littleEndian: this.littleEndian,
51 | numberMode: this.numberMode,
52 | outputType: this.outputType,
53 | signed: false,
54 | }
55 |
56 | if (!args.length) {
57 | return parameters;
58 | }
59 |
60 | if (args.includes("number")) {
61 | args.splice(args.indexOf("number"), 1);
62 | parameters.numberMode = true;
63 | parameters.outputType = "float_n";
64 | }
65 |
66 | const outTypes = SmartOutput.typeList.map(s => `'${s}'`).join(", ");
67 |
68 | args.forEach((arg) => {
69 | arg = String(arg).toLowerCase();
70 |
71 | if (arg === "le") {
72 | parameters.littleEndian = true;
73 | } else if (arg === "be") {
74 | parameters.littleEndian = false;
75 | } else if (SmartOutput.typeList.includes(arg)) {
76 | parameters.outputType = arg;
77 | } else {
78 | throw new TypeError(`Invalid argument: '${arg}.\nValid arguments are:\n'le', 'be', ${outTypes}`);
79 | }
80 | });
81 |
82 | if (initial) {
83 | for (const param in parameters) {
84 | this[param] = parameters[param];
85 | }
86 | }
87 |
88 | return parameters;
89 | }
90 | }
91 |
92 | // apply user settings
93 | this.utils.validateArgs(args, true);
94 | }
95 |
96 |
97 | /**
98 | * BaseEx Byte Encoder.
99 | * @param {*} input - Almost any input.
100 | * @param {...str} [args] - Converter settings.
101 | * @returns {{ buffer: ArrayBufferLike; }} - Bytes of Input.
102 | */
103 | encode(input, ...args) {
104 | const settings = this.utils.validateArgs(args);
105 | return SmartInput.toBytes(input, settings)[0];
106 | }
107 |
108 |
109 | /**
110 | * BaseEx Byte Decoder.
111 | * @param {{ buffer: ArrayBufferLike; }} input - Bytes/Buffer/View
112 | * @param {...any} [args] - Converter settings.
113 | * @returns {*} - Output of requested type.
114 | */
115 | decode(input, ...args) {
116 | const settings = this.utils.validateArgs(args);
117 | return SmartOutput.compile(input, settings.outputType, settings.littleEndian);
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/converters/leb-128.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|LEB128 Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/leb-128.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 | import { BytesInput } from "../io-handlers.js";
11 |
12 | /**
13 | * BaseEx Little Endian Base 128 Converter.
14 | * ---------------------------------------
15 | *
16 | * This is a leb128 converter. Various input can be
17 | * converted to a leb128 string or a leb128 string
18 | * can be decoded into various formats.
19 | *
20 | * There is no real charset available as the input is
21 | * getting converted to bytes. For having the chance
22 | * to store these bytes, there is a hexadecimal output
23 | * available.
24 | */
25 | export default class LEB128 extends BaseTemplate {
26 |
27 | /**
28 | * BaseEx LEB128 Constructor.
29 | * @param {...string} [args] - Converter settings.
30 | */
31 | constructor(...args) {
32 | // initialize base template without utils
33 | super();
34 |
35 | // converters
36 | this.converter = new BaseConverter(10, 0, 0);
37 | this.hexlify = new BaseConverter(16, 1, 2);
38 |
39 | // charsets
40 | this.charsets.default = "";
41 | this.charsets.hex = ""
42 |
43 | // predefined settings
44 | this.version = "default";
45 | this.frozenCharsets = true;
46 |
47 | // predefined settings
48 | this.littleEndian = true;
49 | this.hasSignedMode = true;
50 | this.isMutable.signed = true;
51 |
52 | // apply user settings
53 | this.utils.validateArgs(args, true);
54 | }
55 |
56 |
57 | /**
58 | * BaseEx LEB128 Encoder.
59 | * @param {*} input - Input according to the used byte converter.
60 | * @param {...str} [args] - Converter settings.
61 | * @returns {{ buffer: ArrayBufferLike; }} - LEB128 encoded Unit8Array (or hex string of it).
62 | */
63 | encode(input, ...args) {
64 |
65 | // argument validation and input settings
66 | const settings = this.utils.validateArgs(args);
67 |
68 | const signed = settings.signed;
69 | settings.signed = true;
70 | const [ inputBytes, negative, ] = this.utils.inputHandler.toBytes(input, settings);
71 |
72 | // Convert to BaseRadix string
73 | let base10 = this.converter.encode(inputBytes, null, settings.littleEndian)[0];
74 |
75 | let n = BigInt(base10);
76 | let output = new Array();
77 |
78 | if (negative) {
79 | if (!signed) {
80 | throw new TypeError("Negative values in unsigned mode are invalid.");
81 | }
82 | n = -n;
83 | }
84 |
85 | if (signed) {
86 |
87 | for (;;) {
88 | const byte = Number(n & 127n);
89 | n >>= 7n;
90 | if ((n == 0 && (byte & 64) == 0) || (n == -1 && (byte & 64) != 0)) {
91 | output.push(byte);
92 | break;
93 | }
94 | output.push(byte | 128);
95 | }
96 | }
97 |
98 | else {
99 | for (;;) {
100 | const byte = Number(n & 127n);
101 | n >>= 7n;
102 | if (n == 0) {
103 | output.push(byte)
104 | break;
105 | }
106 | output.push(byte | 128);
107 | }
108 | }
109 |
110 | const Uint8Output = Uint8Array.from(output);
111 |
112 | if (settings.version === "hex") {
113 | return this.hexlify.encode(Uint8Output, [..."0123456789abcdef"], false)[0];
114 | }
115 |
116 | return Uint8Output;
117 | }
118 |
119 |
120 | /**
121 | * BaseEx LEB128 Decoder.
122 | * @param {{ buffer: ArrayBufferLike; }|string} input - LEB128-Bytes or String of Hex-Version.
123 | * @param {...any} [args] - Converter settings.
124 | * @returns {*} - Output according to converter settings.
125 | */
126 | decode(input, ...args) {
127 |
128 | // Argument validation and output settings
129 | const settings = this.utils.validateArgs(args);
130 |
131 | if (settings.version === "hex") {
132 | input = this.hexlify.decode(this.utils.normalizeInput(input).toLowerCase(), [..."0123456789abcdef"], [], settings.integrity, false);
133 | } else if (typeof input.byteLength !== "undefined") {
134 | input = BytesInput.toBytes(input)[0];
135 | } else {
136 | throw new TypeError("Input must be a bytes like object.");
137 | }
138 |
139 | if (input.length === 1 && !input[0]) {
140 | return this.utils.outputHandler.compile(new Uint8Array(1), settings.outputType, true);
141 | }
142 |
143 | input = Array.from(input);
144 |
145 | let n = 0n;
146 | let shiftVal = -7n;
147 | let byte;
148 |
149 | for (byte of input) {
150 | shiftVal += 7n;
151 | n += (BigInt(byte & 127) << shiftVal);
152 | }
153 |
154 | if (settings.signed && ((byte & 64) !== 0)) {
155 | n |= -(1n << shiftVal + 7n);
156 | }
157 |
158 | // Test for a negative sign
159 | let decimalNum, negative;
160 | [decimalNum, negative] = this.utils.extractSign(n.toString());
161 |
162 | const output = this.converter.decode(decimalNum, [..."0123456789"], [], settings.integrity, true);
163 |
164 | // Return the output
165 | return this.utils.outputHandler.compile(output, settings.outputType, true, negative);
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/converters/simple-base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|SimpleBase Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/simple-base.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 |
11 |
12 | /**
13 | * BaseEx SimpleBase Converter.
14 | * ---------------------------
15 | * SimpleBase provides the simple mathematical base
16 | * conversion as known from (n).toString(radix) and
17 | * parseInt(n, radix).
18 | *
19 | * The constructor needs a radix between 2-62 as the
20 | * first argument. In other regards it behaves pretty
21 | * much as any other converter.
22 | */
23 | export default class SimpleBase extends BaseTemplate {
24 |
25 | /**
26 | * SimpleBase Constructor.
27 | * @param {number} radix - Radix between 2 and 62
28 | * @param {...any} args - Converter settings.
29 | */
30 | constructor(radix, ...args) {
31 | super();
32 |
33 | if (!radix || !Number.isInteger(radix) || radix < 2 || radix > 62) {
34 | throw new RangeError("Radix argument must be provided and has to be an integer between 2 and 62.")
35 | }
36 | this.converter = new BaseConverter(radix, 0, 0);
37 |
38 |
39 | // charsets
40 | this.charsets.default = [..."0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"].slice(0, radix);
41 |
42 |
43 | // predefined settings
44 | this.frozenCharsets = true;
45 | this.hasSignedMode = true;
46 | this.littleEndian = !(radix === 2 || radix === 16);
47 | this.signed = true;
48 | this.version = "default";
49 |
50 | // list of allowed/disallowed args to change
51 | this.isMutable.littleEndian = true,
52 | this.isMutable.upper = radix <= 36;
53 |
54 | // apply user settings
55 | this.utils.validateArgs(args, true);
56 | }
57 |
58 |
59 | /**
60 | * BaseEx SimpleBase Encoder.
61 | * @param {*} input - Input according to the used byte converter.
62 | * @param {...any} [args] - Converter settings.
63 | * @returns {string} - Base 2-62 encoded string.
64 | */
65 | encode(input, ...args) {
66 | return super.encode(input, null, null, ...args);
67 | }
68 |
69 |
70 | /**
71 | * BaseEx SimpleBase Decoder.
72 | * @param {string} input - Base 2-62 String.
73 | * @param {...any} [args] - Converter settings.
74 | * @returns {*} - Output according to converter settings.
75 | */
76 | decode(rawInput, ...args) {
77 |
78 | // pre decoding function
79 | const normalizeInput = ({ input }) => {
80 |
81 | // normalize input (add leading zeros) for base 2 and 16
82 | if (this.converter.radix === 2) {
83 | const leadingZeros = (8 - (input.length % 8)) % 8;
84 | input = `${"0".repeat(leadingZeros)}${input}`;
85 | } else if (this.converter.radix === 16) {
86 | const leadingZeros = input.length % 2;
87 | input = `${"0".repeat(leadingZeros)}${input}`;
88 | }
89 |
90 | return input;
91 | }
92 |
93 | return super.decode(rawInput, normalizeInput, null, false, ...args);
94 |
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/converters/uuencode.js:
--------------------------------------------------------------------------------
1 | /**
2 | * [BaseEx|UUencode Converter]{@link https://github.com/UmamiAppearance/BaseExJS/blob/main/src/converters/uuencode.js}
3 | *
4 | * @version 0.8.1
5 | * @author UmamiAppearance [mail@umamiappearance.eu]
6 | * @license MIT
7 | */
8 |
9 | import { BaseConverter, BaseTemplate } from "../core.js";
10 |
11 | /**
12 | * BaseEx UUencode Converter.
13 | * ------------------------
14 | *
15 | * This is a UUencoder/UUdecoder. Various input can be
16 | * converted to a UUencoded string or a UUencoded string
17 | * can be decoded into various formats.
18 | *
19 | * Available charsets are:
20 | * - default
21 | * - original
22 | * - xx
23 | */
24 | export default class UUencode extends BaseTemplate {
25 |
26 | /**
27 | * BaseEx UUencode Constructor.
28 | * @param {...string} [args] - Converter settings.
29 | */
30 | constructor(...args) {
31 | super();
32 | this.converter = new BaseConverter(64, 3, 4);
33 |
34 | // charsets
35 | this.charsets.default = [..."`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"];
36 | Object.defineProperty(this.padChars, "default", {
37 | get: () => [ this.charsets.default.at(0) ]
38 | });
39 |
40 | this.charsets.original = [" ", ...this.charsets.default.slice(1)];
41 | Object.defineProperty(this.padChars, "original", {
42 | get: () => [ this.charsets.original.at(0) ]
43 | });
44 |
45 | this.charsets.xx = [..."+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"];
46 | Object.defineProperty(this.padChars, "xx", {
47 | get: () => [ this.charsets.xx.at(0) ]
48 | });
49 |
50 |
51 | // predefined settings
52 | this.padding = true;
53 | this.buffering = false;
54 | this.utils.converterArgs.buffering = ["nobuffering", "buffering"];
55 | this.isMutable.buffering = true;
56 | this.header = false;
57 | this.utils.converterArgs.header = ["noheader", "header"];
58 | this.isMutable.header = true;
59 | this.isMutable.integrity = false;
60 |
61 | // apply user settings
62 | this.utils.validateArgs(args, true);
63 | }
64 |
65 |
66 | /**
67 | * BaseEx UUencoder.
68 | * @param {*} input - Input according to the used byte converter.
69 | * @param {...str} [args] - Converter settings.
70 | * @returns {string} - UUencode string.
71 | */
72 | encode(input, ...args) {
73 |
74 | const format = ({ output, settings, zeroPadding }) => {
75 |
76 | const charset = this.charsets[settings.version];
77 | const outArray = [...output];
78 | const outLen = outArray.length;
79 | settings.options.lineWrap = 0;
80 |
81 |
82 | if (settings.header && !settings.buffering) {
83 | const permissions = settings.options.permissions || een();
84 | const fileName = settings.options.file || ees();
85 | output = `begin ${permissions} ${fileName}\n`;
86 | } else {
87 | output = "";
88 | }
89 |
90 | // repeatedly take 60 chars from the output
91 | for (let start=0; start= outLen) {
97 | const byteCount = this.converter.padChars(lArray.length) - zeroPadding;
98 |
99 | // add the the current chars plus the leading
100 | // count char
101 | output += `${charset.at(byteCount)}${lArray.join("")}\n`;
102 | }
103 |
104 | // add the the current chars plus the leading
105 | // count char ("M" for default charsets)
106 | else {
107 | output += `${charset.at(45)}${lArray.join("")}\n`;
108 | }
109 | }
110 |
111 | if (!settings.buffering) {
112 | output += `${charset.at(0)}\n`;
113 |
114 | if (settings.header) {
115 | output += "end\n";
116 | }
117 | }
118 |
119 | return output;
120 | }
121 |
122 | return super.encode(input, null, format, ...args);
123 | }
124 |
125 |
126 | /**
127 | * BaseEx UUdecoder.
128 | * @param {string} input - UUencode String.
129 | * @param {...any} [args] - Converter settings.
130 | * @returns {*} - Output according to converter settings.
131 | */
132 | decode(input, ...args) {
133 |
134 | let padChars = 0;
135 |
136 | const format = ({ input, settings }) => {
137 |
138 | const charset = this.charsets[settings.version];
139 | const lines = input.trim().split(/\r?\n/);
140 | const inArray = [];
141 |
142 | if ((/^begin/i).test(lines.at(0))) {
143 | lines.shift();
144 | }
145 |
146 | for (const line of lines) {
147 | const lArray = [...line];
148 | const byteCount = charset.indexOf(lArray.shift());
149 |
150 | if (!(byteCount > 0)) {
151 | break;
152 | }
153 |
154 | inArray.push(...lArray);
155 |
156 | if (byteCount !== 45) {
157 | let len = lArray.length
158 |
159 | // fix probably missing spaces for original charset
160 | if (settings.version === "original") {
161 | const expectedLen = calcUUStrLen(byteCount);
162 | while (len < expectedLen) {
163 | len++;
164 | inArray.push(" ");
165 | }
166 | }
167 |
168 | padChars = this.converter.padChars(len) - byteCount;
169 | break;
170 | }
171 |
172 | // fix probably missing spaces for original charset
173 | else if (lArray.length !== 60 && settings.version === "original") {
174 | while (inArray.length % 60) {
175 | inArray.push(" ");
176 | }
177 | }
178 | }
179 |
180 | return inArray.join("");
181 |
182 | }
183 |
184 | const removePadChars = ({ output }) => {
185 | if (padChars) {
186 | output = new Uint8Array(output.slice(0, -padChars));
187 | }
188 | return output;
189 | }
190 |
191 | return super.decode(input, format, removePadChars, true, ...args);
192 | }
193 | }
194 |
195 |
196 | const een = () => {
197 | const o = () => Math.floor(Math.random() * 8);
198 | return `${o()}${o()}${o()}`;
199 | }
200 |
201 | const ees = () => {
202 | const name = [
203 | "unchronological",
204 | "unconditionally",
205 | "underemphasized",
206 | "underprivileged",
207 | "undistinguished",
208 | "unsophisticated",
209 | "untitled",
210 | "untitled-1",
211 | "untitled-3",
212 | "uuencode"
213 | ];
214 |
215 | const ext = [
216 | "applescript",
217 | "bat",
218 | "beam",
219 | "bin",
220 | "exe",
221 | "js",
222 | "mam",
223 | "py",
224 | "sh",
225 | "vdo",
226 | "wiz"
227 | ];
228 |
229 | const pick = (arr) => arr.at(Math.floor(Math.random() * arr.length));
230 |
231 | return `${pick(name)}.${pick(ext)}`;
232 | };
233 |
234 | const calcUUStrLen = byteCount => {
235 | const len = byteCount / 3 * 4;
236 | if (len % 4) {
237 | return Math.floor(len/4) * 4 + 4;
238 | }
239 | return len;
240 | }
241 |
--------------------------------------------------------------------------------
/test/base-1.test.js:
--------------------------------------------------------------------------------
1 | import { Base1, SimpleBase } from "base-ex";
2 | import { randInt } from "./fixtures/helpers.js";
3 | import test from "ava";
4 |
5 |
6 | const b1Test = test.macro(async (t, input, expectedLen, base, ...args) => {
7 | const output = base.encode(input, ...args);
8 | t.is(output.length, expectedLen);
9 | t.is(base.decode(output, ...args), input);
10 | });
11 |
12 | const bFn = new Base1();
13 | const base10 = new SimpleBase(10);
14 |
15 | // string
16 | let input = "str";
17 | let expectedLen = base10.encode(input)|0;
18 | const title = `En- and decode Base1 for type String with input 'str'`;
19 |
20 | test(title, b1Test, input, expectedLen, bFn, "str");
21 |
22 |
23 | // integers
24 | for (let i=0; i<2; i++) {
25 |
26 | const int = ["Uint", "Int"].at(i);
27 | const signMulti = [1, -1].at(i);
28 | const arg = `${int.toLowerCase()}_n`;
29 |
30 | input = randInt(256, 2**24);
31 |
32 | // raise by one if negative sign is present
33 | expectedLen = input + i;
34 | input *= signMulti;
35 |
36 | const title = `En- and decode Base1 for type Integer with input '${input}'`;
37 |
38 | test(title, b1Test, input, expectedLen, bFn, arg);
39 | }
40 |
--------------------------------------------------------------------------------
/test/ecoji-orig.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * JavaScript/AVA implementation
3 | * @see https://github.com/keith-turner/ecoji/blob/main/test_scripts/ecoji_test.sh
4 | */
5 |
6 |
7 | import { readFile, readdir } from "fs/promises";
8 | import { Ecoji } from "base-ex";
9 | import test from "ava";
10 |
11 | // macros
12 | const enDecodeTest = test.macro((t, input, expected, ecoji) => {
13 | const output = ecoji.encode(input);
14 | t.is(output, expected);
15 | t.deepEqual(ecoji.decode(output), input);
16 | });
17 |
18 | const decodeTest = test.macro((t, input, expected, ecoji, ...args) => {
19 | t.is(ecoji.decode(input, ...args), expected);
20 | });
21 |
22 | const errorTest = test.macro((t, input, ecoji) => {
23 | t.throws(() => ecoji.decode(input));
24 | });
25 |
26 |
27 | // declarations
28 | const path = "./test/fixtures/ecoji/";
29 | const files = await (readdir(path));
30 | const ecojiV1 = new Ecoji("emojis_v1", "uint8");
31 | const ecojiV2 = new Ecoji("emojis_v2", "uint8");
32 |
33 |
34 | // test group file lists
35 | const plainFilesA = files.filter(f => (/\.plain$/).test(f));
36 | const aLen = plainFilesA.length;
37 |
38 | const plainFilesB = files.filter(f => (/\.plaind$/).test(f));
39 | const bLen = plainFilesB.length;
40 |
41 | const garbage = files.filter(f => (/\.garbage$/).test(f));
42 | const gLen = garbage.length;
43 |
44 |
45 | // test data generation
46 | const dataA = await Promise.all(
47 | plainFilesA.map(async plainFile => {
48 | const bareName = plainFile.slice(0, -6);
49 |
50 | const input = new Uint8Array(await readFile(`${path}${plainFile}`));
51 |
52 | const expectedV1 = await readFile(`${path}${bareName}.ev1`, "utf-8");
53 | const expectedV2 = await readFile(`${path}${bareName}.ev2`, "utf-8");
54 |
55 | return {
56 | input,
57 | expectedV1,
58 | expectedV2
59 | }
60 | })
61 | );
62 |
63 | const dataB = await Promise.all(
64 | plainFilesB.map(async plainFile => {
65 | const bareName = plainFile.slice(0, -7);
66 |
67 | const input = await readFile(`${path}${bareName}.enc`, "utf-8");
68 | const expected = await readFile(`${path}${plainFile}`, "utf-8");
69 |
70 | return {
71 | input,
72 | expected
73 | }
74 | })
75 | );
76 |
77 | const dataC = await Promise.all(
78 | garbage.map(
79 | async plainFile => readFile(`${path}${plainFile}`)
80 | )
81 | );
82 |
83 |
84 | // tests
85 | dataA.forEach((data, i) => {
86 | test(`En- and decoding for Ecoji Version 1, Test: [${i+1}|${aLen}]`, enDecodeTest, data.input, data.expectedV1, ecojiV1);
87 | test(`En- and decoding for Ecoji Version 2, Test: [${i+1}|${aLen}]`, enDecodeTest, data.input, data.expectedV2, ecojiV2);
88 | });
89 |
90 | dataB.forEach((data, i) => {
91 | test(`Decode sample data for both versions, Test: [${i+1}|${bLen}]`, decodeTest, data.input, data.expected, ecojiV2, "str");
92 | });
93 |
94 | dataC.forEach((data, i) => {
95 | test(`Garbage input > throw Error, Test: [${i+1}|${gLen}]`, errorTest, data, ecojiV2);
96 | });
97 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/ascii.garbage:
--------------------------------------------------------------------------------
1 | not emojisV2
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v1_1.enc:
--------------------------------------------------------------------------------
1 | 👖📸🎈☕🎥🤠📠🏍🐲👡🕟☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v1_1.plaind:
--------------------------------------------------------------------------------
1 | abc6789XY
2 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v1_2.enc:
--------------------------------------------------------------------------------
1 | 🏒☕☕☕🏗🈳☕☕🏟🌚👑☕🏫🍌🔥📑🏾🎌🛡🔢🐒🏣🍜🛢🐥☕☕☕🐪👆📨🐫🎈🚌☕☕🎐🚯🏛🐇🎩🤰🔓☕👖📸🎦🌭👪🕕📬🏍👺😁🚗🐿💎🚃🌤🕒
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v1_2.plaind:
--------------------------------------------------------------------------------
1 | ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrs
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v2_1.enc:
--------------------------------------------------------------------------------
1 | 👖📸🧈🌭👩☕💲🥇🪚☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v2_1.plaind:
--------------------------------------------------------------------------------
1 | abcdefxyz
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v2_2.enc:
--------------------------------------------------------------------------------
1 | 🏒☕🧏🥱☕🧝🌚👑☕🏫🍌🔥📑🧦🎌🫣🧽🐒🏣🍜🫤🐥☕🐪👆📨🐫🎈🚌☕🎐🚯🧙🐇🎩🤰🔓☕👖📸🧈🌭👪🪐📬🛼👺😁🚗🧨💎🚃🦩🪄
--------------------------------------------------------------------------------
/test/fixtures/ecoji/concat_v2_2.plaind:
--------------------------------------------------------------------------------
1 | ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrs
--------------------------------------------------------------------------------
/test/fixtures/ecoji/eight_byte.ev1:
--------------------------------------------------------------------------------
1 | 🅱🎙👁🔼🕰🦰🎈☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/eight_byte.ev2:
--------------------------------------------------------------------------------
1 | ⏳🧃🧩🩻🪤🫳🎈☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/eight_byte.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/eight_byte.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/exhaustive.ev1:
--------------------------------------------------------------------------------
1 | 💜🥪🌫🚏🛬🇦🥖🕷🐓🍮🕋🏪🥠🦶👺📺👭🔽👊🦵🥈🈸🚅🎠🎲😌🕴🍰🚾🕗🏖🌙🚒🍄🛶🌒🤤🎺🍣🦀🈁🖖🔒👖🗳🍠🤛📋👤🥯🆖🏝💋🚬🇧💃🎚🦊👶🌩🛑🗡📅😅🖕🍱🇬🈺😷🌖🖼🛡😪😿👁🀄👌💲🌭👷🚶🏙🏯🏾🚍🥘👈🍸🏆🇩🚌🛰🇸🇷🤸📕🕎🛳😥😒🦞🥼📬🔎🌇🎰🐂📭🍭💻🔱🤲😚📷🕳💒🔈🌾📌🍗😀🕸🚐🦋🆗🙆🔌🏒🎖🏁🏹🦹🚖🏫🦇📽🥒🍦🤺😮🚳🦲🍹🚠👵🚀📖🎹🥇👿🤾🌜💇🏜💯🖱😤🕤👕🗻🗂🎥🤷🖥🦑🤐🕑🏴🦉🦐🏩📍🚔🕶💰🐁🏈🏽🍪🆙🌵💨🎆🍁👪👝🔧🔥🎼🗄🛣🦴🚤🥕🎡🛢🏐🌷😴🎃🚩🍨🎋🔄🐹🥌😣📆🦠🤞🔀🏻🐻🤖🦢📙😵🥙🚎🔞🇮🏃🔝🌈🦙🙄🎏🎢😐💹🗼🐩💡📊📥🤗🛐😊🌅💿👓📀🌪🐨🕦🍷📰📚🏤💢🌯🤱🗿🍌🚁🥝👐🍲🍉🗝🥤🗞🌞🔩🈚😨🚻🔃🐘😑🍋🎧🌶😔🍻🍟👋💫🍖🤶🚄🔙🤘👦🐯🐟🏺🇳🌬🙌🏂💶🛴🆎🐅🔜🐇🌹📶🍢🦍🕓🌡🐮🔅🔭🌂💏👢📣📯📘👙🦸🌘🗨💈📁🆕🇨🕖🛤👟🐎👰🉑🍓😉🔐🦃🌉🤡🐣🍐🍽🔻💆🌝🎾💵👨🐌🐶👡🐪🔑👞🏓🙃🐍😱👸🗯📟🍛🔴🐊🎌🕢🐤👂🛀🦎🤚🤢🖌🕕🦅💎🥮🇹💤📦😂💷🧁🥗🛂🎛🚛😛🥭🚢🎦🙁🛒🔕💟📱💗🌱🎁🤫🚗🕠🙇🛌😡🦰🙅🦟🔯🛠😇📢🚭🗽🌳🍺🗣📵🏦🌑🤪🏣🔖🌄🎐👀🛹🇪🕍🦷🌍🔫📨🎙😢🎑🧐😲🥿🛩🏀🕹😏🚇🚣🚺🎎🎂🕰🈯🗃🤜🦡📮🍍🔺🌮🍂🐳🔦🥡🆔🎬💩🏸🥦🐺🏛🎓🏏🍚🎳🔳🎱🧓👏🥐🏷🧒🕛🐔💀📴🅰🕥🥳🏕👫🏄🕡🚨🚕🌲🌰🎞📩🐜📝🎣😜👻🖲🛵📓🍇🍡📼💕🏡🎸🈳🗓📸🤳🕞🏥😎🛅🌴👒🛋📿🎭🗑🚱📒📧🖍🛎🔬🎵👯🦔🐷🕺🏼🕣👗🥞🕟😽🥓🏔💖🌔😬🐥🇼😞🤹🕜🚑🚙🥧🇽🔹🥟🏧🖤🏨🛍👘🤑🎍🏞🎄🥫🈂💊🔘👬🚆💛🤩🇲💽🔂🖋🐲📛💉🍵💧🍈🇫🔟🐭🌛🥴🙂📤🌁🚹🔏🏰🇱🕌😟🎟🚧🏅🕧🥏🔨🧔💄🏚🔉🚫🐿😹🏮🤰🍊🐐🌟🙎💐📪🐕🖨👾📃🚞🍤🎗🐠🎪📜😺🚜🍙💍🍅🈹👇👧🇵🍑🌎🌼🐄🇯💞🛏🔸👱🆓🧀🛄🎶🗾💱🦕💥🔛🌆🌕💓🕵💅🔇🏳👃📔😻🍎🚚🎤🥛👄🈲🙏🤧🕯🔚🕚👔🐗🇴🚸🛁📂🌽🍴💳👹🏎😙🦗🇰👜🚘🤽🥉🤟👍🎊😦🦁🙊🐡🦛🔢📫🐒👣🥥🧂🚟🕔🈷🦖📳📻🚼🔰😫🚰💁🎇🐝🌊🍀🕉🔤🚥🔼🖐🐵🌓👛🍫📇🛸🕐🛃🚯🐖🥁🎿🧑🍿📏💚🚊🔡🥣🎯🇺🧕🔊🏵🥽🦘💮📞🏉🔮🥚👼😍🚋🔠👳💪🍃👅🤒🏋💦😘👠😩🚃🐾👥🥔🍆🥰📉😳😓🔪😶🎀🤯🚓😈🥋🆚💸🤔🎫🥬🐼🌗🤵🤦🆘🏢📹🥊🎻🍯🕊🚵🙈🐸🚉💺📗🐴🦜🐱😾👚😰🔍🕒🍜👑🍒🆑🏗📲🌿🦳🇿😸🍏🍔😠🦒🍳🏿🔋🔓🚈🥵🚦🆒🥺🦱😯🦝📄🖊🔶🥾🔵🥄😧🌠🐰💾🕝🌺🏬🐀🤭🐞🌻🤕🐽😖🐙🎷👉🌤🖇🤼🔷🦓🐢🙉🚂🅾🐦😼🍾🇻🗺🤥🥂🈵💘🎅🐑😄🥑🍶🤣🎽🗜👴🚲🇭🌸🤙🚽🍬🔆🏠📎🍞🥃🦏🌐📡🐧😁🦆🛥🐃👩🅱🎉📠🤝🦚🌥😆🌃🔣🤨🥩🌨💭🐫🔲🍼🎈💠🥨🕘🐛🥍📈🥢🏭🐉💣🤮🎒🍕🌋🅿🤠💔💴🌀📐🕙🎩😃🌌💼🥶🤬🐏🥜🇶🌦🔗🥅😝🙀🈶🤴😗💝😕💂🔁🍥🈴🥎🍧🛷🛫🉐🏌🚮💬🚷🚡🏘🐚🌏😋👲🍝🐈💙🏊🙍🚴😭💌🌚🏟🎴🗒👎🐋👆👽👮🥀🎨🤓🦂🐬🦌🚝🚿🐆💑🏑🇾🔔🍩🍘🦄🌧🏇🃏🦈🚪🎮
--------------------------------------------------------------------------------
/test/fixtures/ecoji/exhaustive.ev2:
--------------------------------------------------------------------------------
1 | 💜🥪🦺🚏🛬♿🥖🪩🐓🍮🕋🏪🥠🦶👺📺👭🩼👊🦵🥈🦣🚅🎠🎲😌🪦🍰🚾🪒🧎🌙🚒🍄🛶🌒🤤🎺🍣🦀🈁🖖🔒👖🫖🍠🤛📋👤🥯♏🧛💋🚬⚓💃🧄🦊👶🦮🛑🫒🧬😅🖕🍱⛅🦥😷🌖🪹🫣😪😿🧩🀄👌💲🌭👷🚶🧗🏯🧦🚍🥘👈🍸🏆⚽🚌🫱⭐✨🤸📕🕎🫲😥😒🦞🥼📬🔎🌇🎰🐂📭🍭💻🔱🤲😚📷🪥💒🔈🌾📌🍗😀🪪🚐🦋♐🙆🔌🏒🦾🏁🏹🦹🚖🏫🦇🧮🥒🍦🤺😮🚳🫵🍹🚠👵🚀📖🎹🥇👿🤾🌜💇🧚💯🪷😤🪟👕🗻🪺🎥🤷🪵🦑🤐🪃🏴🦉🦐🏩📍🚔🪨💰🐁🏈🧥🍪♒🌵💨🎆🍁👪👝🔧🔥🎼🫁🫥🦴🚤🥕🎡🫤🏐🌷😴🎃🚩🍨🎋🧳🐹🥌😣📆🦠🤞🧯🧣🐻🤖🦢📙😵🥙🚎🧹⛔🏃🧸🌈🦙🙄🎏🎢😐🧪🗼🐩💡📊📥🤗🛐😊🌅💿👓📀🦯🐨🪡🍷📰📚🏤💢🌯🤱🗿🍌🚁🥝👐🍲🍉🫐🥤🫑🌞🔩🤌😨🚻🧲🐘😑🍋🎧🦼😔🍻🍟👋💫🍖🤶🚄🧴🤘👦🐯🐟🏺⛺🦻🙌🏂💶🛴♉🐅🧷🐇🌹📶🍢🦍🪅🦨🐮🔅🔭🌂💏👢📣📯📘👙🦸🌘🫔💈🧫♎⚡🪑🫦👟🐎👰🦧🍓😉🔐🦃🌉🤡🐣🍐🦽🩺💆🌝🎾💵👨🐌🐶👡🐪🔑👞🏓🙃🐍😱👸🫕📟🍛🩰🐊🎌🪝🐤👂🛀🦎🤚🤢🪲🪐🦅💎🥮🛕💤📦😂💷🧁🥗🛂🧅🚛😛🥭🚢🧈🙁🛒🔕💟📱💗🌱🎁🤫🚗🪛🙇🛌😡🫳🙅🦟🔯🫢😇📢🚭🗽🌳🍺🫓📵🏦🌑🤪🏣🔖🌄🎐👀🛹⚾🕍🦷🌍🔫📨🧃😢🎑🧐😲🥿🫰🏀🪫😏🚇🚣🚺🎎🎂🪤🤏🫀🤜🦡📮🍍🩹🌮🍂🐳🔦🥡♍🎬💩🏸🥦🐺🧙🎓🏏🍚🎳🔳🎱🧓👏🥐🧢🧒🪖🐔💀🧭⏰🪠🥳🧍👫🏄🪜🚨🚕🌲🌰🧆📩🐜📝🎣😜👻🪸🛵📓🍇🍡📼💕🏡🎸🥱🫄📸🤳🪙🏥😎🛅🌴👒🫘📿🎭🫂🚱📒📧🪳🫠🔬🎵👯🦔🐷🕺🧤🪞👗🥞🪚😽🥓🧌💖🌔😬🐥🛝😞🤹🪗🚑🚙🥧🛞🩸🥟🧞🖤🏨🫙👘🤑🎍🧜🎄🥫🛻💊🔘👬🚆💛🤩⛵💽🧱🪱🐲📛💉🍵💧🍈⛄🧺🐭🌛🥴🙂📤🌁🚹🔏🏰⛳🕌😟🧇🚧🏅🪢🥏🔨🧔💄🧘🔉🚫🧨😹🏮🤰🍊🐐🌟🙎💐📪🐕🪶👾📃🚞🍤🦿🐠🎪📜😺🚜🍙💍🍅🦤👇👧✊🍑🌎🌼🐄⛪💞🫡🩴👱♌🧀🛄🎶🗾💱🦕💥🧶🌆🌕💓🪧💅🔇🧟👃📔😻🍎🚚🎤🥛👄🤿🙏🤧🪣🧵🪕👔🐗⛽🚸🛁📂🌽🍴💳👹🧋😙🦗⛲👜🚘🤽🥉🤟👍🎊😦🦁🙊🐡🦛🧽📫🐒👣🥥🧂🚟🪆🥻🦖📳📻🚼🔰😫🚰💁🎇🐝🌊🍀🪀🧿🚥🩻🪴🐵🌓👛🍫📇🛸🪂🛃🚯🐖🥁🎿🧑🍿📏💚🚊🧼🥣🎯🛖🧕🔊🧠🥽🦘💮📞🏉🔮🥚👼😍🚋🧻👳💪🍃👅🤒🧉💦😘👠😩🚃🐾👥🥔🍆🥰📉😳😓🔪😶🎀🤯🚓😈🥋♓💸🤔🎫🥬🐼🌗🤵🤦♑🏢📹🥊🎻🍯🪁🚵🙈🐸🚉💺📗🐴🦜🐱😾👚😰🔍🪄🍜👑🍒♊🧏📲🌿🫶🛺😸🍏🍔😠🦒🍳🧧🔋🔓🚈🥵🚦♋🥺🫴😯🦝📄🪰🩲🥾🩱🥄😧🌠🐰💾🪘🌺🏬🐀🤭🐞🌻🤕🐽😖🐙🎷👉🦩🪬🤼🩳🦓🐢🙉🚂☔🐦😼🍾🛗🫗🤥🥂🥸💘🎅🐑😄🥑🍶🤣🎽🫅👴🚲⛎🌸🤙🚽🍬🔆🏠📎🍞🥃🦏🌐📡🐧😁🦆🫧🐃👩⏳🎉📠🤝🦚🦪😆🌃🧾🤨🥩🦭💭🐫🔲🍼🎈💠🥨🪓🐛🥍📈🥢🏭🐉💣🤮🎒🍕🌋♈🤠💔💴🌀📐🪔🎩😃🌌💼🥶🤬🐏🥜✋🦫🔗🥅😝🙀🥹🤴😗💝😕💂🧰🍥🥲🥎🍧🛷🛫🦦🧊🚮💬🚷🚡🧖🐚🌏😋👲🍝🐈💙🏊🙍🚴😭💌🌚🧝🎴🫃👎🐋👆👽👮🥀🎨🤓🦂🐬🦌🚝🚿🐆💑🏑🛟🔔🍩🍘🦄🦬🏇🃏🦈🚪🎮
--------------------------------------------------------------------------------
/test/fixtures/ecoji/exhaustive.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/exhaustive.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/five_byte.ev1:
--------------------------------------------------------------------------------
1 | 🗺🎫🥰🏳
--------------------------------------------------------------------------------
/test/fixtures/ecoji/five_byte.ev2:
--------------------------------------------------------------------------------
1 | 🫗🎫🥰🧟
--------------------------------------------------------------------------------
/test/fixtures/ecoji/five_byte.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/five_byte.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_1.ev1:
--------------------------------------------------------------------------------
1 | 🀄🆚🍈⚜
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_1.ev2:
--------------------------------------------------------------------------------
1 | 🀄♓🍈🥷
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_1.plain:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_2.ev1:
--------------------------------------------------------------------------------
1 | 🀄🆚🍈🏍
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_2.ev2:
--------------------------------------------------------------------------------
1 | 🀄♓🍈🛼
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_2.plain:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_3.ev1:
--------------------------------------------------------------------------------
1 | 🀄🆚🍈📑
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_3.ev2:
--------------------------------------------------------------------------------
1 | 🀄♓🍈📑
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_3.plain:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_4.ev1:
--------------------------------------------------------------------------------
1 | 🀄🆚🍈🙋
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_4.ev2:
--------------------------------------------------------------------------------
1 | 🀄♓🍈🙋
--------------------------------------------------------------------------------
/test/fixtures/ecoji/four_byte_4.plain:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/incorrect_v1_padding.garbage:
--------------------------------------------------------------------------------
1 | 🌶🌶🌶🌶🌶
--------------------------------------------------------------------------------
/test/fixtures/ecoji/misplaced_padding_1.garbage:
--------------------------------------------------------------------------------
1 | ⚜🃏🅰🅱
--------------------------------------------------------------------------------
/test/fixtures/ecoji/misplaced_padding_2.garbage:
--------------------------------------------------------------------------------
1 | 🥷🃏⏰⏳
--------------------------------------------------------------------------------
/test/fixtures/ecoji/misplaced_padding_3.garbage:
--------------------------------------------------------------------------------
1 | 🃏🏍🅰🅱
--------------------------------------------------------------------------------
/test/fixtures/ecoji/misplaced_padding_4.garbage:
--------------------------------------------------------------------------------
1 | 🃏⏰🙋⏳
--------------------------------------------------------------------------------
/test/fixtures/ecoji/misplaced_padding_5.garbage:
--------------------------------------------------------------------------------
1 | 🀄🅰☕🤾
--------------------------------------------------------------------------------
/test/fixtures/ecoji/misplaced_padding_6.garbage:
--------------------------------------------------------------------------------
1 | ☕🃏⏰⏳
--------------------------------------------------------------------------------
/test/fixtures/ecoji/misplaced_padding_7.garbage:
--------------------------------------------------------------------------------
1 | 🃏⏰⏳☔☕☕☕☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/missing_padding_1.garbage:
--------------------------------------------------------------------------------
1 | 🃏⏰⏳
--------------------------------------------------------------------------------
/test/fixtures/ecoji/missing_padding_2.garbage:
--------------------------------------------------------------------------------
1 | 🃏⏰⏳☔♈
--------------------------------------------------------------------------------
/test/fixtures/ecoji/mixed_1.garbage:
--------------------------------------------------------------------------------
1 | 🀄🅰🤿🤾
--------------------------------------------------------------------------------
/test/fixtures/ecoji/mixed_2.garbage:
--------------------------------------------------------------------------------
1 | 🀄🤿🅰🤾
--------------------------------------------------------------------------------
/test/fixtures/ecoji/mixed_3.garbage:
--------------------------------------------------------------------------------
1 | 🀄🅰🅰🤾🀄🅰🅰🤾🀄🅰🤿🤾
--------------------------------------------------------------------------------
/test/fixtures/ecoji/mixed_4.garbage:
--------------------------------------------------------------------------------
1 | 🀄🅰🀄🥷
--------------------------------------------------------------------------------
/test/fixtures/ecoji/mixed_5.garbage:
--------------------------------------------------------------------------------
1 | 🀄🅰🀄🛼
--------------------------------------------------------------------------------
/test/fixtures/ecoji/mixed_6.garbage:
--------------------------------------------------------------------------------
1 | 🀄🀄🤿⚜
--------------------------------------------------------------------------------
/test/fixtures/ecoji/mixed_7.garbage:
--------------------------------------------------------------------------------
1 | 🀄🀄🤿🏍
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_0.ev1:
--------------------------------------------------------------------------------
1 | 🛥🏻🦲🌩🔶🏳🛩⚜
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_0.ev2:
--------------------------------------------------------------------------------
1 | 🫧🧣🫵🦮🩲🧟🫰🥷
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_0.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/nine_byte_0.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_1.ev1:
--------------------------------------------------------------------------------
1 | 🛥🏻🦲🌩🔶🏳🛩🏍
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_1.ev2:
--------------------------------------------------------------------------------
1 | 🫧🧣🫵🦮🩲🧟🫰🛼
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_1.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/nine_byte_1.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_2.ev1:
--------------------------------------------------------------------------------
1 | 🛥🏻🦲🌩🔶🏳🛩📑
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_2.ev2:
--------------------------------------------------------------------------------
1 | 🫧🧣🫵🦮🩲🧟🫰📑
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_2.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/nine_byte_2.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_3.ev1:
--------------------------------------------------------------------------------
1 | 🛥🏻🦲🌩🔶🏳🛩🙋
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_3.ev2:
--------------------------------------------------------------------------------
1 | 🫧🧣🫵🦮🩲🧟🫰🙋
--------------------------------------------------------------------------------
/test/fixtures/ecoji/nine_byte_3.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/nine_byte_3.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/non_ecoji_emoji.garbage:
--------------------------------------------------------------------------------
1 | 🟠🟡🤍🟩
--------------------------------------------------------------------------------
/test/fixtures/ecoji/one_byte.ev1:
--------------------------------------------------------------------------------
1 | 👽☕☕☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/one_byte.ev2:
--------------------------------------------------------------------------------
1 | 👽☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/one_byte.plain:
--------------------------------------------------------------------------------
1 | k
--------------------------------------------------------------------------------
/test/fixtures/ecoji/phrase.ev1:
--------------------------------------------------------------------------------
1 | 🏗📩🎦🐇🎛📘🔯🚜💞😽🆖🐊🎱🥁🚄🌱💞😭💮🇵💢🕥🐭🔸🍉🚲🦑🐶💢🕥🔮🔺🍉📸🐮🌼👦🚟🥴📑
--------------------------------------------------------------------------------
/test/fixtures/ecoji/phrase.ev2:
--------------------------------------------------------------------------------
1 | 🧏📩🧈🐇🧅📘🔯🚜💞😽♏🐊🎱🥁🚄🌱💞😭💮✊💢🪠🐭🩴🍉🚲🦑🐶💢🪠🔮🩹🍉📸🐮🌼👦🚟🥴📑
--------------------------------------------------------------------------------
/test/fixtures/ecoji/phrase.plain:
--------------------------------------------------------------------------------
1 | Base64 is so 1999, isn't there something better?
2 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/seven_byte.ev1:
--------------------------------------------------------------------------------
1 | 🎺🌓🏏📓🚥🌸☕☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/seven_byte.ev2:
--------------------------------------------------------------------------------
1 | 🎺🌓🏏📓🚥🌸☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/seven_byte.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/seven_byte.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/six_byte.ev1:
--------------------------------------------------------------------------------
1 | 🍃💙🚑🤺🎩☕☕☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/six_byte.ev2:
--------------------------------------------------------------------------------
1 | 🍃💙🚑🤺🎩☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/six_byte.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/six_byte.plain
--------------------------------------------------------------------------------
/test/fixtures/ecoji/three_byte.ev1:
--------------------------------------------------------------------------------
1 | 🀄🆚🍈☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/three_byte.ev2:
--------------------------------------------------------------------------------
1 | 🀄♓🍈☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/three_byte.plain:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/two_byte.ev1:
--------------------------------------------------------------------------------
1 | 🀄🆚☕☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/two_byte.ev2:
--------------------------------------------------------------------------------
1 | 🀄♓☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/two_byte.plain:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/windows_newline_v2_1.enc:
--------------------------------------------------------------------------------
1 | 🎌
2 | 🚟
3 | 🦿🦣🎥🤠
4 | 📠🐁👖📸🎈☕
--------------------------------------------------------------------------------
/test/fixtures/ecoji/windows_newline_v2_1.plaind:
--------------------------------------------------------------------------------
1 | 1234567890abc
--------------------------------------------------------------------------------
/test/fixtures/ecoji/windows_newline_v2_2.enc:
--------------------------------------------------------------------------------
1 | 🎌🚟🎗🈸🎥🤠📠🐁👖📸🎈☕
2 |
--------------------------------------------------------------------------------
/test/fixtures/ecoji/windows_newline_v2_2.plaind:
--------------------------------------------------------------------------------
1 | 1234567890abc
--------------------------------------------------------------------------------
/test/fixtures/ecoji/zero_byte.ev1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/zero_byte.ev1
--------------------------------------------------------------------------------
/test/fixtures/ecoji/zero_byte.ev2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/zero_byte.ev2
--------------------------------------------------------------------------------
/test/fixtures/ecoji/zero_byte.plain:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UmamiAppearance/BaseExJS/d32c2969546bebad272325d937f0d9daabe3aed3/test/fixtures/ecoji/zero_byte.plain
--------------------------------------------------------------------------------
/test/fixtures/helpers.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 |
3 | const baseTest = test.macro(async (t, input, expected, base, ...args) => {
4 | const output = base.encode(input, ...args);
5 | if (expected !== null) {
6 | t.is(output, expected);
7 | }
8 | t.is(base.decode(output, ...args), input);
9 | });
10 |
11 |
12 | // Random integer
13 | const randInt = (min, max) => Math.floor(Math.random() * (max - min) + min);
14 |
15 | // Random byte value
16 | const randByte = (start=0) => randInt(start, 256);
17 |
18 | // Random array with a length (between 8 and 24 by default)
19 | const randArray = (nullBytes, options={}) => {
20 |
21 | if (!("start" in options)) options.start = 8;
22 | if (!("end" in options)) options.end = 24;
23 |
24 | const array = new Array();
25 | const generator = (nullBytes === null) ? () => 0 : () => randByte();
26 | let i = randInt(options.start, options.end);
27 | while (i--) {
28 | array.push(generator());
29 | }
30 | if (options.noNullStart && array.at(0) === 0) {
31 | array[0] = randByte(1);
32 | } else if (options.noNullEnd && array.at(-1) === 0) {
33 | array[array.length-1] = randByte(1);
34 | }
35 | return array
36 | }
37 |
38 | // Random string of printable ascii-chars including space
39 | const randStr = (len) => {
40 | const array = new Uint8Array(len);
41 | array.forEach((b, i) => array[i] = randInt(32, 127));
42 | return new TextDecoder("ascii").decode(array);
43 | };
44 |
45 |
46 | export { baseTest, randInt, randByte, randArray, randStr };
47 |
--------------------------------------------------------------------------------
/test/fixtures/load-json.js:
--------------------------------------------------------------------------------
1 | import { readFile } from "fs/promises";
2 |
3 | const loadEncodingMap = async () => {
4 |
5 | const absPath = import.meta.url.
6 | replace("file://", "").
7 | split("/").
8 | slice(0, -1).
9 | concat("encoding-map.json").
10 | join("/");
11 |
12 | const encodingMap = JSON.parse(await readFile(absPath));
13 |
14 | return encodingMap;
15 | };
16 |
17 | export { loadEncodingMap };
18 |
--------------------------------------------------------------------------------
/test/map.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-underscore-dangle */
2 |
3 | import * as BaseEx from "base-ex";
4 | import { baseTest } from "./fixtures/helpers.js";
5 | import { loadEncodingMap } from "./fixtures/load-json.js";
6 | import test from "ava";
7 |
8 |
9 | const encodingMap = await loadEncodingMap();
10 | for (const base in encodingMap) {
11 |
12 | const bFn = base === "LEB128"
13 | ? new BaseEx[base]("hex", "signed")
14 | : new BaseEx[base]();
15 |
16 | for (const _type in encodingMap[base]) {
17 |
18 | for (let input in encodingMap[base][_type]) {
19 | const title = `En- and decode ${base} for type ${_type} with input '${input}'`;
20 | const expected = encodingMap[base][_type][input];
21 |
22 | let type = _type;
23 | if (type === "int") {
24 | input = (input.length > 12) ? BigInt(input) : Number(input);
25 | type = (input < 0) ? "int_n" : "uint_n";
26 | } else if (type === "float") {
27 | input = Number(input);
28 | type = "float_n";
29 | } else if (type === "decimal") {
30 | input = Number(input);
31 | }
32 |
33 | test(title, baseTest, input, expected, bFn, type);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/test/number-mode.test.js:
--------------------------------------------------------------------------------
1 | import * as BaseEx from "base-ex";
2 | import { baseTest } from "./fixtures/helpers.js";
3 | import test from 'ava';
4 |
5 |
6 | const numbers = [
7 | -Number.MAX_VALUE,
8 | -(2**256),
9 | -(2**128),
10 | -(2**64),
11 | -(2**32),
12 | -(2**16),
13 | -(2**8),
14 | -2,
15 | -1.23456789,
16 | -Number.MIN_VALUE,
17 | 0,
18 | Number.MIN_VALUE,
19 | 1.23456789,
20 | 2**16,
21 | 2**32,
22 | 2**64,
23 | 2**128,
24 | 2**256,
25 | Number.MAX_VALUE
26 | ];
27 |
28 | const numbersNoMIN = [
29 | ...numbers.slice(0, 9),
30 | 0,
31 | ...numbers.slice(12)
32 | ];
33 |
34 |
35 | for (const base in BaseEx) {
36 |
37 | if (base !== "Base1" && base !== "BaseEx" && base !== "SimpleBase") {
38 |
39 | let bFn, num;
40 |
41 | if (base === "LEB128") {
42 | bFn = new BaseEx[base]("number", "signed");
43 | num = numbersNoMIN;
44 | }
45 |
46 | else if (base === "BasePhi") {
47 | bFn = new BaseEx.BasePhi("number");
48 | num = numbersNoMIN;
49 | }
50 |
51 | else {
52 | bFn = new BaseEx[base]("number");
53 | num = numbers;
54 | }
55 |
56 | for (const n of num) {
57 | test(
58 | `Encode and decode back for ${base} with input '${n}'`,
59 | baseTest,
60 | n,
61 | null,
62 | bFn
63 | );
64 | }
65 | }
66 | }
67 |
68 |
69 | for (let radix=2; radix<=62; radix++) {
70 | const bFn = new BaseEx.SimpleBase(radix, "number");
71 |
72 | for (const n of numbersNoMIN) {
73 | test(
74 | `Encode and decode back for SimpleBase${radix} with input '${n}'`,
75 | baseTest,
76 | n,
77 | null,
78 | bFn
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/test/random-io.test.js:
--------------------------------------------------------------------------------
1 | import * as BaseEx from "base-ex";
2 | import { baseTest, randArray, randInt, randStr } from "./fixtures/helpers.js";
3 | import test from 'ava';
4 |
5 | let ITERATIONS = 4;
6 | process.argv.forEach(arg => {
7 | if ((/^iter=/).test(arg)) {
8 | ITERATIONS = arg.split("=").at(1)|0
9 | }
10 | });
11 |
12 | const randBytesTest = test.macro(async (t, input, baseObj) => {
13 | const output = baseObj.encode(input);
14 | const backDecoded = baseObj.decode(output, "bytes").toString();
15 | t.is(backDecoded, input.toString());
16 | });
17 |
18 |
19 | const randomInputs = (ignoreNullEnd, ignoreNullStart=false) => {
20 |
21 | const noNullStart = !ignoreNullEnd;
22 | const noNullEnd = !ignoreNullStart;
23 |
24 | const randBytesX = new Uint8Array(randArray(false, {
25 | start: 1,
26 | end: randInt(1, 512),
27 | noNullStart,
28 | noNullEnd
29 | }));
30 |
31 | const randStr16 = randStr(16);
32 | const randStr32 = randStr(32);
33 | const randStrX = randStr(randInt(1, 512));
34 |
35 | const inputs = {
36 | bytes: {
37 | randBytesX
38 | },
39 | str: {
40 | randStr16,
41 | randStr32,
42 | randStrX
43 | }
44 | };
45 |
46 | if (!ignoreNullEnd) {
47 | inputs.bytes.randBytesNullEnd = new Uint8Array([
48 | ...randArray(false, {noNullStart}),
49 | ...randArray(null),
50 | ...randArray(),
51 | ...randArray(null)
52 | ]);
53 | }
54 |
55 | if (!ignoreNullStart) {
56 | inputs.bytes.randBytesNullStart= new Uint8Array([
57 | ...randArray(null),
58 | ...randArray(),
59 | ...randArray(null),
60 | ...randArray(false, {noNullEnd})
61 | ]);
62 | }
63 | return inputs;
64 | };
65 |
66 |
67 | [...Array(ITERATIONS).keys()].forEach(async i => {
68 |
69 | Object.keys(BaseEx).forEach(async base => {
70 |
71 | if (base !== "Base1" && base !== "BaseEx" && base !== "SimpleBase") {
72 |
73 | const bFn = new BaseEx[base]();
74 | const inputs = randomInputs(
75 | bFn.littleEndian || base === "ByteConverter",
76 | base === "BasePhi"
77 | );
78 |
79 | for (const input in inputs.bytes) {
80 | test(
81 | `Iteration ${i} - Encode and decode back for ${base} (type bytes) with input <${input}>`,
82 | randBytesTest,
83 | inputs.bytes[input],
84 | bFn
85 | );
86 | }
87 |
88 | for (const input in inputs.str) {
89 | test(
90 | `Iteration ${i} - Encode and decode back for ${base} (type string) with input <${input}>`,
91 | baseTest,
92 | inputs.str[input],
93 | null,
94 | bFn,
95 | "str"
96 | );
97 | }
98 | }
99 | });
100 |
101 |
102 | for (let radix=2; radix<=62; radix++) {
103 |
104 | const bFn = new BaseEx.SimpleBase(radix);
105 | const inputs = randomInputs(bFn.littleEndian, (radix === 2 || radix === 16));
106 |
107 | for (const input in inputs.bytes) {
108 | test(
109 | `Iteration ${i} - Encode and decode back for SimpleBase${radix} (type bytes) with input <${input}>`,
110 | randBytesTest,
111 | inputs.bytes[input],
112 | bFn
113 | );
114 | }
115 |
116 | for (const input in inputs.str) {
117 | test(
118 | `Iteration ${i} - Encode and decode back for SimpleBase${radix} (type string) with input <${input}>`,
119 | baseTest,
120 | inputs.str[input],
121 | null,
122 | bFn,
123 | "str"
124 | );
125 | }
126 | }
127 | });
128 |
129 |
--------------------------------------------------------------------------------
/test/simple-base.test.js:
--------------------------------------------------------------------------------
1 | import { SimpleBase } from "base-ex";
2 | import { baseTest } from "./fixtures/helpers.js";
3 | import test from "ava";
4 |
5 | /**
6 | * Transpiled python code from an online tutorial
7 | * to have the change to compare bases gt 36
8 | *
9 | * @see: https://www.tutorialexample.com/python-convert-decimal-to-62-base-a-completed-guide-python-tutorial/
10 | */
11 | const b62 = {
12 |
13 | charset: [..."0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"],
14 |
15 | divmod: (x, y) => [ BigInt(x) / BigInt(y), BigInt(x) % BigInt(y) ],
16 |
17 | encode: (n, radix) => {
18 | let negative = false;
19 |
20 | if (n < 0) {
21 | n = -n;
22 | negative = true;
23 | }
24 | if (n == 0) {
25 | return 0;
26 | }
27 | const arr = [];
28 | let r;
29 | while (n > 0) {
30 | [n, r] = b62.divmod(n, radix);
31 | arr.unshift(b62.charset[r]);
32 | }
33 | let output = arr.join("");
34 | if (negative) {
35 | output = `-${output}`;
36 | }
37 | return output;
38 | }
39 | }
40 |
41 |
42 | const Base10 = new SimpleBase(10);
43 | const randInt = (max, min=0) => BigInt(Math.floor(Math.random() * (max - min) + min));
44 |
45 | const strToBase = (input, encoder) => {
46 | const endianness = (encoder.littleEndian) ? "LE" : "BE";
47 | const b10Integer = BigInt(Base10.encode(input, endianness));
48 | const radix = encoder.converter.radix;
49 |
50 | const output = radix > 36
51 | ? b62.encode(b10Integer, radix)
52 | : b10Integer.toString(radix);
53 |
54 | return output;
55 | };
56 |
57 | for (let radix=2; radix<=62; radix++) {
58 |
59 | const bFn = new SimpleBase(radix);
60 | const base = `Base${radix}`;
61 |
62 | // integers
63 | for (let i=8; i<=1024; i*=2) {
64 |
65 | const n = 2n**BigInt(i);
66 |
67 | for (const signMulti of [1n, -1n]) {
68 |
69 | for (const add of [-randInt(128, 2), -1n, 0n, 1n, randInt(128, 2)]) {
70 |
71 | let input = (n + add) * signMulti;
72 |
73 | if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) {
74 | input = Number(input);
75 | }
76 |
77 | const expected = radix > 36
78 | ? b62.encode(input, radix)
79 | : input.toString(radix);
80 |
81 | const numVal = (input < 0) ? "int_n" : "uint_n";
82 | const title = `En- and decode Simple${base} for type Number/BigInt with input '${input}'`;
83 |
84 | test(title, baseTest, input, expected, bFn, numVal);
85 | }
86 | }
87 | }
88 |
89 | // string
90 | let helloInput = "";
91 | "Hello World!!!".split("").forEach(c => {
92 | helloInput += c;
93 | const expected = strToBase(helloInput, bFn);
94 | const title = `En- and decode Simple${base} for type String with input '${helloInput}'`;
95 | test(title, baseTest, helloInput, expected, bFn, "str");
96 | });
97 | }
98 |
--------------------------------------------------------------------------------
/third-party-licenses/BASE2048-LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 qntm
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/third-party-licenses/BASE91-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2000-2006 Joachim Henke
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | - Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 | - Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 | - Neither the name of Joachim Henke nor the names of his contributors may be
13 | used to endorse or promote products derived from this software without
14 | specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/third-party-licenses/BIG.JS-LICENCE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | =====================
3 |
4 | Copyright © `<2022>` `Michael Mclaughlin`
5 |
6 | Permission is hereby granted, free of charge, to any person
7 | obtaining a copy of this software and associated documentation
8 | files (the “Software”), to deal in the Software without
9 | restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the
12 | Software is furnished to do so, subject to the following
13 | conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | OTHER DEALINGS IN THE SOFTWARE.
26 |
27 |
--------------------------------------------------------------------------------
/third-party-licenses/ECOJI-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 |
--------------------------------------------------------------------------------