| // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:convert'; | |
| import 'dart:typed_data'; | |
| class Deserializer { | |
| final Uint8List _data; | |
| int offset = 0; | |
| Deserializer(this._data); | |
| int get length => _data.length; | |
| bool get isAtEnd => offset >= _data.length; | |
| int readByte() { | |
| return _data[offset++]; | |
| } | |
| int peekByte() { | |
| return _data[offset]; | |
| } | |
| Uint8List readBytes(int length) { | |
| final bytes = Uint8List.sublistView(_data, offset, offset + length); | |
| offset += length; | |
| return bytes; | |
| } | |
| int readSigned() { | |
| int result = 0; | |
| int shift = 0; | |
| int byte; | |
| do { | |
| byte = readByte(); | |
| result |= (byte & 0x7F) << shift; | |
| shift += 7; | |
| } while ((byte & 0x80) != 0); | |
| if ((shift < 64) && ((byte & 0x40) != 0)) { | |
| result |= ~0 << shift; | |
| } | |
| return result; | |
| } | |
| int readUnsigned() { | |
| int result = 0; | |
| int shift = 0; | |
| int byte; | |
| do { | |
| byte = readByte(); | |
| result |= (byte & 0x7F) << shift; | |
| shift += 7; | |
| } while ((byte & 0x80) != 0); | |
| return result; | |
| } | |
| double readF32() { | |
| final bd = ByteData.sublistView(_data, offset, offset + 4); | |
| offset += 4; | |
| return bd.getFloat32(0, Endian.little); | |
| } | |
| double readF64() { | |
| final bd = ByteData.sublistView(_data, offset, offset + 8); | |
| offset += 8; | |
| return bd.getFloat64(0, Endian.little); | |
| } | |
| String readName() { | |
| final length = readUnsigned(); | |
| return utf8.decode(readBytes(length)); | |
| } | |
| List<T> readList<T>(T Function(Deserializer) fun) { | |
| final length = readUnsigned(); | |
| final list = <T>[]; | |
| for (int i = 0; i < length; i++) { | |
| list.add(fun(this)); | |
| } | |
| return list; | |
| } | |
| } |