diff options
Diffstat (limited to 'dart/lib/src/reference.dart')
-rw-r--r-- | dart/lib/src/reference.dart | 228 |
1 files changed, 132 insertions, 96 deletions
diff --git a/dart/lib/src/reference.dart b/dart/lib/src/reference.dart index 3954f068..c2956e30 100644 --- a/dart/lib/src/reference.dart +++ b/dart/lib/src/reference.dart @@ -11,14 +11,15 @@ class Reference { final int _offset; final BitWidth _parentWidth; final String _path; - int _byteWidth; - ValueType _valueType; - int _length; + final int _byteWidth; + final ValueType _valueType; + int? _length; - Reference._(this._buffer, this._offset, this._parentWidth, int packedType, this._path) { - _byteWidth = 1 << (packedType & 3); - _valueType = ValueTypeUtils.fromInt(packedType >> 2); - } + Reference._( + this._buffer, this._offset, this._parentWidth, int packedType, this._path, + [int? byteWidth, ValueType? valueType]) + : _byteWidth = byteWidth ?? 1 << (packedType & 3), + _valueType = valueType ?? ValueTypeUtils.fromInt(packedType >> 2) {} /// Use this method to access the root value of a FlexBuffer. static Reference fromBuffer(ByteBuffer buffer) { @@ -30,31 +31,44 @@ class Reference { final byteWidth = byteData.getUint8(len - 1); final packedType = byteData.getUint8(len - 2); final offset = len - byteWidth - 2; - return Reference._(ByteData.view(buffer), offset, BitWidthUtil.fromByteWidth(byteWidth), packedType, "/"); + return Reference._(ByteData.view(buffer), offset, + BitWidthUtil.fromByteWidth(byteWidth), packedType, "/"); } /// Returns true if the underlying value is null. bool get isNull => _valueType == ValueType.Null; + /// Returns true if the underlying value can be represented as [num]. - bool get isNum => ValueTypeUtils.isNumber(_valueType) || ValueTypeUtils.isIndirectNumber(_valueType); + bool get isNum => + ValueTypeUtils.isNumber(_valueType) || + ValueTypeUtils.isIndirectNumber(_valueType); + /// Returns true if the underlying value was encoded as a float (direct or indirect). - bool get isDouble => _valueType == ValueType.Float || _valueType == ValueType.IndirectFloat; + bool get isDouble => + _valueType == ValueType.Float || _valueType == ValueType.IndirectFloat; + /// Returns true if the underlying value was encoded as an int or uint (direct or indirect). bool get isInt => isNum && !isDouble; + /// Returns true if the underlying value was encoded as a string or a key. - bool get isString => _valueType == ValueType.String || _valueType == ValueType.Key; + bool get isString => + _valueType == ValueType.String || _valueType == ValueType.Key; + /// Returns true if the underlying value was encoded as a bool. bool get isBool => _valueType == ValueType.Bool; + /// Returns true if the underlying value was encoded as a blob. bool get isBlob => _valueType == ValueType.Blob; + /// Returns true if the underlying value points to a vector. bool get isVector => ValueTypeUtils.isAVector(_valueType); + /// Returns true if the underlying value points to a map. bool get isMap => _valueType == ValueType.Map; /// If this [isBool], returns the bool value. Otherwise, returns null. - bool get boolValue { - if(_valueType == ValueType.Bool) { + bool? get boolValue { + if (_valueType == ValueType.Bool) { return _readInt(_offset, _parentWidth) != 0; } return null; @@ -63,7 +77,7 @@ class Reference { /// Returns an [int], if the underlying value can be represented as an int. /// /// Otherwise returns [null]. - int get intValue { + int? get intValue { if (_valueType == ValueType.Int) { return _readInt(_offset, _parentWidth); } @@ -82,7 +96,7 @@ class Reference { /// Returns [double], if the underlying value [isDouble]. /// /// Otherwise returns [null]. - double get doubleValue { + double? get doubleValue { if (_valueType == ValueType.Float) { return _readFloat(_offset, _parentWidth); } @@ -95,12 +109,12 @@ class Reference { /// Returns [num], if the underlying value is numeric, be it int uint, or float (direct or indirect). /// /// Otherwise returns [null]. - num get numValue => doubleValue ?? intValue; + num? get numValue => doubleValue ?? intValue; /// Returns [String] value or null otherwise. - /// - /// This method performers a utf8 decoding, as FlexBuffers format stores strings in utf8 encoding. - String get stringValue { + /// + /// This method performers a utf8 decoding, as FlexBuffers format stores strings in utf8 encoding. + String? get stringValue { if (_valueType == ValueType.String || _valueType == ValueType.Key) { return utf8.decode(_buffer.buffer.asUint8List(_indirect, length)); } @@ -108,7 +122,7 @@ class Reference { } /// Returns [Uint8List] value or null otherwise. - Uint8List get blobValue { + Uint8List? get blobValue { if (_valueType == ValueType.Blob) { return _buffer.buffer.asUint8List(_indirect, length); } @@ -122,22 +136,31 @@ class Reference { Reference operator [](Object key) { if (key is int && ValueTypeUtils.isAVector(_valueType)) { final index = key; - if(index >= length || index < 0) { - throw ArgumentError('Key: [$key] is not applicable on: $_path of: $_valueType length: $length'); + if (index >= length || index < 0) { + throw ArgumentError( + 'Key: [$key] is not applicable on: $_path of: $_valueType length: $length'); } final elementOffset = _indirect + index * _byteWidth; - final reference = Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), 0, "$_path[$index]"); - reference._byteWidth = 1; + int packedType = 0; + int? byteWidth; + ValueType? valueType; if (ValueTypeUtils.isTypedVector(_valueType)) { - reference._valueType = ValueTypeUtils.typedVectorElementType(_valueType); - return reference; - } - if(ValueTypeUtils.isFixedTypedVector(_valueType)) { - reference._valueType = ValueTypeUtils.fixedTypedVectorElementType(_valueType); - return reference; + byteWidth = 1; + valueType = ValueTypeUtils.typedVectorElementType(_valueType); + } else if (ValueTypeUtils.isFixedTypedVector(_valueType)) { + byteWidth = 1; + valueType = ValueTypeUtils.fixedTypedVectorElementType(_valueType); + } else { + packedType = _buffer.getUint8(_indirect + length * _byteWidth + index); } - final packedType = _buffer.getUint8(_indirect + length * _byteWidth + index); - return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path[$index]"); + return Reference._( + _buffer, + elementOffset, + BitWidthUtil.fromByteWidth(_byteWidth), + packedType, + "$_path[$index]", + byteWidth, + valueType); } if (key is String && _valueType == ValueType.Map) { final index = _keyIndex(key); @@ -145,13 +168,14 @@ class Reference { return _valueForIndexWithKey(index, key); } } - throw ArgumentError('Key: [$key] is not applicable on: $_path of: $_valueType'); + throw ArgumentError( + 'Key: [$key] is not applicable on: $_path of: $_valueType'); } /// Get an iterable if the underlying flexBuffer value is a vector. /// Otherwise throws an exception. Iterable<Reference> get vectorIterable { - if(isVector == false) { + if (isVector == false) { throw UnsupportedError('Value is not a vector. It is: $_valueType'); } return _VectorIterator(this); @@ -160,7 +184,7 @@ class Reference { /// Get an iterable for keys if the underlying flexBuffer value is a map. /// Otherwise throws an exception. Iterable<String> get mapKeyIterable { - if(isMap == false) { + if (isMap == false) { throw UnsupportedError('Value is not a map. It is: $_valueType'); } return _MapKeyIterator(this); @@ -169,7 +193,7 @@ class Reference { /// Get an iterable for values if the underlying flexBuffer value is a map. /// Otherwise throws an exception. Iterable<Reference> get mapValueIterable { - if(isMap == false) { + if (isMap == false) { throw UnsupportedError('Value is not a map. It is: $_valueType'); } return _MapValueIterator(this); @@ -181,59 +205,62 @@ class Reference { /// If the underlying value is a vector, or map, the length reflects number of elements / element pairs. /// If the values is a string or a blob, the length reflects a number of bytes the value occupies (strings are encoded in utf8 format). int get length { - if (_length != null) { - return _length; - } - // needs to be checked before more generic isAVector - if(ValueTypeUtils.isFixedTypedVector(_valueType)) { - _length = ValueTypeUtils.fixedTypedVectorElementSize(_valueType); - } else if(_valueType == ValueType.Blob || ValueTypeUtils.isAVector(_valueType) || _valueType == ValueType.Map){ - _length = _readUInt(_indirect - _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth)); - } else if (_valueType == ValueType.Null) { - _length = 0; - } else if (_valueType == ValueType.String) { - final indirect = _indirect; - var size_byte_width = _byteWidth; - var size = _readUInt(indirect - size_byte_width, BitWidthUtil.fromByteWidth(size_byte_width)); - while (_buffer.getInt8(indirect + size) != 0) { - size_byte_width <<= 1; - size = _readUInt(indirect - size_byte_width, BitWidthUtil.fromByteWidth(size_byte_width)); - } - _length = size; - } else if (_valueType == ValueType.Key) { - final indirect = _indirect; - var size = 1; - while (_buffer.getInt8(indirect + size) != 0) { - size += 1; + if (_length == null) { + // needs to be checked before more generic isAVector + if (ValueTypeUtils.isFixedTypedVector(_valueType)) { + _length = ValueTypeUtils.fixedTypedVectorElementSize(_valueType); + } else if (_valueType == ValueType.Blob || + ValueTypeUtils.isAVector(_valueType) || + _valueType == ValueType.Map) { + _length = _readUInt( + _indirect - _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth)); + } else if (_valueType == ValueType.Null) { + _length = 0; + } else if (_valueType == ValueType.String) { + final indirect = _indirect; + var size_byte_width = _byteWidth; + var size = _readUInt(indirect - size_byte_width, + BitWidthUtil.fromByteWidth(size_byte_width)); + while (_buffer.getInt8(indirect + size) != 0) { + size_byte_width <<= 1; + size = _readUInt(indirect - size_byte_width, + BitWidthUtil.fromByteWidth(size_byte_width)); + } + _length = size; + } else if (_valueType == ValueType.Key) { + final indirect = _indirect; + var size = 1; + while (_buffer.getInt8(indirect + size) != 0) { + size += 1; + } + _length = size; + } else { + _length = 1; } - _length = size; - } else { - _length = 1; } - return _length; + return _length!; } - /// Returns a minified JSON representation of the underlying FlexBuffer value. /// /// This method involves materializing the entire object tree, which may be /// expensive. It is more efficient to work with [Reference] and access only the needed data. /// Blob values are represented as base64 encoded string. String get json { - if(_valueType == ValueType.Bool) { - return boolValue ? 'true' : 'false'; + if (_valueType == ValueType.Bool) { + return boolValue! ? 'true' : 'false'; } if (_valueType == ValueType.Null) { return 'null'; } - if(ValueTypeUtils.isNumber(_valueType)) { + if (ValueTypeUtils.isNumber(_valueType)) { return jsonEncode(numValue); } if (_valueType == ValueType.String) { return jsonEncode(stringValue); } if (_valueType == ValueType.Blob) { - return jsonEncode(base64Encode(blobValue)); + return jsonEncode(base64Encode(blobValue!)); } if (ValueTypeUtils.isAVector(_valueType)) { final result = StringBuffer(); @@ -261,7 +288,8 @@ class Reference { result.write('}'); return result.toString(); } - throw UnsupportedError('Type: $_valueType is not supported for JSON conversion'); + throw UnsupportedError( + 'Type: $_valueType is not supported for JSON conversion'); } /// Computes the indirect offset of the value. @@ -316,16 +344,20 @@ class Reference { } void _validateOffset(int offset, BitWidth width) { - if (_offset < 0 || _buffer.lengthInBytes <= offset + width.index || offset & (BitWidthUtil.toByteWidth(width) - 1) != 0) { + if (_offset < 0 || + _buffer.lengthInBytes <= offset + width.index || + offset & (BitWidthUtil.toByteWidth(width) - 1) != 0) { throw StateError('Bad offset: $offset, width: $width'); } } - int _keyIndex(String key) { + int? _keyIndex(String key) { final input = utf8.encode(key); final keysVectorOffset = _indirect - _byteWidth * 3; - final indirectOffset = keysVectorOffset - _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth)); - final byteWidth = _readUInt(keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth)); + final indirectOffset = keysVectorOffset - + _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth)); + final byteWidth = _readUInt( + keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth)); var low = 0; var high = length - 1; while (low <= high) { @@ -341,9 +373,11 @@ class Reference { return null; } - int _diffKeys(List<int> input, int index, int indirect_offset, int byteWidth) { + int _diffKeys( + List<int> input, int index, int indirect_offset, int byteWidth) { final keyOffset = indirect_offset + index * byteWidth; - final keyIndirectOffset = keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth)); + final keyIndirectOffset = + keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth)); for (var i = 0; i < input.length; i++) { final dif = input[i] - _buffer.getUint8(keyIndirectOffset + i); if (dif != 0) { @@ -357,38 +391,42 @@ class Reference { final indirect = _indirect; final elementOffset = indirect + index * _byteWidth; final packedType = _buffer.getUint8(indirect + length * _byteWidth + index); - return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/$key"); + return Reference._(_buffer, elementOffset, + BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/$key"); } Reference _valueForIndex(int index) { final indirect = _indirect; final elementOffset = indirect + index * _byteWidth; final packedType = _buffer.getUint8(indirect + length * _byteWidth + index); - return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/[$index]"); + return Reference._(_buffer, elementOffset, + BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/[$index]"); } String _keyForIndex(int index) { final keysVectorOffset = _indirect - _byteWidth * 3; - final indirectOffset = keysVectorOffset - _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth)); - final byteWidth = _readUInt(keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth)); + final indirectOffset = keysVectorOffset - + _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth)); + final byteWidth = _readUInt( + keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth)); final keyOffset = indirectOffset + index * byteWidth; - final keyIndirectOffset = keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth)); + final keyIndirectOffset = + keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth)); var length = 0; while (_buffer.getUint8(keyIndirectOffset + length) != 0) { length += 1; } return utf8.decode(_buffer.buffer.asUint8List(keyIndirectOffset, length)); } - } -class _VectorIterator with IterableMixin<Reference> implements Iterator<Reference> { +class _VectorIterator + with IterableMixin<Reference> + implements Iterator<Reference> { final Reference _vector; - int index; + int index = -1; - _VectorIterator(this._vector) { - index = -1; - } + _VectorIterator(this._vector); @override Reference get current => _vector[index]; @@ -405,11 +443,9 @@ class _VectorIterator with IterableMixin<Reference> implements Iterator<Referenc class _MapKeyIterator with IterableMixin<String> implements Iterator<String> { final Reference _map; - int index; + int index = -1; - _MapKeyIterator(this._map) { - index = -1; - } + _MapKeyIterator(this._map); @override String get current => _map._keyForIndex(index); @@ -424,13 +460,13 @@ class _MapKeyIterator with IterableMixin<String> implements Iterator<String> { Iterator<String> get iterator => this; } -class _MapValueIterator with IterableMixin<Reference> implements Iterator<Reference> { +class _MapValueIterator + with IterableMixin<Reference> + implements Iterator<Reference> { final Reference _map; - int index; + int index = -1; - _MapValueIterator(this._map) { - index = -1; - } + _MapValueIterator(this._map); @override Reference get current => _map._valueForIndex(index); |