Skip to content

Commit af7813b

Browse files
committed
Improve codes
- Throws `FormatException` for invalid characters in codecs - Adds `base2` codes. New methods: - `fromBinary` - `toBinary` - More tests
1 parent a7c86f5 commit af7813b

18 files changed

+470
-95
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# 1.11.3
2+
3+
- Throws `FormatException` for invalid characters in codecs
4+
- Adds `base2` codes. New methods:
5+
- `fromBinary`
6+
- `toBinary`
7+
18
# 1.11.2
29

310
- Export codecs

lib/src/codecs/base16.dart

+11-12
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ const int _smallA = 97;
99
const int _bigA = 65;
1010

1111
const _base16Decoding = <int>[
12-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //
13-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
14-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1,
15-
-1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1,
16-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10,
12+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
13+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
14+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -2, -2,
15+
-2, -2, -2, -2, -2, 10, 11, 12, 13, 14, 15, -2, -2, -2, -2, -2, -2, -2, -2,
16+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 10,
1717
11, 12, 13, 14, 15,
1818
];
1919

@@ -69,21 +69,20 @@ class _B16Decoder extends Uint8Decoder {
6969
@override
7070
Iterable<int> convert(Iterable<int> input) sync* {
7171
bool f;
72-
int p, x, n;
72+
int p, x, y, n;
7373
p = 0;
7474
n = input.length;
7575
f = (n & 1 != 0);
76-
for (x in input) {
77-
if (x >= _base16Decoding.length) break;
78-
x = _base16Decoding[x];
79-
if (x == -1) break;
76+
for (y in input) {
77+
if (y >= alphabet.length || (x = alphabet[y]) < 0) {
78+
throw FormatException('Invalid character $y');
79+
}
8080
if (f) {
8181
yield (p | x);
82-
f = false;
8382
} else {
8483
p = x << 4;
85-
f = true;
8684
}
85+
f = !f;
8786
}
8887
}
8988
}

lib/src/codecs/base2.dart

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (c) 2023, Sudipto Chandra
2+
// All rights reserved. Check LICENSE file for details.
3+
4+
import 'codec.dart';
5+
import 'converter.dart';
6+
7+
const int _zero = 48;
8+
9+
class _BinaryEncoder extends Uint8Encoder {
10+
const _BinaryEncoder()
11+
: super(
12+
bits: 2,
13+
alphabet: const <int>[],
14+
);
15+
16+
@override
17+
Iterable<int> convert(Iterable<int> input) sync* {
18+
for (int x in input) {
19+
yield _zero + ((x >>> 7) & 1);
20+
yield _zero + ((x >>> 6) & 1);
21+
yield _zero + ((x >>> 5) & 1);
22+
yield _zero + ((x >>> 4) & 1);
23+
yield _zero + ((x >>> 3) & 1);
24+
yield _zero + ((x >>> 2) & 1);
25+
yield _zero + ((x >>> 1) & 1);
26+
yield _zero + ((x) & 1);
27+
}
28+
}
29+
}
30+
31+
class _BinaryDecoder extends Uint8Decoder {
32+
const _BinaryDecoder()
33+
: super(
34+
bits: 2,
35+
alphabet: const <int>[],
36+
);
37+
38+
@override
39+
Iterable<int> convert(Iterable<int> input) sync* {
40+
int p, n, x, y;
41+
n = (8 - (input.length & 7)) & 7;
42+
p = 0;
43+
for (y in input) {
44+
x = y - _zero;
45+
if (x != 0 && x != 1) {
46+
throw FormatException('Invalid character $y');
47+
}
48+
p = (p << 1) ^ x;
49+
if (n < 7) {
50+
n++;
51+
} else {
52+
yield p;
53+
n = p = 0;
54+
}
55+
}
56+
if (n > 0) {
57+
yield p;
58+
}
59+
}
60+
}
61+
62+
class BinaryCodec extends Uint8Codec {
63+
@override
64+
final encoder = const _BinaryEncoder();
65+
66+
@override
67+
final decoder = const _BinaryDecoder();
68+
69+
/// Base2 (binary) codec
70+
const BinaryCodec();
71+
}
72+
73+
/// Codec to encode and decode an iterable of 8-bit integers to 2-bit Base2
74+
/// alphabets (binary): `0` or `1`
75+
const base2 = BinaryCodec();
76+
77+
/// Encode an array of 8-bit integers to Base2 (binary) string
78+
String toBinary(Iterable<int> input) {
79+
return String.fromCharCodes(base2.encoder.convert(input));
80+
}
81+
82+
/// Decode an array of 8-bit integers from Base2 (binary) string
83+
List<int> fromBinary(String input) {
84+
return base2.decoder.convert(input.codeUnits).toList();
85+
}

lib/src/codecs/base32.dart

+11-11
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ const _base32lowerEncoding = [
1515
];
1616

1717
const _base32Decoding = [
18-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //
19-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
20-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1,
21-
-1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
22-
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1,
18+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
19+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
20+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 26, 27, 28, 29, 30, 31, -2,
21+
-2, -2, -2, -2, -1, -2, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
22+
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2, -2, 0, 1,
2323
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
2424
23, 24, 25
2525
];
@@ -28,6 +28,12 @@ class B32Codec extends Uint8Codec {
2828
@override
2929
final Uint8Encoder encoder;
3030

31+
@override
32+
final decoder = const Uint8Decoder(
33+
bits: 5,
34+
alphabet: _base32Decoding,
35+
);
36+
3137
const B32Codec()
3238
: encoder = const Uint8Encoder(
3339
bits: 5,
@@ -53,12 +59,6 @@ class B32Codec extends Uint8Codec {
5359
padding: 61,
5460
alphabet: _base32lowerEncoding,
5561
);
56-
57-
@override
58-
final decoder = const Uint8Decoder(
59-
bits: 5,
60-
alphabet: _base32Decoding,
61-
);
6262
}
6363

6464
/// Codec to encode and decode an iterable of 8-bit integers to 5-bit Base32

lib/src/codecs/base64.dart

+11-11
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ const _base64Encoding = [
1212
];
1313

1414
const _base64Decoding = [
15-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //
16-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
17-
-1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
18-
61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
19-
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,
15+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
16+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
17+
-2, -2, -2, -2, -2, 62, -2, -2, -2, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
18+
61, -2, -2, -2, -1, -2, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
19+
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2, -2, 26,
2020
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
2121
46, 47, 48, 49, 50, 51
2222
];
@@ -25,6 +25,12 @@ class B64Codec extends Uint8Codec {
2525
@override
2626
final Uint8Encoder encoder;
2727

28+
@override
29+
final decoder = const Uint8Decoder(
30+
bits: 6,
31+
alphabet: _base64Decoding,
32+
);
33+
2834
const B64Codec()
2935
: encoder = const Uint8Encoder(
3036
bits: 6,
@@ -37,12 +43,6 @@ class B64Codec extends Uint8Codec {
3743
padding: 61,
3844
alphabet: _base64Encoding,
3945
);
40-
41-
@override
42-
final decoder = const Uint8Decoder(
43-
bits: 6,
44-
alphabet: _base64Decoding,
45-
);
4646
}
4747

4848
/// Codec to encode and decode an iterable of 8-bit integers to 6-bit Base64

lib/src/codecs/base64url.dart

+11-11
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ const _base64urlEncoding = [
1212
];
1313

1414
const _base64urlDecoding = [
15-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //
16-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
17-
-1, -1, -1, -1, -1, -1, -1, 62, -1, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60,
18-
61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
19-
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26,
15+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
16+
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
17+
-2, -2, -2, -2, -2, -2, -2, 62, -2, -2, 52, 53, 54, 55, 56, 57, 58, 59, 60,
18+
61, -2, -2, -2, -1, -2, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
19+
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, 63, -2, 26,
2020
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
2121
46, 47, 48, 49, 50, 51
2222
];
@@ -25,6 +25,12 @@ class B64URLCodec extends Uint8Codec {
2525
@override
2626
final Uint8Encoder encoder;
2727

28+
@override
29+
final decoder = const Uint8Decoder(
30+
bits: 6,
31+
alphabet: _base64urlDecoding,
32+
);
33+
2834
const B64URLCodec()
2935
: encoder = const Uint8Encoder(
3036
bits: 6,
@@ -37,12 +43,6 @@ class B64URLCodec extends Uint8Codec {
3743
padding: 61,
3844
alphabet: _base64urlEncoding,
3945
);
40-
41-
@override
42-
final decoder = const Uint8Decoder(
43-
bits: 6,
44-
alphabet: _base64urlDecoding,
45-
);
4646
}
4747

4848
/// Codec to encode and decode an iterable of 8-bit integers to URL-safe Base64

lib/src/codecs/converter.dart

+9-8
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,17 @@ class Uint8Encoder extends Uint8Converter {
5353
for (x in input) {
5454
p = (p << 8) | x;
5555
for (n += 8; n >= bits; n -= bits, p &= (1 << n) - 1) {
56-
l++;
56+
l += bits;
5757
yield alphabet[p >>> (n - bits)];
5858
}
5959
}
6060
if (n > 0) {
61-
l++;
61+
l += bits;
6262
yield alphabet[p << (bits - n)];
6363
}
6464
if (padding != null) {
6565
p = padding!;
66-
for (; ((l & 7) * (bits & 7)) & 7 != 0; l++) {
66+
for (; (l & 7) != 0; l += bits) {
6767
yield p;
6868
}
6969
}
@@ -81,12 +81,13 @@ class Uint8Decoder extends Uint8Converter {
8181

8282
@override
8383
Iterable<int> convert(Iterable<int> input) sync* {
84-
int p, n, x;
84+
int p, n, x, y;
8585
p = n = 0;
86-
for (x in input) {
87-
if (x >= alphabet.length) break;
88-
x = alphabet[x];
89-
if (x == -1) break;
86+
for (y in input) {
87+
if (y >= alphabet.length || (x = alphabet[y]) == -2) {
88+
throw FormatException('Invalid character $y');
89+
}
90+
if (x < 0) return;
9091
p = (p << bits) | x;
9192
for (n += bits; n >= 8; n -= 8, p &= (1 << n) - 1) {
9293
yield (p >>> (n - 8));

lib/src/codecs_base.dart

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// All rights reserved. Check LICENSE file for details.
33

44
export 'codecs/ascii.dart' hide ASCIICodec;
5+
export 'codecs/base2.dart' hide BinaryCodec;
56
export 'codecs/base16.dart' hide B16Codec;
67
export 'codecs/base32.dart' hide B32Codec;
78
export 'codecs/base64.dart' hide B64Codec;

lib/src/xxh128.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class XXH128 extends BlockHashBase {
3232

3333
/// Creates a new instance of [XXH128].
3434
///
35-
/// Paramters:
35+
/// Parameters:
3636
/// - [seed] is an optional 64-bit integer. Default: 0
3737
/// - [secret] is an array of bytes. The length should be at least 136.
3838
/// - If the [secret] is present, the [seed] is ignored.

lib/src/xxh3.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class XXH3 extends BlockHashBase {
3232

3333
/// Creates a new instance of [XXH3].
3434
///
35-
/// Paramters:
35+
/// Parameters:
3636
/// - [seed] is an optional 64-bit integer. Default: 0
3737
/// - [secret] is an array of bytes. The length should be at least 136.
3838
/// - If the [secret] is present, the [seed] is ignored.

lib/src/xxh32.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class XXHash32 extends BlockHashBase {
2525

2626
/// Creates a new instance of [XXHash32].
2727
///
28-
/// Paramters:
28+
/// Parameters:
2929
/// - [seed] is an optional 32-bit integer. Default: 0
3030
const XXHash32([this.seed = 0]);
3131

lib/src/xxh64.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class XXHash64 extends BlockHashBase {
2525

2626
/// Creates a new instance of [XXHash64].
2727
///
28-
/// Paramters:
28+
/// Parameters:
2929
/// - [seed] is an optional 64-bit integer. Default: 0
3030
const XXHash64([this.seed = 0]);
3131

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: hashlib
22
description: Secure hash functions, checksum generators, and key derivation algorithms optimized for Dart.
33
homepage: https://github.com/dipu-bd/hashlib
4-
version: 1.11.2
4+
version: 1.11.3
55

66
environment:
77
sdk: ">=2.14.0 <4.0.0"

0 commit comments

Comments
 (0)