| // Copyright 2018 The Fuchsia Authors. 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:typed_data'; |
| |
| import 'package:zircon/zircon.dart'; |
| |
| import 'error.dart'; |
| import 'message.dart'; |
| |
| // ignore_for_file: always_specify_types |
| // ignore_for_file: avoid_positional_boolean_parameters |
| // ignore_for_file: public_member_api_docs |
| |
| const int _kAlignment = 8; |
| const int _kAlignmentMask = 0x7; |
| |
| int _align(int size) => |
| size + ((_kAlignment - (size & _kAlignmentMask)) & _kAlignmentMask); |
| |
| void _throwIfNegative(int value) { |
| if (value < 0) { |
| throw new FidlError( |
| 'Cannot encode a negative value for an unsigned type: $value'); |
| } |
| } |
| |
| const int _kInitialBufferSize = 1024; |
| |
| class Encoder { |
| Message get message { |
| final ByteData trimmed = new ByteData.view(data.buffer, 0, _extent); |
| return new Message(trimmed, _handles, _extent, _handles.length); |
| } |
| |
| ByteData data = new ByteData(_kInitialBufferSize); |
| final List<Handle> _handles = <Handle>[]; |
| int _extent = 0; |
| |
| void _grow(int newSize) { |
| final Uint8List newList = new Uint8List(newSize) |
| ..setRange(0, data.lengthInBytes, data.buffer.asUint8List()); |
| data = newList.buffer.asByteData(); |
| } |
| |
| void _claimMemory(int claimSize) { |
| _extent += claimSize; |
| if (_extent > data.lengthInBytes) { |
| int newSize = data.lengthInBytes + claimSize; |
| newSize += newSize >> 1; |
| _grow(newSize); |
| } |
| } |
| |
| int alloc(int size) { |
| int offset = _extent; |
| _claimMemory(_align(size)); |
| return offset; |
| } |
| |
| int nextOffset() { |
| return _extent; |
| } |
| |
| int countHandles() { |
| return _handles.length; |
| } |
| |
| void addHandle(Handle value) { |
| _handles.add(value); |
| } |
| |
| void encodeMessageHeader(int ordinal, int txid) { |
| alloc(kMessageHeaderSize); |
| encodeUint32(ordinal, kMessageOrdinalOffset); |
| encodeUint32(txid, kMessageTxidOffset); |
| } |
| |
| void encodeBool(bool value, int offset) { |
| data.setInt8(offset, value ? 1 : 0); |
| } |
| |
| void encodeInt8(int value, int offset) { |
| data.setInt8(offset, value); |
| } |
| |
| void encodeUint8(int value, int offset) { |
| _throwIfNegative(value); |
| data.setUint8(offset, value); |
| } |
| |
| void encodeInt16(int value, int offset) { |
| data.setInt16(offset, value, Endian.little); |
| } |
| |
| void encodeUint16(int value, int offset) { |
| _throwIfNegative(value); |
| data.setUint16(offset, value, Endian.little); |
| } |
| |
| void encodeInt32(int value, int offset) { |
| data.setInt32(offset, value, Endian.little); |
| } |
| |
| void encodeUint32(int value, int offset) { |
| _throwIfNegative(value); |
| data.setUint32(offset, value, Endian.little); |
| } |
| |
| void encodeInt64(int value, int offset) { |
| data.setInt64(offset, value, Endian.little); |
| } |
| |
| void encodeUint64(int value, int offset) { |
| data.setUint64(offset, value, Endian.little); |
| } |
| |
| void encodeFloat32(double value, int offset) { |
| data.setFloat32(offset, value, Endian.little); |
| } |
| |
| void encodeFloat64(double value, int offset) { |
| data.setFloat64(offset, value, Endian.little); |
| } |
| } |
| |
| class Decoder { |
| Decoder(Message message) |
| : _message = message, |
| data = message.data; |
| |
| Message _message; |
| ByteData data; |
| |
| int _nextOffset = 0; |
| int _nextHandle = 0; |
| |
| int nextOffset() { |
| return _nextOffset; |
| } |
| |
| int claimMemory(int size) { |
| final int result = _nextOffset; |
| _nextOffset += _align(size); |
| if (_nextOffset > _message.dataLength) { |
| throw new FidlError('Cannot access out of range memory'); |
| } |
| return result; |
| } |
| |
| int countClaimedHandles() { |
| return _nextHandle; |
| } |
| |
| Handle claimHandle() { |
| if (_nextHandle >= _message.handlesLength) { |
| throw new FidlError('Cannot access out of range handle'); |
| } |
| return _message.handles[_nextHandle++]; |
| } |
| |
| bool decodeBool(int offset) => data.getInt8(offset) != 0; |
| |
| int decodeInt8(int offset) => data.getInt8(offset); |
| |
| int decodeUint8(int offset) => data.getUint8(offset); |
| |
| int decodeInt16(int offset) => data.getInt16(offset, Endian.little); |
| |
| int decodeUint16(int offset) => data.getUint16(offset, Endian.little); |
| |
| int decodeInt32(int offset) => data.getInt32(offset, Endian.little); |
| |
| int decodeUint32(int offset) => data.getUint32(offset, Endian.little); |
| |
| int decodeInt64(int offset) => data.getInt64(offset, Endian.little); |
| |
| int decodeUint64(int offset) => data.getUint64(offset, Endian.little); |
| |
| double decodeFloat32(int offset) => data.getFloat32(offset, Endian.little); |
| |
| double decodeFloat64(int offset) => data.getFloat64(offset, Endian.little); |
| } |