Skip to content

Commit 03e0742

Browse files
committed
feat(base32): add noPadding option
Signed-off-by: Chen Su <ghosind@gmail.com>
1 parent f1864a3 commit 03e0742

4 files changed

Lines changed: 61 additions & 18 deletions

File tree

src/base32.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ export interface Base32Options {
2525
*/
2626
encoder?: string;
2727

28+
/**
29+
* Disable padding character when encoding the data. Default false. This option is equivalent
30+
* to setting `padChar` to empty string, and has higher priority than `padChar`.
31+
*/
32+
noPadding?: boolean;
33+
2834
/**
2935
* Padding character for padding when the encoded string in bytes is not a number to a multiple
3036
* of 8, or set it to empty string to disable padding. The padding character must not be newline
@@ -39,10 +45,16 @@ export class Base32Encoding {
3945
*/
4046
private encoder: string;
4147

48+
/**
49+
* Disable padding character when encoding the data. Default false. This option is equivalent
50+
* to setting `padChar` to empty string, and has higher priority than `padChar`.
51+
*/
52+
private noPadding?: boolean;
53+
4254
/**
4355
* The default padding character.
4456
*/
45-
private padChar: string;
57+
private padChar?: string;
4658

4759
/**
4860
* Creates a Base32 encoding instance with the optional encoder alphabets and padding character
@@ -57,16 +69,20 @@ export class Base32Encoding {
5769
* @param options Optional settings for Base32 encoding.
5870
*/
5971
constructor(options?: Base32Options) {
60-
let padChar: string | undefined;
61-
if (options?.padChar !== undefined) {
62-
padChar = checkPadChar(options.padChar);
72+
this.noPadding = !!options?.noPadding;
73+
74+
if (!this.noPadding) {
75+
let padChar: string | undefined;
76+
if (options?.padChar !== undefined) {
77+
padChar = checkPadChar(options.padChar);
78+
}
79+
this.padChar = padChar !== undefined ? padChar : '=';
6380
}
64-
this.padChar = padChar !== undefined ? padChar : '=';
6581

6682
this.encoder = checkEncoder(
6783
options?.encoder ? options.encoder : Base32StdEncoder,
68-
this.padChar,
6984
ENCODER_LENGTH,
85+
this.padChar,
7086
);
7187
}
7288

@@ -206,7 +222,9 @@ export class Base32Encoding {
206222
let padChar;
207223
let encoder;
208224

209-
if (!options || options.padChar === undefined || checkPadChar(options.padChar) === undefined) {
225+
if (this.noPadding || !!options?.noPadding) {
226+
padChar = '';
227+
} else if (!options || options.padChar === undefined || checkPadChar(options.padChar) === undefined) {
210228
padChar = this.padChar;
211229
} else {
212230
padChar = options.padChar;
@@ -218,11 +236,11 @@ export class Base32Encoding {
218236
encoder = options.encoder;
219237
}
220238

221-
encoder = checkEncoder(encoder, padChar, 32);
239+
encoder = checkEncoder(encoder, ENCODER_LENGTH, padChar);
222240

223241
return {
224242
encoder,
225-
padChar,
243+
padChar: padChar!,
226244
};
227245
}
228246
}

src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
* `'\n'`) or the padding character.
55
*
66
* @param encoder The encoding alphabets for BaseXX encoding.
7-
* @param padChar The padding character.
87
* @param base The base number.
8+
* @param padChar The padding character.
99
* @returns The valid encoder alphabets.
1010
* @throws The length in bytes of encoder alphabets is not equals to the base number.
1111
* @throws The encoder alphabets contains the padding character.
1212
* @throws The encoder alphabets contains the newline character ('\r' or '\n').
1313
*/
14-
export const checkEncoder = (encoder: string, padChar: string, base: number): string => {
14+
export const checkEncoder = (encoder: string, base: number, padChar?: string): string => {
1515
if (encoder?.length !== base || new TextEncoder().encode(encoder).length !== base) {
1616
throw new Error(`encoding alphabet is not ${base}-bytes.`);
1717
}

test/base32.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ describe('Test base32 encode', () => {
2727
});
2828

2929
it('Test base32 encode with standard encoder and no padding character', () => {
30+
const encoder = new Base32Encoding({
31+
noPadding: true,
32+
});
33+
34+
assert.equal(encoder.encode(''), '');
35+
assert.equal(encoder.encode('f'), 'MY');
36+
assert.equal(encoder.encode('fo'), 'MZXQ');
37+
assert.equal(encoder.encode('foo'), 'MZXW6');
38+
assert.equal(encoder.encode('foob'), 'MZXW6YQ');
39+
assert.equal(encoder.encode('fooba'), 'MZXW6YTB');
40+
assert.equal(encoder.encode('foobar'), 'MZXW6YTBOI');
41+
});
42+
43+
it('Test base32 encode with standard encoder and empty padding character', () => {
3044
const encoder = new Base32Encoding({
3145
padChar: '',
3246
});
@@ -165,7 +179,16 @@ describe('Test base32 decode', () => {
165179
assert.equal(decoder.decode('CO======', options), 'f');
166180
assert.equal(decoder.decode('CPNG====', options), 'fo');
167181

182+
options.noPadding = true;
183+
assert.equal(decoder.decode('CPNMU', options), 'foo');
184+
assert.equal(decoder.decode('CPNMUOG', options), 'foob');
185+
186+
// set padding character but noPadding is true, so padChar is ignored.
168187
options.padChar = '+';
188+
assert.equal(decoder.decode('CPNMU', options), 'foo');
189+
assert.equal(decoder.decode('CPNMUOG', options), 'foob');
190+
191+
options.noPadding = false;
169192
assert.equal(decoder.decode('CPNMU+++', options), 'foo');
170193
assert.equal(decoder.decode('CPNMUOG+', options), 'foob');
171194

test/utils.spec.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ import { checkEncoder, checkPadChar, decodeBytes } from '../src/utils';
66

77
describe('Test check encoder', () => {
88
it('Test check encoder', () => {
9-
assert.doesNotThrow(() => checkEncoder(Base32StdEncoder, '=', 32));
9+
assert.doesNotThrow(() => checkEncoder(Base32StdEncoder, 32));
10+
assert.doesNotThrow(() => checkEncoder(Base32StdEncoder, 32, ''));
11+
assert.doesNotThrow(() => checkEncoder(Base32StdEncoder, 32, '='));
1012
// @ts-ignore
11-
assert.throws(() => checkEncoder(undefined, '=', 32));
12-
assert.throws(() => checkEncoder(`${Base32StdEncoder},.`, '=', 32));
13-
assert.throws(() => checkEncoder('å∫ç∂´ƒ©˙ˆ∆˚¬µ˜øπœ®ß†¨√∑≈¥234567', '=', 32));
14-
assert.throws(() => checkEncoder(Base32StdEncoder, 'A', 32));
15-
assert.throws(() => checkEncoder('ABCDEFGHIJKLMNOPQRSTUVWXYZ23456\n', '=', 32));
16-
assert.throws(() => checkEncoder('ABCDEFGHIJKLMNOPQRSTUVWXYZ23456\r', '=', 32));
13+
assert.throws(() => checkEncoder(undefined, 32, '='));
14+
assert.throws(() => checkEncoder(`${Base32StdEncoder},.`, 32, '='));
15+
assert.throws(() => checkEncoder('å∫ç∂´ƒ©˙ˆ∆˚¬µ˜øπœ®ß†¨√∑≈¥234567', 32, '='));
16+
assert.throws(() => checkEncoder(Base32StdEncoder, 32, 'A'));
17+
assert.throws(() => checkEncoder('ABCDEFGHIJKLMNOPQRSTUVWXYZ23456\n', 32, '='));
18+
assert.throws(() => checkEncoder('ABCDEFGHIJKLMNOPQRSTUVWXYZ23456\r', 32, '='));
1719
});
1820
});
1921

0 commit comments

Comments
 (0)