Support for Any (#116)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21d492b..b605451 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.10.1
+
+* Added Support for [any](https://developers.google.com/protocol-buffers/docs/proto3#any) messages.
+
## 0.10.0
* Breaking change: Add `GeneratedMessage.freeze()`. A frozen message and its
diff --git a/lib/protobuf.dart b/lib/protobuf.dart
index dd08da7..177a717 100644
--- a/lib/protobuf.dart
+++ b/lib/protobuf.dart
@@ -35,6 +35,7 @@
part 'src/protobuf/rpc_client.dart';
part 'src/protobuf/unknown_field_set.dart';
part 'src/protobuf/utils.dart';
+part 'src/protobuf/unpack.dart';
part 'src/protobuf/wire_format.dart';
// TODO(sra): Remove this method when clients upgrade to protoc 0.3.5
diff --git a/lib/src/protobuf/builder_info.dart b/lib/src/protobuf/builder_info.dart
index abc0965..0670c56 100644
--- a/lib/src/protobuf/builder_info.dart
+++ b/lib/src/protobuf/builder_info.dart
@@ -6,6 +6,7 @@
/// Per-message type setup.
class BuilderInfo {
+ /// The fully qualified name of this message.
final String messageName;
final List<FieldInfo> byIndex = <FieldInfo>[];
final Map<int, FieldInfo> fieldInfo = new Map<int, FieldInfo>();
@@ -15,7 +16,8 @@
bool hasRequiredFields = true;
List<FieldInfo> _sortedByTag;
- BuilderInfo(this.messageName);
+ BuilderInfo(String messageName, {PackageName package = const PackageName('')})
+ : messageName = "${package.prefix}$messageName";
void add<T>(
int tagNumber,
diff --git a/lib/src/protobuf/exceptions.dart b/lib/src/protobuf/exceptions.dart
index 412a8d8..bc8d43c 100644
--- a/lib/src/protobuf/exceptions.dart
+++ b/lib/src/protobuf/exceptions.dart
@@ -34,4 +34,11 @@
input has been truncated or that an embedded message
misreported its own length.
''');
+
+ InvalidProtocolBufferException.wrongAnyMessage(
+ String anyTypeName, unpackerTypeName)
+ : this._('''
+The type of the Any message ($anyTypeName) does not match the given
+unpacker ($unpackerTypeName).
+''');
}
diff --git a/lib/src/protobuf/generated_message.dart b/lib/src/protobuf/generated_message.dart
index fb22b2d..0adc6c9 100644
--- a/lib/src/protobuf/generated_message.dart
+++ b/lib/src/protobuf/generated_message.dart
@@ -373,3 +373,10 @@
/// For generated code only.
void $_setInt64(int index, Int64 value) => _fieldSet._$set(index, value);
}
+
+/// The package name of a protobuf message.
+class PackageName {
+ final String name;
+ const PackageName(this.name);
+ String get prefix => name == '' ? '' : '$name.';
+}
diff --git a/lib/src/protobuf/unpack.dart b/lib/src/protobuf/unpack.dart
new file mode 100644
index 0000000..142ebcd
--- /dev/null
+++ b/lib/src/protobuf/unpack.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2018, 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.
+
+part of protobuf;
+
+/// Unpacks the message in [value] into [instance].
+///
+/// Throws a [InvalidProtocolBufferException] if [typeUrl] does not correspond
+/// with the type of [instance].
+///
+/// This is a helper method for `Any.unpackInto`.
+void unpackIntoHelper<T extends GeneratedMessage>(
+ List<int> value, T instance, String typeUrl,
+ {ExtensionRegistry extensionRegistry = ExtensionRegistry.EMPTY}) {
+ // From "google/protobuf/any.proto":
+ //
+ // The pack methods provided by protobuf library will by default use
+ // 'type.googleapis.com/full.type.name' as the type URL and the unpack
+ // methods only use the fully qualified type name after the last '/'
+ // in the type URL, for example "foo.bar.com/x/y.z" will yield type
+ // name "y.z".
+ if (!canUnpackIntoHelper(instance, typeUrl)) {
+ String typeName = instance.info_.messageName;
+ throw new InvalidProtocolBufferException.wrongAnyMessage(
+ _typeNameFromUrl(typeUrl), typeName);
+ }
+ instance.mergeFromBuffer(value, extensionRegistry);
+}
+
+/// Returns `true` if the type of [instance] is described by
+/// `typeUrl`.
+///
+/// This is a helper method for `Any.canUnpackInto`.
+bool canUnpackIntoHelper(GeneratedMessage instance, String typeUrl) {
+ return instance.info_.messageName == _typeNameFromUrl(typeUrl);
+}
+
+String _typeNameFromUrl(String typeUrl) {
+ int index = typeUrl.lastIndexOf('/');
+ return index == -1 ? '' : typeUrl.substring(index + 1);
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index c715c6b..fb08c89 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: protobuf
-version: 0.10.0
+version: 0.10.1
author: Dart Team <misc@dartlang.org>
description: Runtime library for protocol buffers support.
homepage: https://github.com/dart-lang/protobuf