Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions .github/workflows/ci-module.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
name: ci

on:
push:
branches:
- master
pull_request:
workflow_dispatch:
push:
branches:
- master
pull_request:
workflow_dispatch:

jobs:
test:
uses: hapijs/.github/.github/workflows/ci-module.yml@master
with:
min-node-version: 14
test:
uses: hapijs/.github/.github/workflows/ci-module.yml@min-node-22-hapi-21
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
**/node_modules
**/package-lock.json

coverage.*
coverage/

**/.DS_Store
**/._*
Expand Down
6 changes: 1 addition & 5 deletions API.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@

### encode(buffer)

Base64 encode the buffer and return it as a new Buffer.


### decode(buffer)

Base64 decode the buffer and return the result as a new buffer.


### Encoder

Transform stream that base64 encodes each chunk of the stream.
Expand All @@ -27,7 +24,6 @@ const encoder = new B64.Encoder();
stream.pipe(encoder).pipe(process.stdout);
```


### Decoder

Transform stream that base64 decodes each chunk of the stream.
Expand All @@ -52,4 +48,4 @@ Encodes value of string or buffer type in Base64 or URL encoding, function will

### base64urlDecode(value)

Decodes string into Base64 or URL encoding, function throws an error on invalid input and returns a string or buffer depending on encoding provided. Default encoding is binary.
Decodes string into Base64 or URL encoding, function throws an error on invalid input and returns a string or buffer depending on encoding provided. Default encoding is binary.
44 changes: 0 additions & 44 deletions lib/index.js

This file was deleted.

8 changes: 8 additions & 0 deletions oxfmt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import DefaultOxfmtConfig from '@hapi/oxc-plugin/oxfmt';
import { defineConfig } from 'oxfmt';

import type { OxfmtConfig } from 'oxfmt';

export default defineConfig({
...DefaultOxfmtConfig,
}) as OxfmtConfig;
11 changes: 11 additions & 0 deletions oxlint.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import HapiRecommended from '@hapi/oxc-plugin/oxlint';
import { defineConfig } from 'oxlint';

import type { OxlintConfig } from 'oxlint';

export default defineConfig({
extends: [HapiRecommended],
env: {
...HapiRecommended.env,
},
}) as OxlintConfig;
83 changes: 49 additions & 34 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
{
"name": "@hapi/b64",
"description": "Base64 streaming encoder and decoder",
"version": "6.0.1",
"repository": "git://github.com/hapijs/b64",
"main": "lib/index.js",
"files": [
"lib"
],
"keywords": [
"buffer",
"base64",
"decode",
"encode",
"stream"
],
"eslintConfig": {
"extends": [
"plugin:@hapi/module"
]
},
"dependencies": {
"@hapi/hoek": "^11.0.2"
},
"devDependencies": {
"@hapi/code": "^9.0.0",
"@hapi/eslint-plugin": "^6.0.0",
"@hapi/lab": "^25.0.1",
"@hapi/wreck": "^18.0.0"
},
"scripts": {
"test": "lab -a @hapi/code -t 100 -L",
"test-cov-html": "lab -a @hapi/code -r html -o coverage.html"
},
"license": "BSD-3-Clause"
"name": "@hapi/b64",
"version": "6.0.1",
"description": "Base64 streaming encoder and decoder",
"keywords": [
"base64",
"buffer",
"decode",
"encode",
"stream"
],
"license": "BSD-3-Clause",
"repository": "git://github.com/hapijs/b64",
"files": [
"src",
"API.md"
],
"type": "module",
"types": "src/index.d.ts",
"exports": {
".": {
"types": "./src/index.d.ts",
"default": "./src/index.js"
}
},
"scripts": {
"test": "vitest run --coverage",
"typecheck": "tsc --noEmit",
"lint": "oxlint",
"lint:fix": "oxlint --fix",
"fmt": "oxfmt --check",
"fmt:fix": "oxfmt",
"check": "npm run lint && npm run fmt && npm run typecheck && npm test"
},
"dependencies": {
"@hapi/hoek": "^12.0.0-rc.0"
},
"devDependencies": {
"@hapi/oxc-plugin": "^1.1.1",
"@hapi/wreck": "^18.0.0",
"@types/node": "^22.19.20",
"@vitest/coverage-v8": "^5.0.5",
"oxfmt": "^0.75.0",
"oxlint": "^1.90.0",
"typescript": "^6.0.3",
"vitest": "^5.0.5"
},
"engines": {
"node": ">=22"
}
}
66 changes: 23 additions & 43 deletions lib/decoder.js → src/decoder.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
'use strict';

/*
Decode functions adapted from:
Version 1.0 12/25/99 Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
http://www.onicos.com/staff/iz/amuse/javascript/expert/base64.txt
*/

const Stream = require('stream');


const internals = {
decodeChars: [
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
]
};

import Stream from 'stream';

exports.decode = function (buffer) {
const decodeChars = [
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
];

const decodeChars = internals.decodeChars;
export function decode(buffer) {
const len = buffer.length;
const allocated = Math.ceil(len / 4) * 3;
const result = Buffer.alloc(allocated);
Expand All @@ -36,20 +25,18 @@ exports.decode = function (buffer) {
let c4;
let j = 0;

for (let i = 0; i < len; ) {
for (let i = 0; i < len;) {
do {
c1 = decodeChars[buffer[i++] & 0xff];
}
while (i < len && c1 === -1);
} while (i < len && c1 === -1);

if (c1 === -1) {
break;
}

do {
c2 = decodeChars[buffer[i++] & 0xff];
}
while (i < len && c2 === -1);
} while (i < len && c2 === -1);

if (c2 === -1) {
break;
Expand All @@ -59,13 +46,12 @@ exports.decode = function (buffer) {

do {
c3 = buffer[i++] & 0xff;
if (c3 === 61) { // =
if (c3 === 61 /* = */) {
return result.slice(0, j);
}

c3 = decodeChars[c3];
}
while (i < len && c3 === -1);
} while (i < len && c3 === -1);

if (c3 === -1) {
break;
Expand All @@ -75,52 +61,46 @@ exports.decode = function (buffer) {

do {
c4 = buffer[i++] & 0xff;
if (c4 === 61) { // =
if (c4 === 61 /* = */) {
return result.slice(0, j);
}

c4 = decodeChars[c4];
}
while (i < len && c4 === -1);
} while (i < len && c4 === -1);

if (c4 !== -1) {
result[j++] = ((c3 & 0x03) << 6) | c4;
}
}

return (j === allocated ? result : result.slice(0, j));
};

return j === allocated ? result : result.slice(0, j);
}

exports.Decoder = class Decoder extends Stream.Transform {
export class Decoder extends Stream.Transform {
constructor() {

super();
this._reminder = null;
}

_transform(chunk, encoding, callback) {

let part = this._reminder ? Buffer.concat([this._reminder, chunk]) : chunk;
const remaining = part.length % 4;
if (remaining) {
this._reminder = part.slice(part.length - remaining);
part = part.slice(0, part.length - remaining);
}
else {
} else {
this._reminder = null;
}

this.push(exports.decode(part));
this.push(decode(part));
return callback();
}

_flush(callback) {

if (this._reminder) {
this.push(exports.decode(this._reminder));
this.push(decode(this._reminder));
}

return callback();
}
};
}
Loading
Loading