diff --git a/protobuf/CHANGELOG.md b/protobuf/CHANGELOG.md index 1ec9d5f5..9d10a960 100644 --- a/protobuf/CHANGELOG.md +++ b/protobuf/CHANGELOG.md @@ -1,3 +1,12 @@ +## 4.2.0-wip + +* Internal refactoring to split the package into libraries. This allows + conditionally importing different libraries and improving performance by + using different encoding/decoding libraries based on the target platform. + ([#1026]) + +[#1026]: https://github.com/google/protobuf.dart/pull/1026 + ## 4.1.1 * Minimum SDK dependency bumped from 3.6.0 to 3.7.0. ([#1024]) diff --git a/protobuf/lib/protobuf.dart b/protobuf/lib/protobuf.dart index b500e512..2c6ef839 100644 --- a/protobuf/lib/protobuf.dart +++ b/protobuf/lib/protobuf.dart @@ -7,61 +7,13 @@ /// [1]: https://developers.google.com/protocol-buffers library; -import 'dart:collection' show ListBase, MapBase; -import 'dart:convert' - show - Utf8Decoder, - Utf8Encoder, - base64Decode, - base64Encode, - jsonDecode, - jsonEncode; -import 'dart:math' as math; -import 'dart:typed_data' show ByteData, Endian, Uint8List; - -import 'package:fixnum/fixnum.dart' show Int64; -import 'package:meta/meta.dart' show UseResult; - -import 'src/protobuf/json_parsing_context.dart'; -import 'src/protobuf/permissive_compare.dart'; -import 'src/protobuf/type_registry.dart'; - -export 'src/protobuf/type_registry.dart' show TypeRegistry; - -part 'src/protobuf/annotations.dart'; -part 'src/protobuf/builder_info.dart'; -part 'src/protobuf/coded_buffer.dart'; -part 'src/protobuf/coded_buffer_reader.dart'; -part 'src/protobuf/coded_buffer_writer.dart'; -part 'src/protobuf/consts.dart'; -part 'src/protobuf/exceptions.dart'; -part 'src/protobuf/extension.dart'; -part 'src/protobuf/extension_field_set.dart'; -part 'src/protobuf/extension_registry.dart'; -part 'src/protobuf/field_error.dart'; -part 'src/protobuf/field_info.dart'; -part 'src/protobuf/field_set.dart'; -part 'src/protobuf/field_type.dart'; -part 'src/protobuf/generated_message.dart'; -part 'src/protobuf/generated_service.dart'; -part 'src/protobuf/json.dart'; -part 'src/protobuf/message_set.dart'; -part 'src/protobuf/pb_list.dart'; -part 'src/protobuf/pb_map.dart'; -part 'src/protobuf/proto3_json.dart'; -part 'src/protobuf/protobuf_enum.dart'; -part 'src/protobuf/rpc_client.dart'; -part 'src/protobuf/unknown_field_set.dart'; -part 'src/protobuf/unpack.dart'; -part 'src/protobuf/utils.dart'; -part 'src/protobuf/wire_format.dart'; - -// TODO(sra): Use `Int64.parse()` when available: -// https://github.com/dart-lang/fixnum/issues/18. -/// @nodoc -Int64 parseLongInt(String text) { - if (text.startsWith('0x')) return Int64.parseHex(text.substring(2)); - if (text.startsWith('+0x')) return Int64.parseHex(text.substring(3)); - if (text.startsWith('-0x')) return -Int64.parseHex(text.substring(3)); - return Int64.parseInt(text); -} +export 'src/protobuf/internal.dart' + hide + BuilderInfoInternalExtension, + ExtensionFieldSet, + ExtensionFieldSetInternalExtension, + FieldInfoInternalExtension, + FieldSet, + FieldSetInternalExtension, + GeneratedMessageInternalExtension, + MapFieldInfoInternalExtension; diff --git a/protobuf/lib/src/protobuf/annotations.dart b/protobuf/lib/src/protobuf/annotations.dart index 9ec997b6..fa274538 100644 --- a/protobuf/lib/src/protobuf/annotations.dart +++ b/protobuf/lib/src/protobuf/annotations.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Annotation for marking accessors that belong together. class TagNumber { diff --git a/protobuf/lib/src/protobuf/builder_info.dart b/protobuf/lib/src/protobuf/builder_info.dart index 4ac8bc06..24af8110 100644 --- a/protobuf/lib/src/protobuf/builder_info.dart +++ b/protobuf/lib/src/protobuf/builder_info.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Per-message type setup. class BuilderInfo { @@ -28,7 +28,7 @@ class BuilderInfo { final Map byName = {}; /// Mapping from `oneof` field [FieldInfo.tagNumber]s to the their indices in - /// [_FieldSet._oneofCases]. + /// [FieldSet._oneofCases]. final Map oneofs = {}; /// Whether the message has extension fields. @@ -487,3 +487,16 @@ class BuilderInfo { ?.call(rawValue); } } + +extension BuilderInfoInternalExtension on BuilderInfo { + GeneratedMessage makeEmptyMessage( + int tagNumber, + ExtensionRegistry? extensionRegistry, + ) => _makeEmptyMessage(tagNumber, extensionRegistry); + + ProtobufEnum? decodeEnum( + int tagNumber, + ExtensionRegistry? registry, + int rawValue, + ) => _decodeEnum(tagNumber, registry, rawValue); +} diff --git a/protobuf/lib/src/protobuf/coded_buffer.dart b/protobuf/lib/src/protobuf/coded_buffer.dart index 4166228c..92102654 100644 --- a/protobuf/lib/src/protobuf/coded_buffer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer.dart @@ -2,9 +2,9 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; -void _writeToCodedBufferWriter(_FieldSet fs, CodedBufferWriter out) { +void _writeToCodedBufferWriter(FieldSet fs, CodedBufferWriter out) { // Sorting by tag number isn't required, but it sometimes enables // performance optimizations for the receiver. See: // https://developers.google.com/protocol-buffers/docs/encoding?hl=en#order @@ -17,7 +17,7 @@ void _writeToCodedBufferWriter(_FieldSet fs, CodedBufferWriter out) { final extensions = fs._extensions; if (extensions != null) { - for (final tagNumber in _sorted(extensions._tagNumbers)) { + for (final tagNumber in sorted(extensions._tagNumbers)) { final fi = extensions._getInfoOrNull(tagNumber)!; out.writeField(tagNumber, fi.type, extensions._getFieldOrNull(fi)); } @@ -31,7 +31,7 @@ void _writeToCodedBufferWriter(_FieldSet fs, CodedBufferWriter out) { void _mergeFromCodedBufferReader( BuilderInfo meta, - _FieldSet fs, + FieldSet fs, CodedBufferReader input, ExtensionRegistry registry, ) { @@ -404,7 +404,7 @@ void _mergeFromCodedBufferReader( void _readPackableToListEnum( List list, BuilderInfo meta, - _FieldSet fs, + FieldSet fs, CodedBufferReader input, int wireType, int tagNumber, @@ -426,7 +426,7 @@ void _readPackableToListEnum( void _readRepeatedEnum( List list, BuilderInfo meta, - _FieldSet fs, + FieldSet fs, CodedBufferReader input, int tagNumber, ExtensionRegistry registry, diff --git a/protobuf/lib/src/protobuf/coded_buffer_reader.dart b/protobuf/lib/src/protobuf/coded_buffer_reader.dart index 2bb9c2ec..bb1f5855 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_reader.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_reader.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Reader used for converting binary-encoded protobufs into /// [GeneratedMessage]s. diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index a8dffd80..312e8fdd 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart @@ -4,7 +4,7 @@ // ignore_for_file: constant_identifier_names -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Writer used for converting [GeneratedMessage]s into binary /// representation. diff --git a/protobuf/lib/src/protobuf/consts.dart b/protobuf/lib/src/protobuf/consts.dart index 227188ac..22062b7d 100644 --- a/protobuf/lib/src/protobuf/consts.dart +++ b/protobuf/lib/src/protobuf/consts.dart @@ -2,16 +2,14 @@ // 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. -part of '../../protobuf.dart'; - /// Constant string value of `double.infinity.toString()` and the infinity /// value recognized by `double.parse(..)`. -const _infinity = 'Infinity'; +const infinity = 'Infinity'; /// Constant string value of `double.negativeInfinity.toString()` and the /// negative infinity value recognized by `double.parse(..)`. -const _negativeInfinity = '-Infinity'; +const negativeInfinity = '-Infinity'; /// Constant string value of `double.nan.toString()` and the NaN (not a number) /// value recognized by `double.parse(..)`. -const _nan = 'NaN'; +const nan = 'NaN'; diff --git a/protobuf/lib/src/protobuf/exceptions.dart b/protobuf/lib/src/protobuf/exceptions.dart index 3effb448..f55e9be0 100644 --- a/protobuf/lib/src/protobuf/exceptions.dart +++ b/protobuf/lib/src/protobuf/exceptions.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; const _truncatedMessageText = ''' While parsing a protocol message, the input ended unexpectedly diff --git a/protobuf/lib/src/protobuf/extension.dart b/protobuf/lib/src/protobuf/extension.dart index 27743b72..dc37b91f 100644 --- a/protobuf/lib/src/protobuf/extension.dart +++ b/protobuf/lib/src/protobuf/extension.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// An object representing an extension field. class Extension extends FieldInfo { diff --git a/protobuf/lib/src/protobuf/extension_field_set.dart b/protobuf/lib/src/protobuf/extension_field_set.dart index 9e066435..64972003 100644 --- a/protobuf/lib/src/protobuf/extension_field_set.dart +++ b/protobuf/lib/src/protobuf/extension_field_set.dart @@ -2,15 +2,15 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; -class _ExtensionFieldSet { - final _FieldSet _parent; +class ExtensionFieldSet { + final FieldSet _parent; final Map _info = {}; final Map _values = {}; bool _isReadOnly = false; - _ExtensionFieldSet(this._parent); + ExtensionFieldSet(this._parent); Extension? _getInfoOrNull(int tagNumber) => _info[tagNumber]; @@ -157,8 +157,8 @@ class _ExtensionFieldSet { bool get _hasValues => _values.isNotEmpty; - bool _equalValues(_ExtensionFieldSet? other) => - other != null && _areMapsEqual(_values, other._values); + bool _equalValues(ExtensionFieldSet? other) => + other != null && areMapsEqual(_values, other._values); void _clearValues() => _values.clear(); @@ -166,7 +166,7 @@ class _ExtensionFieldSet { /// /// Repeated fields are copied. /// Extensions cannot contain map fields. - void _shallowCopyValues(_ExtensionFieldSet original) { + void _shallowCopyValues(ExtensionFieldSet original) { for (final tagNumber in original._tagNumbers) { final extension = original._getInfoOrNull(tagNumber)!; _addInfoUnchecked(extension); @@ -212,3 +212,9 @@ class _ExtensionFieldSet { } } } + +extension ExtensionFieldSetInternalExtension on ExtensionFieldSet { + Map get values => _values; + Iterable get tagNumbers => _tagNumbers; + Extension? getInfoOrNull(int tagNumber) => _getInfoOrNull(tagNumber); +} diff --git a/protobuf/lib/src/protobuf/extension_registry.dart b/protobuf/lib/src/protobuf/extension_registry.dart index bc2f8b46..2535b49c 100644 --- a/protobuf/lib/src/protobuf/extension_registry.dart +++ b/protobuf/lib/src/protobuf/extension_registry.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// A collection of [Extension] objects, organized by the message type they /// extend. diff --git a/protobuf/lib/src/protobuf/field_error.dart b/protobuf/lib/src/protobuf/field_error.dart index 6c91a21b..c3dda123 100644 --- a/protobuf/lib/src/protobuf/field_error.dart +++ b/protobuf/lib/src/protobuf/field_error.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Returns the error message for an invalid field value, /// or null if it's valid. diff --git a/protobuf/lib/src/protobuf/field_info.dart b/protobuf/lib/src/protobuf/field_info.dart index a30925e2..87d76c27 100644 --- a/protobuf/lib/src/protobuf/field_info.dart +++ b/protobuf/lib/src/protobuf/field_info.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// An object representing a protobuf message field. class FieldInfo { @@ -60,7 +60,7 @@ class FieldInfo { /// `tagNumber` of `result_per_page` field is 3. final int tagNumber; - /// Index of the field in [_FieldSet._values] list of this field's message. + /// Index of the field in [FieldSet._values] list of this field's message. /// /// The value is `null` for extension fields. final int? index; @@ -148,7 +148,7 @@ class FieldInfo { assert(!_isEnum(type) || valueOf != null); static MakeDefaultFunc? findMakeDefault(int type, dynamic defaultOrMaker) { - if (defaultOrMaker == null) return PbFieldType._defaultForType(type); + if (defaultOrMaker == null) return PbFieldType.defaultForType(type); if (defaultOrMaker is MakeDefaultFunc) return defaultOrMaker; return () => defaultOrMaker; } @@ -238,8 +238,8 @@ class FieldInfo { } /// Convenience method to thread this FieldInfo's reified type parameter to - /// `_FieldSet._ensureRepeatedField`. - PbList _ensureRepeatedField(BuilderInfo meta, _FieldSet fs) { + /// `FieldSet._ensureRepeatedField`. + PbList _ensureRepeatedField(BuilderInfo meta, FieldSet fs) { return fs._ensureRepeatedField(meta, this); } @@ -247,6 +247,11 @@ class FieldInfo { String toString() => name; } +extension FieldInfoInternalExtension on FieldInfo { + List ensureRepeatedField(BuilderInfo meta, FieldSet fs) => + _ensureRepeatedField(meta, fs); +} + final RegExp _upperCase = RegExp('[A-Z]'); String _unCamelCase(String name) { @@ -304,7 +309,7 @@ class MapFieldInfo extends FieldInfo?> { FieldInfo get valueFieldInfo => mapEntryBuilderInfo.fieldInfo[PbMap._valueFieldNumber]!; - PbMap _ensureMapField(BuilderInfo meta, _FieldSet fs) { + PbMap _ensureMapField(BuilderInfo meta, FieldSet fs) { return fs._ensureMapField(meta, this); } @@ -313,3 +318,8 @@ class MapFieldInfo extends FieldInfo?> { return PbMap(keyFieldType, valueFieldType); } } + +extension MapFieldInfoInternalExtension on MapFieldInfo { + Map ensureMapField(BuilderInfo meta, FieldSet fs) => + _ensureMapField(meta, fs); +} diff --git a/protobuf/lib/src/protobuf/field_set.dart b/protobuf/lib/src/protobuf/field_set.dart index ec73665b..aee73b7b 100644 --- a/protobuf/lib/src/protobuf/field_set.dart +++ b/protobuf/lib/src/protobuf/field_set.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; @pragma('vm:never-inline') @pragma('wasm:never-inline') @@ -25,7 +25,7 @@ void _throwFrozenMessageModificationError( /// These fields and methods are in a separate class to avoid polymorphic /// access due to inheritance. This turns out to be faster when compiled to /// JavaScript. -class _FieldSet { +class FieldSet { final GeneratedMessage? _message; /// The value of each non-extension field in a fixed-length array. @@ -34,7 +34,7 @@ class _FieldSet { final List _values; /// Contains all the extension fields, or null if there aren't any. - _ExtensionFieldSet? _extensions; + ExtensionFieldSet? _extensions; /// Contains all the unknown fields, or null if there aren't any. UnknownFieldSet? _unknownFields; @@ -53,7 +53,7 @@ class _FieldSet { /// code as an `int`. Object _frozenState = false; - /// The [BuilderInfo] for the [GeneratedMessage] this [_FieldSet] belongs to. + /// The [BuilderInfo] for the [GeneratedMessage] this [FieldSet] belongs to. /// /// WARNING: Avoid calling this for any performance critical code, instead /// obtain the [BuilderInfo] on the call site. @@ -82,7 +82,7 @@ class _FieldSet { /// the index is not present, the oneof field is unset. final Map? _oneofCases; - _FieldSet(this._message, BuilderInfo meta) + FieldSet(this._message, BuilderInfo meta) : _values = _makeValueList(meta.byIndex.length), _oneofCases = meta.oneofs.isEmpty ? null : {}; @@ -106,8 +106,8 @@ class _FieldSet { /// The [FieldInfo] for each non-extension field in tag order. Iterable get _infosSortedByTag => _meta.sortedByTag; - _ExtensionFieldSet _ensureExtensions() => - _extensions ??= _ExtensionFieldSet(this); + ExtensionFieldSet _ensureExtensions() => + _extensions ??= ExtensionFieldSet(this); UnknownFieldSet _ensureUnknownFields() { if (_unknownFields == null) { @@ -510,7 +510,7 @@ class _FieldSet { _extensions?._clearValues(); } - bool _equals(_FieldSet o) { + bool _equals(FieldSet o) { if (_meta != o._meta) return false; for (var i = 0; i < _values.length; i++) { if (!_equalFieldValues(_values[i], o._values[i])) return false; @@ -545,7 +545,7 @@ class _FieldSet { } bool _equalFieldValues(Object? left, Object? right) { - if (left != null && right != null) return _deepEquals(left, right); + if (left != null && right != null) return deepEquals(left, right); final val = left ?? right; @@ -584,7 +584,7 @@ class _FieldSet { } // Hash with descriptor. - var hash = _HashUtils._combine(0, _meta.hashCode); + var hash = HashUtils.combine(0, _meta.hashCode); // Hash with non-extension fields. final values = _values; @@ -597,7 +597,7 @@ class _FieldSet { // Hash with extension fields. final extensions = _extensions; if (extensions != null) { - final sortedByTagNumbers = _sorted(extensions._tagNumbers); + final sortedByTagNumbers = sorted(extensions._tagNumbers); for (final tagNumber in sortedByTagNumbers) { final fi = extensions._getInfoOrNull(tagNumber)!; hash = _hashField(hash, fi, extensions._getFieldOrNull(fi)); @@ -605,7 +605,7 @@ class _FieldSet { } // Hash with unknown fields. - hash = _HashUtils._combine(hash, _unknownFields?.hashCode ?? 0); + hash = HashUtils.combine(hash, _unknownFields?.hashCode ?? 0); // Ignore _unknownJsonData to preserve existing hashing behavior. @@ -625,18 +625,18 @@ class _FieldSet { return hash; } - hash = _HashUtils._combine(hash, fi.tagNumber); + hash = HashUtils.combine(hash, fi.tagNumber); if (_isBytes(fi.type)) { // Bytes are represented as a List (Usually with byte-data). // We special case that to match our equality semantics. - hash = _HashUtils._combine(hash, _HashUtils._hashObjects(value)); + hash = HashUtils.combine(hash, HashUtils.hashObjects(value)); } else if (!_isEnum(fi.type)) { - hash = _HashUtils._combine(hash, value.hashCode); + hash = HashUtils.combine(hash, value.hashCode); } else if (fi.isRepeated) { final PbList list = value; - hash = _HashUtils._combine( + hash = HashUtils.combine( hash, - _HashUtils._hashObjects( + HashUtils.hashObjects( list.map((enm) { final ProtobufEnum enm_ = enm; return enm_.value; @@ -645,7 +645,7 @@ class _FieldSet { ); } else { final ProtobufEnum enm = value; - hash = _HashUtils._combine(hash, enm.value); + hash = HashUtils.combine(hash, enm.value); } return hash; @@ -716,7 +716,7 @@ class _FieldSet { /// Singular fields that are set in [other] overwrite the corresponding fields /// in this message. Repeated fields are appended. Singular sub-messages are /// recursively merged. - void _mergeFromMessage(_FieldSet other) { + void _mergeFromMessage(FieldSet other) { // TODO(https://github.com/google/protobuf.dart/issues/60): Recognize // when `this` and [other] are the same protobuf (e.g. from cloning). In // this case, we can merge the non-extension fields without field lookups or @@ -880,7 +880,7 @@ class _FieldSet { /// Makes a shallow copy of all values from [original] to this. /// /// Map fields and repeated fields are copied. - void _shallowCopyValues(_FieldSet original) { + void _shallowCopyValues(FieldSet original) { _values.setRange(0, original._values.length, original._values); final info = _meta; for (var index = 0; index < info.byIndex.length; index++) { @@ -917,3 +917,26 @@ class _FieldSet { _oneofCases?.addAll(original._oneofCases!); } } + +extension FieldSetInternalExtension on FieldSet { + Iterable get infos => _infos; + Iterable get infosSortedByTag => _infosSortedByTag; + List get values => _values; + ExtensionFieldSet? get extensions => _extensions; + UnknownFieldSet? get unknownFields => _unknownFields; + Map? get unknownJsonData => _unknownJsonData; + set unknownJsonData(Map? value) => _unknownJsonData = value; + BuilderInfo get meta => _meta; + GeneratedMessage? get message => _message; + String get messageName => _messageName; + + void ensureWritable() => _ensureWritable(); + PbList ensureRepeatedField(BuilderInfo meta, FieldInfo fi) => + _ensureRepeatedField(meta, fi); + PbMap ensureMapField(BuilderInfo meta, MapFieldInfo fi) => + _ensureMapField(meta, fi); + void validateField(FieldInfo fi, dynamic newValue) => + _validateField(fi, newValue); + void setFieldUnchecked(BuilderInfo meta, FieldInfo fi, dynamic value) => + _setFieldUnchecked(meta, fi, value); +} diff --git a/protobuf/lib/src/protobuf/field_type.dart b/protobuf/lib/src/protobuf/field_type.dart index cb6a1a47..ad3ac240 100644 --- a/protobuf/lib/src/protobuf/field_type.dart +++ b/protobuf/lib/src/protobuf/field_type.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. // ignore_for_file: constant_identifier_names,non_constant_identifier_names -part of '../../protobuf.dart'; +part of 'internal.dart'; bool _isRepeated(int fieldType) => (fieldType & PbFieldType._REPEATED_BIT) != 0; @@ -27,7 +27,7 @@ class PbFieldType { static int _baseType(int fieldType) => fieldType & ~(_REQUIRED_BIT | _REPEATED_BIT | _PACKED_BIT | _MAP_BIT); - static MakeDefaultFunc? _defaultForType(int type) { + static MakeDefaultFunc? defaultForType(int type) { switch (type) { case _OPTIONAL_BOOL: case _REQUIRED_BOOL: diff --git a/protobuf/lib/src/protobuf/generated_message.dart b/protobuf/lib/src/protobuf/generated_message.dart index 7cf6a0a1..28f4992b 100644 --- a/protobuf/lib/src/protobuf/generated_message.dart +++ b/protobuf/lib/src/protobuf/generated_message.dart @@ -4,7 +4,7 @@ // ignore_for_file: non_constant_identifier_names -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Type of an empty message builder. typedef CreateBuilderFunc = GeneratedMessage Function(); @@ -25,13 +25,13 @@ typedef ValueOfFunc = ProtobufEnum? Function(int value); /// `GeneratedMessage_reservedNames` and should be unlikely to be used in a /// proto file. abstract class GeneratedMessage { - _FieldSet? __fieldSet; + FieldSet? __fieldSet; @pragma('dart2js:tryInline') - _FieldSet get _fieldSet => __fieldSet!; + FieldSet get _fieldSet => __fieldSet!; GeneratedMessage() { - __fieldSet = _FieldSet(this, info_); + __fieldSet = FieldSet(this, info_); // The following two returns confuse dart2js into avoiding inlining the // constructor *body*. A `@pragma('dart2js:never-inline')` annotation on @@ -637,3 +637,7 @@ extension GeneratedMessageGenericExtensions on T { ) T deepCopy() => info_.createEmptyInstance!() as T..mergeFromMessage(this); } + +extension GeneratedMessageInternalExtension on GeneratedMessage { + FieldSet get fieldSet => _fieldSet; +} diff --git a/protobuf/lib/src/protobuf/generated_service.dart b/protobuf/lib/src/protobuf/generated_service.dart index f2b8857e..fc6feae3 100644 --- a/protobuf/lib/src/protobuf/generated_service.dart +++ b/protobuf/lib/src/protobuf/generated_service.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Server side context. class ServerContext { diff --git a/protobuf/lib/src/protobuf/internal.dart b/protobuf/lib/src/protobuf/internal.dart new file mode 100644 index 00000000..176084d7 --- /dev/null +++ b/protobuf/lib/src/protobuf/internal.dart @@ -0,0 +1,67 @@ +// Copyright (c) 2011, 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. + +/// Runtime library for Dart implementation of [protobufs][1]. +/// +/// [1]: https://developers.google.com/protocol-buffers +library; + +import 'dart:collection' show ListBase, MapBase; +import 'dart:convert' + show + Utf8Decoder, + Utf8Encoder, + base64Decode, + base64Encode, + jsonDecode, + jsonEncode; +import 'dart:math' as math; +import 'dart:typed_data' show ByteData, Endian, Uint8List; + +import 'package:fixnum/fixnum.dart' show Int64; +import 'package:meta/meta.dart' show UseResult; + +import 'consts.dart'; +import 'json_parsing_context.dart'; +import 'permissive_compare.dart'; +import 'type_registry.dart'; +import 'utils.dart'; + +export 'type_registry.dart' show TypeRegistry; + +part 'annotations.dart'; +part 'builder_info.dart'; +part 'coded_buffer.dart'; +part 'coded_buffer_reader.dart'; +part 'coded_buffer_writer.dart'; +part 'exceptions.dart'; +part 'extension.dart'; +part 'extension_field_set.dart'; +part 'extension_registry.dart'; +part 'field_error.dart'; +part 'field_info.dart'; +part 'field_set.dart'; +part 'field_type.dart'; +part 'generated_message.dart'; +part 'generated_service.dart'; +part 'json.dart'; +part 'message_set.dart'; +part 'pb_list.dart'; +part 'pb_map.dart'; +part 'proto3_json.dart'; +part 'protobuf_enum.dart'; +part 'rpc_client.dart'; +part 'unknown_field_set.dart'; +part 'unpack.dart'; +part 'wire_format.dart'; + +// TODO(sra): Use `Int64.parse()` when available: +// https://github.com/dart-lang/fixnum/issues/18. +/// @nodoc +Int64 parseLongInt(String text) { + if (text.startsWith('0x')) return Int64.parseHex(text.substring(2)); + if (text.startsWith('+0x')) return Int64.parseHex(text.substring(3)); + if (text.startsWith('-0x')) return -Int64.parseHex(text.substring(3)); + return Int64.parseInt(text); +} diff --git a/protobuf/lib/src/protobuf/json.dart b/protobuf/lib/src/protobuf/json.dart index 75d4fa86..f2175675 100644 --- a/protobuf/lib/src/protobuf/json.dart +++ b/protobuf/lib/src/protobuf/json.dart @@ -2,9 +2,9 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; -Map _writeToJsonMap(_FieldSet fs) { +Map _writeToJsonMap(FieldSet fs) { dynamic convertToMap(dynamic fieldValue, int fieldType) { final baseType = PbFieldType._baseType(fieldType); @@ -26,10 +26,10 @@ Map _writeToJsonMap(_FieldSet fs) { case PbFieldType._DOUBLE_BIT: final value = fieldValue as double; if (value.isNaN) { - return _nan; + return nan; } if (value.isInfinite) { - return value.isNegative ? _negativeInfinity : _infinity; + return value.isNegative ? negativeInfinity : infinity; } if (fieldValue.toInt() == fieldValue) { return fieldValue.toInt(); @@ -84,7 +84,7 @@ Map _writeToJsonMap(_FieldSet fs) { } final extensions = fs._extensions; if (extensions != null) { - for (final tagNumber in _sorted(extensions._tagNumbers)) { + for (final tagNumber in sorted(extensions._tagNumbers)) { final value = extensions._values[tagNumber]; if (value is List && value.isEmpty) { continue; // It's repeated or an empty byte array. @@ -105,7 +105,7 @@ Map _writeToJsonMap(_FieldSet fs) { // Merge fields from a previously decoded JSON object. // (Called recursively on nested messages.) void _mergeFromJsonMap( - _FieldSet fs, + FieldSet fs, Map json, ExtensionRegistry? registry, ) { @@ -139,7 +139,7 @@ void _mergeFromJsonMap( void _appendJsonList( BuilderInfo meta, - _FieldSet fs, + FieldSet fs, List jsonList, FieldInfo fi, ExtensionRegistry? registry, @@ -169,7 +169,7 @@ void _appendJsonList( void _appendJsonMap( BuilderInfo meta, - _FieldSet fs, + FieldSet fs, List jsonList, MapFieldInfo fi, ExtensionRegistry? registry, @@ -178,7 +178,7 @@ void _appendJsonMap( final map = fi._ensureMapField(meta, fs); for (final jsonEntryDynamic in jsonList) { final jsonEntry = jsonEntryDynamic as Map; - final entryFieldSet = _FieldSet(null, entryMeta); + final entryFieldSet = FieldSet(null, entryMeta); final convertedKey = _convertJsonValue( entryMeta, entryFieldSet, @@ -205,7 +205,7 @@ void _appendJsonMap( void _setJsonField( BuilderInfo meta, - _FieldSet fs, + FieldSet fs, json, FieldInfo fi, ExtensionRegistry? registry, @@ -239,7 +239,7 @@ void _setJsonField( /// Throws [ArgumentError] if it cannot convert the value. dynamic _convertJsonValue( BuilderInfo meta, - _FieldSet fs, + FieldSet fs, value, int tagNumber, int fieldType, diff --git a/protobuf/lib/src/protobuf/message_set.dart b/protobuf/lib/src/protobuf/message_set.dart index 9a021317..dfae8770 100644 --- a/protobuf/lib/src/protobuf/message_set.dart +++ b/protobuf/lib/src/protobuf/message_set.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; const _messageSetItemsTag = 1; const _messageSetItemTypeIdTag = 2; diff --git a/protobuf/lib/src/protobuf/pb_list.dart b/protobuf/lib/src/protobuf/pb_list.dart index 9d880f55..d48a8214 100644 --- a/protobuf/lib/src/protobuf/pb_list.dart +++ b/protobuf/lib/src/protobuf/pb_list.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Type of a function that checks items added to a `PbList`. /// @@ -204,10 +204,10 @@ class PbList extends ListBase { @override bool operator ==(Object other) => - other is PbList && _areListsEqual(other, this); + other is PbList && areListsEqual(other, this); @override - int get hashCode => _HashUtils._hashObjects(_wrappedList); + int get hashCode => HashUtils.hashObjects(_wrappedList); void freeze() { if (_isReadOnly) { diff --git a/protobuf/lib/src/protobuf/pb_map.dart b/protobuf/lib/src/protobuf/pb_map.dart index 44337fb2..f9c5379d 100644 --- a/protobuf/lib/src/protobuf/pb_map.dart +++ b/protobuf/lib/src/protobuf/pb_map.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// A [MapBase] implementation used for protobuf `map` fields. class PbMap extends MapBase { @@ -77,7 +77,7 @@ class PbMap extends MapBase { int get hashCode { return _wrappedMap.entries.fold( 0, - (h, entry) => h ^ _HashUtils._hash2(entry.key, entry.value), + (h, entry) => h ^ HashUtils.hash2(entry.key, entry.value), ); } @@ -108,7 +108,7 @@ class PbMap extends MapBase { final length = input.readInt32(); final oldLimit = input._currentLimit; input._currentLimit = input._bufferPos + length; - final entryFieldSet = _FieldSet(null, mapEntryMeta); + final entryFieldSet = FieldSet(null, mapEntryMeta); _mergeFromCodedBufferReader(mapEntryMeta, entryFieldSet, input, registry); input.checkLastTagWas(0); input._currentLimit = oldLimit; diff --git a/protobuf/lib/src/protobuf/proto3_json.dart b/protobuf/lib/src/protobuf/proto3_json.dart index c2bbf29c..c1dbe11a 100644 --- a/protobuf/lib/src/protobuf/proto3_json.dart +++ b/protobuf/lib/src/protobuf/proto3_json.dart @@ -2,9 +2,9 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; -Object? _writeToProto3Json(_FieldSet fs, TypeRegistry typeRegistry) { +Object? _writeToProto3Json(FieldSet fs, TypeRegistry typeRegistry) { String? convertToMapKey(dynamic key, int keyType) { final baseType = PbFieldType._baseType(keyType); @@ -64,10 +64,10 @@ Object? _writeToProto3Json(_FieldSet fs, TypeRegistry typeRegistry) { case PbFieldType._DOUBLE_BIT: final double value = fieldValue; if (value.isNaN) { - return _nan; + return nan; } if (value.isInfinite) { - return value.isNegative ? _negativeInfinity : _infinity; + return value.isNegative ? negativeInfinity : infinity; } if (value.toInt() == fieldValue) { return value.toInt(); @@ -160,7 +160,7 @@ extension _FindFirst on Iterable { /// to [fieldSet]. void _mergeFromProto3Json( Object? json, - _FieldSet fieldSet, + FieldSet fieldSet, TypeRegistry typeRegistry, bool ignoreUnknownFields, bool supportNamesWithUnderscores, @@ -173,7 +173,7 @@ void _mergeFromProto3Json( permissiveEnums, ); - void recursionHelper(Object? json, _FieldSet fieldSet) { + void recursionHelper(Object? json, FieldSet fieldSet) { Object? convertProto3JsonValue(Object value, FieldInfo fieldInfo) { final fieldType = fieldInfo.type; switch (PbFieldType._baseType(fieldType)) { diff --git a/protobuf/lib/src/protobuf/protobuf_enum.dart b/protobuf/lib/src/protobuf/protobuf_enum.dart index 73779fb2..5ec61a0a 100644 --- a/protobuf/lib/src/protobuf/protobuf_enum.dart +++ b/protobuf/lib/src/protobuf/protobuf_enum.dart @@ -4,7 +4,7 @@ // ignore_for_file: non_constant_identifier_names -part of '../../protobuf.dart'; +part of 'internal.dart'; /// A base class for all proto enum types. /// diff --git a/protobuf/lib/src/protobuf/rpc_client.dart b/protobuf/lib/src/protobuf/rpc_client.dart index 6239674e..7f091f08 100644 --- a/protobuf/lib/src/protobuf/rpc_client.dart +++ b/protobuf/lib/src/protobuf/rpc_client.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Client side context for [RpcClient]s. class ClientContext { diff --git a/protobuf/lib/src/protobuf/unknown_field_set.dart b/protobuf/lib/src/protobuf/unknown_field_set.dart index b0579a91..62cee24b 100644 --- a/protobuf/lib/src/protobuf/unknown_field_set.dart +++ b/protobuf/lib/src/protobuf/unknown_field_set.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// A set of unknown fields in a [GeneratedMessage]. class UnknownFieldSet { @@ -140,7 +140,7 @@ class UnknownFieldSet { if (other is! UnknownFieldSet) return false; final o = other; - return _areMapsEqual(o._fields, _fields); + return areMapsEqual(o._fields, _fields); } @override @@ -159,7 +159,7 @@ class UnknownFieldSet { String _toString(String indent) { final stringBuffer = StringBuffer(); - for (final tag in _sorted(_fields.keys)) { + for (final tag in sorted(_fields.keys)) { final field = _fields[tag]!; for (final value in field.values) { if (value is UnknownFieldSet) { @@ -230,14 +230,14 @@ class UnknownFieldSetField { final o = other; if (lengthDelimited.length != o.lengthDelimited.length) return false; for (var i = 0; i < lengthDelimited.length; i++) { - if (!_areListsEqual(o.lengthDelimited[i], lengthDelimited[i])) { + if (!areListsEqual(o.lengthDelimited[i], lengthDelimited[i])) { return false; } } - if (!_areListsEqual(o.varints, varints)) return false; - if (!_areListsEqual(o.fixed32s, fixed32s)) return false; - if (!_areListsEqual(o.fixed64s, fixed64s)) return false; - if (!_areListsEqual(o.groups, groups)) return false; + if (!areListsEqual(o.varints, varints)) return false; + if (!areListsEqual(o.fixed32s, fixed32s)) return false; + if (!areListsEqual(o.fixed64s, fixed64s)) return false; + if (!areListsEqual(o.groups, groups)) return false; return true; } diff --git a/protobuf/lib/src/protobuf/unpack.dart b/protobuf/lib/src/protobuf/unpack.dart index aed3260b..08d54760 100644 --- a/protobuf/lib/src/protobuf/unpack.dart +++ b/protobuf/lib/src/protobuf/unpack.dart @@ -2,7 +2,7 @@ // 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. -part of '../../protobuf.dart'; +part of 'internal.dart'; /// Unpacks the message in [value] into [instance]. /// diff --git a/protobuf/lib/src/protobuf/utils.dart b/protobuf/lib/src/protobuf/utils.dart index 4a6b0885..b4bb8bce 100644 --- a/protobuf/lib/src/protobuf/utils.dart +++ b/protobuf/lib/src/protobuf/utils.dart @@ -2,38 +2,38 @@ // 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. -part of '../../protobuf.dart'; +import 'internal.dart'; // TODO(antonm): reconsider later if PbList should take care of equality. -bool _deepEquals(Object lhs, Object rhs) { +bool deepEquals(Object lhs, Object rhs) { // Some GeneratedMessages implement Map, so test this first. if (lhs is GeneratedMessage) return lhs == rhs; if (rhs is GeneratedMessage) return false; - if ((lhs is List) && (rhs is List)) return _areListsEqual(lhs, rhs); - if ((lhs is Map) && (rhs is Map)) return _areMapsEqual(lhs, rhs); + if ((lhs is List) && (rhs is List)) return areListsEqual(lhs, rhs); + if ((lhs is Map) && (rhs is Map)) return areMapsEqual(lhs, rhs); return lhs == rhs; } -bool _areListsEqual(List lhs, List rhs) { +bool areListsEqual(List lhs, List rhs) { if (lhs.length != rhs.length) return false; for (var i = 0; i < lhs.length; i++) { - if (!_deepEquals(lhs[i], rhs[i])) return false; + if (!deepEquals(lhs[i], rhs[i])) return false; } return true; } -bool _areMapsEqual(Map lhs, Map rhs) { +bool areMapsEqual(Map lhs, Map rhs) { if (lhs.length != rhs.length) return false; - return lhs.keys.every((key) => _deepEquals(lhs[key], rhs[key])); + return lhs.keys.every((key) => deepEquals(lhs[key], rhs[key])); } -List _sorted(Iterable list) => List.from(list)..sort(); +List sorted(Iterable list) => List.from(list)..sort(); -class _HashUtils { +class HashUtils { // Jenkins hash functions copied from // https://github.com/google/quiver-dart/blob/master/lib/src/core/hash.dart. - static int _combine(int hash, int value) { + static int combine(int hash, int value) { hash = 0x1fffffff & (hash + value); hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); return hash ^ (hash >> 6); @@ -46,10 +46,10 @@ class _HashUtils { } /// Generates a hash code for multiple [objects]. - static int _hashObjects(Iterable objects) => - _finish(objects.fold(0, (h, i) => _combine(h, i.hashCode))); + static int hashObjects(Iterable objects) => + _finish(objects.fold(0, (h, i) => combine(h, i.hashCode))); /// Generates a hash code for two objects. - static int _hash2(dynamic a, dynamic b) => - _finish(_combine(_combine(0, a.hashCode), b.hashCode)); + static int hash2(dynamic a, dynamic b) => + _finish(combine(combine(0, a.hashCode), b.hashCode)); } diff --git a/protobuf/lib/src/protobuf/wire_format.dart b/protobuf/lib/src/protobuf/wire_format.dart index a255c817..1dabb638 100644 --- a/protobuf/lib/src/protobuf/wire_format.dart +++ b/protobuf/lib/src/protobuf/wire_format.dart @@ -4,7 +4,7 @@ // ignore_for_file: constant_identifier_names -part of '../../protobuf.dart'; +part of 'internal.dart'; const int _TAG_TYPE_BITS = 3; const int _TAG_TYPE_MASK = (1 << _TAG_TYPE_BITS) - 1; diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml index 0b3a6103..50d99cf2 100644 --- a/protobuf/pubspec.yaml +++ b/protobuf/pubspec.yaml @@ -1,5 +1,5 @@ name: protobuf -version: 4.1.1 +version: 4.2.0-wip description: >- Runtime library for protocol buffers support. Use with package:protoc_plugin to generate Dart code for your '.proto' files. diff --git a/protoc_plugin/test/reserved_names_test.dart b/protoc_plugin/test/reserved_names_test.dart index 2158b9ab..56376c3f 100644 --- a/protoc_plugin/test/reserved_names_test.dart +++ b/protoc_plugin/test/reserved_names_test.dart @@ -20,7 +20,7 @@ void main() { test('GeneratedMessage reserved names are up to date', () { final actual = Set.from(GeneratedMessage_reservedNames); final expected = findMemberNames( - 'package:protobuf/protobuf.dart', + 'package:protobuf/src/protobuf/internal.dart', #GeneratedMessage, ); @@ -30,7 +30,7 @@ void main() { test('ProtobufEnum reserved names are up to date', () { final actual = Set.from(ProtobufEnum_reservedNames); final expected = findMemberNames( - 'package:protobuf/protobuf.dart', + 'package:protobuf/src/protobuf/internal.dart', #ProtobufEnum, ); @@ -39,7 +39,7 @@ void main() { test("ReadonlyMessageMixin doesn't add any reserved names", () { final mixinNames = findMemberNames( - 'package:protobuf/protobuf.dart', + 'package:protobuf/src/protobuf/internal.dart', #ReadonlyMessageMixin, ); final reservedNames = Set.from(GeneratedMessage_reservedNames);