Skip to content

Commit a08ee97

Browse files
authored
V4+1 (#50)
* Prepare for v4.0.0-alpha+1. * ++ * Update README.
1 parent 0ca55ac commit a08ee97

22 files changed

+955
-95
lines changed

CHANGELOG.md

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# CHANGELOG
22

3-
## 4.0.0-alpha
4-
53
> [!IMPORTANT]
64
> Version 4.0.0 has a _large_ set of breaking changes, including removing the
75
> vast majority of extension methods and boxed classes, in favor of using the
@@ -11,11 +9,35 @@
119
1210
[file an issue]: https://github.com/matanlurey/binary.dart/issues
1311

12+
## 4.0.0-alpha+1
13+
14+
**New features**:
15+
16+
- Added `BitList`, a compact `List<bool>` implementation that stores every
17+
element as a single bit, with implementations that are fixed-size and
18+
growable.
19+
20+
- Added `<FixedInt>.zero` and `<FixedInt>.one` as static constants.
21+
22+
- Added `collectBytes()`, a utility to convert a `Stream<List<int>>` into a
23+
`Uint8List`.
24+
25+
**Breaking changes**:
26+
27+
- Replaced `<FixedInt>.bits` with `<FixedInt>.toBitList()`:
28+
29+
```diff
30+
- final bits = Int8(0).bits;
31+
+ final bits = Int8(0).toBitList();
32+
```
33+
34+
## 4.0.0-alpha
35+
1436
**New features**:
1537

1638
Lots and lots. It will be easier to just read the API documentation.
1739

18-
**Breaking changes:**
40+
**Breaking changes**:
1941

2042
_Basically everything_. The entire API has been restructured to use extension
2143
types, and some APIs removed entirely that were either not well-thought out

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ integers.
156156
[pub_img]: https://img.shields.io/pub/v/binary.svg
157157
[gha_url]: https://github.com/matanlurey/binary.dart/actions
158158
[gha_img]: https://github.com/matanlurey/binary.dart/actions/workflows/check.yaml/badge.svg
159-
[cov_url]: https://codecov.io/gh/matanlurey/binary.dart
160-
[cov_img]: https://codecov.io/gh/matanlurey/binary.dart/branch/main/graph/badge.svg
159+
[cov_url]: https://coveralls.io/github/matanlurey/binary.dart?branch=main
160+
[cov_img]: https://coveralls.io/repos/github/matanlurey/binary.dart/badge.svg?branch=main
161161
[doc_url]: https://www.dartdocs.org/documentation/binary/latest
162162
[doc_img]: https://img.shields.io/badge/Documentation-binary-blue.svg
163163
[sty_url]: https://pub.dev/packages/oath

example/README.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Examples
2+
3+
This directory contains examples of how to use `package:binary`.
4+
5+
## [Basic](./basic.dart)
6+
7+
A simple example of how to use `package:binary` to parse and shift bits.
8+
9+
```shell
10+
$ dart example/basic.dart
11+
12+
127
13+
00000011
14+
```
15+
16+
## [Checksum](./checksum.dart)
17+
18+
Calculates the CRC32 checksum of a file.
19+
20+
```shell
21+
$ dart example/checksum.dart example/checksum.dart
22+
23+
CRC32 checksum: 13b53c2f
24+
```
25+
26+
## [Bitfield](./bitfield.dart)
27+
28+
Demonstrates decoding binary data efficiently, i.e. opcodes or binary formats.
29+
30+
```shell
31+
$ dart example/bitfield.dart
32+
33+
11011101
34+
35+
Kind: 00001101
36+
S: 00000001
37+
Level: 00000010
38+
P: 00000001
39+
```
File renamed without changes.

example/bitfield.dart

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'package:binary/binary.dart' show Uint8;
2+
3+
/// Let's assume we have the following format:
4+
/// ```txt
5+
/// 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
6+
/// - | ----- | - | -------------
7+
/// P | Level | S | Kind
8+
/// ```
9+
void main() {
10+
// Create a bit field with the format.
11+
final field = Uint8.zero
12+
.replace(0, 3, int.parse('1101', radix: 2)) // Kind
13+
.replace(4, 4, int.parse('1', radix: 2)) // S
14+
.replace(5, 6, int.parse('10', radix: 2)) // Level
15+
.replace(7, 7, int.parse('1', radix: 2)); // P
16+
17+
// P S
18+
// vv v
19+
print(field.toBinaryString()); // 11011101
20+
// ^^ ^^^^
21+
// Level Kind
22+
23+
// Now, read it back.
24+
final (kind, s, level, p) = (
25+
field.slice(0, 3),
26+
field.slice(4, 4),
27+
field.slice(5, 6),
28+
field.slice(7, 7),
29+
);
30+
31+
print('');
32+
print('Kind: ${kind.toBinaryString()}');
33+
print('S: ${s.toBinaryString()}');
34+
print('Level: ${level.toBinaryString()}');
35+
print('P: ${p.toBinaryString()}');
36+
}

example/checksum.dart

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'dart:convert' show utf8;
2+
import 'dart:typed_data';
3+
4+
import 'package:binary/binary.dart';
5+
6+
/// Examples of commom checksum algorithms using `package:binary`.
7+
void main() {
8+
// Calculate the CRC32 checksum of a list of bytes.
9+
final data = Uint8List.fromList(utf8.encode('Hello, World!'));
10+
final checksum = crc32(data);
11+
print('CRC32 checksum: ${checksum.toRadixString(16)}');
12+
}
13+
14+
/// Calculate the CRC32 checksum of a list of bytes using `CRC-32/JAMCRC`.
15+
int crc32(Uint8List data, [Uint32 initialCrc = Uint32.max]) {
16+
var crc = initialCrc;
17+
for (final byte in data) {
18+
final index = (crc.toInt() ^ byte) & 0xFF;
19+
crc = (crc >> 8) ^ _crc32Table[index];
20+
}
21+
return crc.toInt();
22+
}
23+
24+
final List<Uint32> _crc32Table = (() {
25+
// We can freely cast a Uint32List to a List<Uint32> (zero-cost).
26+
final table = Uint32List(256) as List<Uint32>;
27+
28+
// Precompute the CRC32 table.
29+
for (var i = 0; i < 256; i++) {
30+
// Cost-free conversion from int to Uint32.
31+
var crc = Uint32.fromUnchecked(i);
32+
for (var j = 0; j < 8; j++) {
33+
if (crc.nthBit(0)) {
34+
crc = (crc >> 1) ^ const Uint32.fromUnchecked(0xEDB88320);
35+
} else {
36+
crc >>= 1;
37+
}
38+
}
39+
table[i] = crc;
40+
}
41+
return table;
42+
})();

lib/binary.dart

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
/// [little endian]: https://en.wikipedia.org/wiki/Endianness
1919
library;
2020

21+
export 'src/async.dart' show collectBytes;
22+
export 'src/bit_list.dart';
2123
export 'src/descriptor.dart';
2224
export 'src/extension.dart';
2325
export 'src/int16.dart';

lib/src/async.dart

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'dart:async';
2+
import 'dart:typed_data';
3+
4+
/// Collects the bytes of a `Stream<List<int>>` into a [Uint8List].
5+
///
6+
/// This function returns a `Future<Uint8List>` that completes when the stream
7+
/// is done, and a `Future<void> Function()` that can be used to cancel the
8+
/// collection and underlying stream early.
9+
(Future<Uint8List>, Future<void> Function() cancel) collectBytes(
10+
Stream<List<int>> stream,
11+
) {
12+
final completer = Completer<Uint8List>.sync();
13+
final builder = BytesBuilder(copy: false);
14+
late final StreamSubscription<void> sub;
15+
sub = stream.listen(
16+
builder.add,
17+
onDone: () async {
18+
completer.complete(builder.toBytes());
19+
await sub.cancel();
20+
},
21+
onError: completer.completeError,
22+
cancelOnError: true,
23+
);
24+
return (completer.future, sub.cancel);
25+
}

0 commit comments

Comments
 (0)