-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.dart
More file actions
107 lines (94 loc) · 2.98 KB
/
Copy pathmain.dart
File metadata and controls
107 lines (94 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import 'dart:io';
import 'dart:typed_data';
import 'package:pro_binary/pro_binary.dart';
void main() {
// 1. Basic Serialization
final user = User(
id: 101,
name: 'Dart 🚀',
isActive: true,
level: 5,
balance: -150, // Demonstrate signed VarInt (ZigZag)
score: 99.5,
avatar: Uint8List.fromList([0xDE, 0xAD, 0xBE, 0xEF]),
);
final writer = BinaryWriter();
user.encode(writer);
// takeBytes() returns Uint8List and resets writer for reuse
final bytes = writer.takeBytes();
_log('Serialization');
_log(' Encoded: ${bytes.length} bytes');
// 2. Basic Deserialization
final reader = BinaryReader(bytes);
final decodedUser = User.decode(reader);
_log('\nDeserialization -');
_log(' Decoded: $decodedUser');
_log(' Avatar: ${decodedUser.avatar}');
// 3. Pool API (Recommended for high-frequency operations)
// Reuses internal buffers to minimize Garbage Collection pressure.
_log('\nPool API');
final pooledBytes = BinaryWriterPool.withWriter((w) {
user.encode(w);
// safely copy data, keeping internal buffer pooled
return w.takeBytes(copy: true);
});
_log(' Pooled serialization done: ${pooledBytes.length} bytes');
// 4. Navigation & Peeking
_log('\nNavigation & Peeking');
final navReader = BinaryReader(pooledBytes);
// Support for index operator [] (peeking at specific position)
_log(' Peek byte at index 0: 0x${navReader[0].toRadixString(16)}');
navReader.skip(1); // Manually move cursor
_log(' Remaining bytes: ${navReader.availableBytes}');
}
/// A domain model demonstrating diverse data types and serialization patterns.
class User {
User({
required this.id,
required this.name,
required this.isActive,
required this.level,
required this.balance,
required this.score,
required this.avatar,
});
/// Pattern: Factory for deserialization.
factory User.decode(BinaryReader r) => User(
id: r.readVarUint(), // Compact variable-length unsigned int
name: r.readVarString(), // Length-prefixed UTF-8 string
isActive: r.readBool(), // 1 byte boolean
level: r.readUint8(), // Fixed-size 1 byte unsigned int
balance: r.readVarInt(), // Signed variable-length int (ZigZag)
score: r.readFloat64(), // 8 byte floating point
avatar: r.readVarBytes(), // Length-prefixed byte array
);
final int id;
final String name;
final bool isActive;
final int level;
final int balance;
final double score;
final Uint8List avatar;
/// Pattern: Instance method for serialization.
void encode(BinaryWriter w) {
w
..writeVarUint(id)
..writeVarString(name)
..writeBool(isActive)
..writeUint8(level)
..writeVarInt(balance)
..writeFloat64(score)
..writeVarBytes(avatar);
}
@override
String toString() =>
'User('
'id: $id, '
'name: "$name", '
'active: $isActive, '
'lvl: $level, '
'bal: $balance, '
'score: $score'
')';
}
void _log([Object? object = '']) => stdout.writeln(object);