Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V4+1 #50

Merged
merged 3 commits into from
Aug 3, 2024
Merged

V4+1 #50

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
28 changes: 25 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# CHANGELOG

## 4.0.0-alpha

> [!IMPORTANT]
> Version 4.0.0 has a _large_ set of breaking changes, including removing the
> vast majority of extension methods and boxed classes, in favor of using the
Expand All @@ -11,11 +9,35 @@

[file an issue]: https://github.com/matanlurey/binary.dart/issues

## 4.0.0-alpha+1

**New features**:

- Added `BitList`, a compact `List<bool>` implementation that stores every
element as a single bit, with implementations that are fixed-size and
growable.

- Added `<FixedInt>.zero` and `<FixedInt>.one` as static constants.

- Added `collectBytes()`, a utility to convert a `Stream<List<int>>` into a
`Uint8List`.

**Breaking changes**:

- Replaced `<FixedInt>.bits` with `<FixedInt>.toBitList()`:

```diff
- final bits = Int8(0).bits;
+ final bits = Int8(0).toBitList();
```

## 4.0.0-alpha

**New features**:

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

**Breaking changes:**
**Breaking changes**:

_Basically everything_. The entire API has been restructured to use extension
types, and some APIs removed entirely that were either not well-thought out
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ integers.
[pub_img]: https://img.shields.io/pub/v/binary.svg
[gha_url]: https://github.com/matanlurey/binary.dart/actions
[gha_img]: https://github.com/matanlurey/binary.dart/actions/workflows/check.yaml/badge.svg
[cov_url]: https://codecov.io/gh/matanlurey/binary.dart
[cov_img]: https://codecov.io/gh/matanlurey/binary.dart/branch/main/graph/badge.svg
[cov_url]: https://coveralls.io/github/matanlurey/binary.dart?branch=main
[cov_img]: https://coveralls.io/repos/github/matanlurey/binary.dart/badge.svg?branch=main
[doc_url]: https://www.dartdocs.org/documentation/binary/latest
[doc_img]: https://img.shields.io/badge/Documentation-binary-blue.svg
[sty_url]: https://pub.dev/packages/oath
Expand Down
39 changes: 39 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Examples

This directory contains examples of how to use `package:binary`.

## [Basic](./basic.dart)

A simple example of how to use `package:binary` to parse and shift bits.

```shell
$ dart example/basic.dart

127
00000011
```

## [Checksum](./checksum.dart)

Calculates the CRC32 checksum of a file.

```shell
$ dart example/checksum.dart example/checksum.dart

CRC32 checksum: 13b53c2f
```

## [Bitfield](./bitfield.dart)

Demonstrates decoding binary data efficiently, i.e. opcodes or binary formats.

```shell
$ dart example/bitfield.dart

11011101

Kind: 00001101
S: 00000001
Level: 00000010
P: 00000001
```
File renamed without changes.
36 changes: 36 additions & 0 deletions example/bitfield.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:binary/binary.dart' show Uint8;

/// Let's assume we have the following format:
/// ```txt
/// 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
/// - | ----- | - | -------------
/// P | Level | S | Kind
/// ```
void main() {
// Create a bit field with the format.
final field = Uint8.zero
.replace(0, 3, int.parse('1101', radix: 2)) // Kind
.replace(4, 4, int.parse('1', radix: 2)) // S
.replace(5, 6, int.parse('10', radix: 2)) // Level
.replace(7, 7, int.parse('1', radix: 2)); // P

// P S
// vv v
print(field.toBinaryString()); // 11011101
// ^^ ^^^^
// Level Kind

// Now, read it back.
final (kind, s, level, p) = (
field.slice(0, 3),
field.slice(4, 4),
field.slice(5, 6),
field.slice(7, 7),
);

print('');
print('Kind: ${kind.toBinaryString()}');
print('S: ${s.toBinaryString()}');
print('Level: ${level.toBinaryString()}');
print('P: ${p.toBinaryString()}');
}
42 changes: 42 additions & 0 deletions example/checksum.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'dart:convert' show utf8;
import 'dart:typed_data';

import 'package:binary/binary.dart';

/// Examples of commom checksum algorithms using `package:binary`.
void main() {
// Calculate the CRC32 checksum of a list of bytes.
final data = Uint8List.fromList(utf8.encode('Hello, World!'));
final checksum = crc32(data);
print('CRC32 checksum: ${checksum.toRadixString(16)}');
}

/// Calculate the CRC32 checksum of a list of bytes using `CRC-32/JAMCRC`.
int crc32(Uint8List data, [Uint32 initialCrc = Uint32.max]) {
var crc = initialCrc;
for (final byte in data) {
final index = (crc.toInt() ^ byte) & 0xFF;
crc = (crc >> 8) ^ _crc32Table[index];
}
return crc.toInt();
}

final List<Uint32> _crc32Table = (() {
// We can freely cast a Uint32List to a List<Uint32> (zero-cost).
final table = Uint32List(256) as List<Uint32>;

// Precompute the CRC32 table.
for (var i = 0; i < 256; i++) {
// Cost-free conversion from int to Uint32.
var crc = Uint32.fromUnchecked(i);
for (var j = 0; j < 8; j++) {
if (crc.nthBit(0)) {
crc = (crc >> 1) ^ const Uint32.fromUnchecked(0xEDB88320);
} else {
crc >>= 1;
}
}
table[i] = crc;
}
return table;
})();
2 changes: 2 additions & 0 deletions lib/binary.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
/// [little endian]: https://en.wikipedia.org/wiki/Endianness
library;

export 'src/async.dart' show collectBytes;
export 'src/bit_list.dart';
export 'src/descriptor.dart';
export 'src/extension.dart';
export 'src/int16.dart';
Expand Down
25 changes: 25 additions & 0 deletions lib/src/async.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'dart:async';
import 'dart:typed_data';

/// Collects the bytes of a `Stream<List<int>>` into a [Uint8List].
///
/// This function returns a `Future<Uint8List>` that completes when the stream
/// is done, and a `Future<void> Function()` that can be used to cancel the
/// collection and underlying stream early.
(Future<Uint8List>, Future<void> Function() cancel) collectBytes(
Stream<List<int>> stream,
) {
final completer = Completer<Uint8List>.sync();
final builder = BytesBuilder(copy: false);
late final StreamSubscription<void> sub;
sub = stream.listen(
builder.add,
onDone: () async {
completer.complete(builder.toBytes());
await sub.cancel();
},
onError: completer.completeError,
cancelOnError: true,
);
return (completer.future, sub.cancel);
}
Loading