From c7c49d1054a9c83af24462c24a8776fc1e019d57 Mon Sep 17 00:00:00 2001 From: Linus Wong Date: Thu, 21 Apr 2022 14:12:30 +0800 Subject: [PATCH 1/2] add a recursive class test example --- test/messagepack_test.dart | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/test/messagepack_test.dart b/test/messagepack_test.dart index 3ab41dd..a19c4bd 100644 --- a/test/messagepack_test.dart +++ b/test/messagepack_test.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:math'; +import 'dart:typed_data'; import 'package:messagepack/messagepack.dart'; import 'package:test/test.dart'; @@ -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 = {}; + 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 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.data == data && + other.children.length == children.length)) return false; + for (final item in children.entries) { + if (!other.children.containsKey(item.key) || + other.children[item.key] != item.value) return false; + } + return true; + } + + @override + int get hashCode => Object.hash(data, children); + + late int data; + late Map children; +} + void main() { test('int sequentially increasing [independent]', () { for (int v = -65536; v < 65536; v++) { @@ -413,4 +472,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)); + }); } From c9ee08032c58da3a82734da16d06b66e4eddca2e Mon Sep 17 00:00:00 2001 From: Linus Wong Date: Thu, 21 Apr 2022 15:28:02 +0800 Subject: [PATCH 2/2] add method to unpack binary data as uint8 --- lib/src/unpacker.dart | 14 +++++++++++--- test/messagepack_test.dart | 24 ++++++++++++++++-------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/src/unpacker.dart b/lib/src/unpacker.dart index cd734c2..f2e2cb8 100644 --- a/lib/src/unpacker.dart +++ b/lib/src/unpacker.dart @@ -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 unpackBinary() { + Uint8List unpackBinaryUint8() { final b = _d.getUint8(_offset); int len; if (b == 0xc4) { @@ -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 unpackBinary() { + return unpackBinaryUint8().toList(); } Object? _unpack() { diff --git a/test/messagepack_test.dart b/test/messagepack_test.dart index a19c4bd..6980210 100644 --- a/test/messagepack_test.dart +++ b/test/messagepack_test.dart @@ -114,12 +114,12 @@ class MyData { void add(int key, MyData child) => children[key] = child; @override bool operator ==(Object other) { - if (!(other is MyData && - other.data == data && - other.children.length == children.length)) return false; + 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.containsKey(item.key) || - other.children[item.key] != item.value) return false; + if (other.children[item.key] != item.value) return false; } return true; } @@ -127,8 +127,8 @@ class MyData { @override int get hashCode => Object.hash(data, children); - late int data; - late Map children; + int data; + Map children; } void main() { @@ -388,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]', () {