Skip to content
Open
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
14 changes: 11 additions & 3 deletions lib/src/unpacker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,11 @@ class Unpacker {
return len;
}

/// Unpack value if packed value is binary or `null`.
/// Unpack value as Uint8List if packed value is binary or `null`.
///
/// Encoded in msgpack packet null unpacks to [List] with 0 length for convenience.
/// Throws [FormatException] if value is not a binary.
List<int> unpackBinary() {
Uint8List unpackBinaryUint8() {
final b = _d.getUint8(_offset);
int len;
if (b == 0xc4) {
Expand All @@ -222,7 +222,15 @@ class Unpacker {
final data =
Uint8List.view(_list.buffer, _list.offsetInBytes + _offset, len);
_offset += len;
return data.toList();
return data;
}

/// Unpack value if packed value is binary or `null`.
///
/// Encoded in msgpack packet null unpacks to [List] with 0 length for convenience.
/// Throws [FormatException] if value is not a binary.
List<int> unpackBinary() {
return unpackBinaryUint8().toList();
}

Object? _unpack() {
Expand Down
87 changes: 86 additions & 1 deletion test/messagepack_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';

import 'package:messagepack/messagepack.dart';
import 'package:test/test.dart';
Expand Down Expand Up @@ -72,6 +73,64 @@ final strs = [
'hi'
];

/// Example recursive datastruct and one way to pack/unpack.
class MyData {
MyData(this.data) : children = {};
MyData._new(this.data, this.children);

static MyData unpack(Uint8List bytes) {
final u = Unpacker(bytes);
return _unpack(u);
}

static MyData _unpack(Unpacker u) {
final data = u.unpackInt()!;
final children = <int, MyData>{};
final mapLength = u.unpackMapLength();
for (var i = 0; i < mapLength; ++i) {
final key = u.unpackInt();
if (key != null) {
children[key] = _unpack(u);
}
}
return MyData._new(data, children);
}

Uint8List pack() {
final p = Packer();
_pack(p);
return p.takeBytes();
}

void _pack(Packer p) {
p.packInt(data);
p.packMapLength(children.length);
for (final MapEntry<int, MyData> entry in children.entries) {
p.packInt(entry.key);
entry.value._pack(p);
}
}

void add(int key, MyData child) => children[key] = child;
@override
bool operator ==(Object other) {
if (!(other is MyData) ||
other.runtimeType != runtimeType ||
other.data != data ||
other.children.length != children.length) return false;
for (final item in children.entries) {
if (other.children[item.key] != item.value) return false;
}
return true;
}

@override
int get hashCode => Object.hash(data, children);

int data;
Map<int, MyData> children;
}

void main() {
test('int sequentially increasing [independent]', () {
for (int v = -65536; v < 65536; v++) {
Expand Down Expand Up @@ -329,13 +388,21 @@ void main() {
p.packBool(true);
p.packBinary(bytes2);
p.packInt(3);
final u = Unpacker(p.takeBytes());
final packedBytes = p.takeBytes();
final u = Unpacker(packedBytes);
expect(u.unpackBinary(), equals(empty));
expect(u.unpackBinary(), equals(empty));
expect(u.unpackBinary(), equals(bytes1));
expect(u.unpackBool(), equals(true));
expect(u.unpackBinary(), equals(bytes2));
expect(u.unpackInt(), equals(3));
final u2 = Unpacker(packedBytes);
expect(u2.unpackBinaryUint8(), equals(empty));
expect(u2.unpackBinaryUint8(), equals(empty));
expect(u2.unpackBinaryUint8(), equals(bytes1));
expect(u2.unpackBool(), equals(true));
expect(u2.unpackBinaryUint8(), equals(bytes2));
expect(u2.unpackInt(), equals(3));
});

test('Manual int example [dependent]', () {
Expand Down Expand Up @@ -413,4 +480,22 @@ void main() {
final l = u.unpackList();
print(l);
});

test('Recursive strutures', () {
final myData = MyData(0);
myData.add(11, MyData(1));
myData.add(12, MyData(2)..add(33, MyData(4)));
myData.add(13, MyData(3));
final bytes = myData.pack();
print('encoded length: ${bytes.lengthInBytes}');

final unpackedData = MyData.unpack(bytes);
expect(myData.data, unpackedData.data);
final otherChildren = unpackedData.children;
expect(otherChildren, containsPair(11, MyData(1)));
expect(otherChildren, containsPair(12, MyData(2)..add(33, MyData(4))));
expect(otherChildren, containsPair(13, MyData(3)));
expect(myData.children.length, otherChildren.length);
expect(myData, equals(unpackedData));
});
}