Sync changes from internal repo. (#79)

* Added enumValues to FieldInfo. Fixes #63.
* Small performance optimization when deserializing repeated messages
  from JSON.
* Type annotations for strong mode.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index edc89ea..00018f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,9 @@
-## 0.5.6
+## 0.6.0
 
-* Add generic type to `CheckFunc` typedef.
+* Added enumValues to FieldInfo. Fixes #63.
+* Small performance optimization when deserializing repeated messages
+  from JSON.
+* Type annotations for strong mode.
 
 ## 0.5.5
 
diff --git a/lib/src/protobuf/builder_info.dart b/lib/src/protobuf/builder_info.dart
index 5e3ecc5..e9d55f9 100644
--- a/lib/src/protobuf/builder_info.dart
+++ b/lib/src/protobuf/builder_info.dart
@@ -16,18 +16,30 @@
 
   BuilderInfo(this.messageName);
 
-  void add<T>(int tagNumber, String name, int fieldType, dynamic defaultOrMaker,
-      CreateBuilderFunc subBuilder, ValueOfFunc valueOf) {
+  void add<T>(
+      int tagNumber,
+      String name,
+      int fieldType,
+      dynamic defaultOrMaker,
+      CreateBuilderFunc subBuilder,
+      ValueOfFunc valueOf,
+      List<ProtobufEnum> enumValues) {
     var index = fieldInfo.length;
     addField(new FieldInfo<T>(name, tagNumber, index, fieldType, defaultOrMaker,
-        subBuilder, valueOf));
+        subBuilder, valueOf, enumValues));
   }
 
-  void addRepeated<T>(int tagNumber, String name, int fieldType,
-      CheckFunc<T> check, CreateBuilderFunc subBuilder, ValueOfFunc valueOf) {
+  void addRepeated<T>(
+      int tagNumber,
+      String name,
+      int fieldType,
+      CheckFunc<T> check,
+      CreateBuilderFunc subBuilder,
+      ValueOfFunc valueOf,
+      List<ProtobufEnum> enumValues) {
     var index = fieldInfo.length;
-    addField(new FieldInfo<T>.repeated(
-        name, tagNumber, index, fieldType, check, subBuilder, valueOf));
+    addField(new FieldInfo<T>.repeated(name, tagNumber, index, fieldType, check,
+        subBuilder, valueOf, enumValues));
   }
 
   void addField(FieldInfo fi) {
@@ -39,14 +51,17 @@
   void a<T>(int tagNumber, String name, int fieldType,
       [dynamic defaultOrMaker,
       CreateBuilderFunc subBuilder,
-      ValueOfFunc valueOf]) {
-    add<T>(tagNumber, name, fieldType, defaultOrMaker, subBuilder, valueOf);
+      ValueOfFunc valueOf,
+      List<ProtobufEnum> enumValues]) {
+    add<T>(tagNumber, name, fieldType, defaultOrMaker, subBuilder, valueOf,
+        enumValues);
   }
 
   // Enum.
   void e<T>(int tagNumber, String name, int fieldType, dynamic defaultOrMaker,
-      ValueOfFunc valueOf) {
-    add<T>(tagNumber, name, fieldType, defaultOrMaker, null, valueOf);
+      ValueOfFunc valueOf, List<ProtobufEnum> enumValues) {
+    add<T>(
+        tagNumber, name, fieldType, defaultOrMaker, null, valueOf, enumValues);
   }
 
   // Repeated message.
@@ -54,21 +69,24 @@
   void m<T>(int tagNumber, String name, CreateBuilderFunc subBuilder,
       MakeDefaultFunc makeDefault) {
     add<T>(tagNumber, name, PbFieldType._REPEATED_MESSAGE, makeDefault,
-        subBuilder, null);
+        subBuilder, null, null);
   }
 
   // Repeated, not a message, group, or enum.
   void p<T>(int tagNumber, String name, int fieldType) {
     assert(!_isGroupOrMessage(fieldType) && !_isEnum(fieldType));
-    addRepeated<T>(
-        tagNumber, name, fieldType, getCheckFunction(fieldType), null, null);
+    addRepeated<T>(tagNumber, name, fieldType, getCheckFunction(fieldType),
+        null, null, null);
   }
 
   // Repeated message, group, or enum.
   void pp<T>(int tagNumber, String name, int fieldType, CheckFunc<T> check,
-      [CreateBuilderFunc subBuilder, ValueOfFunc valueOf]) {
+      [CreateBuilderFunc subBuilder,
+      ValueOfFunc valueOf,
+      List<ProtobufEnum> enumValues]) {
     assert(_isGroupOrMessage(fieldType) || _isEnum(fieldType));
-    addRepeated<T>(tagNumber, name, fieldType, check, subBuilder, valueOf);
+    addRepeated<T>(
+        tagNumber, name, fieldType, check, subBuilder, valueOf, enumValues);
   }
 
   bool containsTagNumber(int tagNumber) => fieldInfo.containsKey(tagNumber);
diff --git a/lib/src/protobuf/extension.dart b/lib/src/protobuf/extension.dart
index 6881e36..59e350f 100644
--- a/lib/src/protobuf/extension.dart
+++ b/lib/src/protobuf/extension.dart
@@ -11,14 +11,18 @@
   Extension(this.extendee, String name, int tagNumber, int fieldType,
       [dynamic defaultOrMaker,
       CreateBuilderFunc subBuilder,
-      ValueOfFunc valueOf])
+      ValueOfFunc valueOf,
+      List<ProtobufEnum> enumValues])
       : super(name, tagNumber, null, fieldType, defaultOrMaker, subBuilder,
-            valueOf);
+            valueOf, enumValues);
 
   Extension.repeated(this.extendee, String name, int tagNumber, int fieldType,
-      CheckFunc<T> check, [CreateBuilderFunc subBuilder, ValueOfFunc valueOf])
-      : super.repeated(
-            name, tagNumber, null, fieldType, check, subBuilder, valueOf);
+      CheckFunc<T> check,
+      [CreateBuilderFunc subBuilder,
+      ValueOfFunc valueOf,
+      List<ProtobufEnum> enumValues])
+      : super.repeated(name, tagNumber, null, fieldType, check, subBuilder,
+            valueOf, enumValues);
 
   int get hashCode => extendee.hashCode * 31 + tagNumber;
 
diff --git a/lib/src/protobuf/field_error.dart b/lib/src/protobuf/field_error.dart
index 105999d..7644653 100644
--- a/lib/src/protobuf/field_error.dart
+++ b/lib/src/protobuf/field_error.dart
@@ -118,58 +118,58 @@
 
 // check functions for repeated fields
 
-void _checkNotNull(val) {
+void _checkNotNull(Object val) {
   if (val == null) {
     throw new ArgumentError("Can't add a null to a repeated field");
   }
 }
 
-void _checkBool(bool val) {
+void _checkBool(Object val) {
   if (val is! bool) throw _createFieldTypeError(val, 'a bool');
 }
 
-void _checkBytes(List<int> val) {
+void _checkBytes(Object val) {
   if (val is! List<int>) throw _createFieldTypeError(val, 'a List<int>');
 }
 
-void _checkString(String val) {
+void _checkString(Object val) {
   if (val is! String) throw _createFieldTypeError(val, 'a String');
 }
 
-void _checkFloat(double val) {
+void _checkFloat(Object val) {
   _checkDouble(val);
   if (!_isFloat32(val)) throw _createFieldRangeError(val, 'a float');
 }
 
-void _checkDouble(double val) {
+void _checkDouble(Object val) {
   if (val is! double) throw _createFieldTypeError(val, 'a double');
 }
 
-void _checkInt(int val) {
+void _checkInt(Object val) {
   if (val is! int) throw _createFieldTypeError(val, 'an int');
 }
 
-void _checkSigned32(int val) {
+void _checkSigned32(Object val) {
   _checkInt(val);
   if (!_isSigned32(val)) throw _createFieldRangeError(val, 'a signed int32');
 }
 
-void _checkUnsigned32(int val) {
+void _checkUnsigned32(Object val) {
   _checkInt(val);
   if (!_isUnsigned32(val)) {
     throw _createFieldRangeError(val, 'an unsigned int32');
   }
 }
 
-void _checkAnyInt64(Int64 val) {
+void _checkAnyInt64(Object val) {
   if (val is! Int64) throw _createFieldTypeError(val, 'an Int64');
 }
 
-void _checkAnyEnum(ProtobufEnum val) {
+void _checkAnyEnum(Object val) {
   if (val is! ProtobufEnum) throw _createFieldTypeError(val, 'a ProtobufEnum');
 }
 
-void _checkAnyMessage(GeneratedMessage val) {
+void _checkAnyMessage(Object val) {
   if (val is! GeneratedMessage) {
     throw _createFieldTypeError(val, 'a GeneratedMessage');
   }
diff --git a/lib/src/protobuf/field_info.dart b/lib/src/protobuf/field_info.dart
index cb195de..b036ddc 100644
--- a/lib/src/protobuf/field_info.dart
+++ b/lib/src/protobuf/field_info.dart
@@ -20,6 +20,10 @@
   // see GeneratedMessage._getEmptyMessage
   final CreateBuilderFunc subBuilder;
 
+  // List of all enum enumValues.
+  // (Not used for other types.)
+  final List<ProtobufEnum> enumValues;
+
   // Looks up the enum value given its integer code.
   // (Not used for other types.)
   // see GeneratedMessage._getValueOfFunc
@@ -30,7 +34,7 @@
   final CheckFunc<T> check;
 
   FieldInfo(this.name, this.tagNumber, this.index, int type,
-      [dynamic defaultOrMaker, this.subBuilder, this.valueOf])
+      [dynamic defaultOrMaker, this.subBuilder, this.valueOf, this.enumValues])
       : this.type = type,
         this.makeDefault = findMakeDefault(type, defaultOrMaker),
         this.check = null {
@@ -41,7 +45,7 @@
 
   FieldInfo.repeated(this.name, this.tagNumber, this.index, int type,
       this.check, this.subBuilder,
-      [this.valueOf])
+      [this.valueOf, this.enumValues])
       : this.type = type,
         this.makeDefault = (() => new PbList<T>(check: check)) {
     assert(name != null);
@@ -59,6 +63,8 @@
 
   bool get isRequired => _isRequired(type);
   bool get isRepeated => _isRepeated(type);
+  bool get isGroupOrMessage => _isGroupOrMessage(type);
+  bool get isEnum => _isEnum(type);
 
   /// Returns a read-only default value for a field.
   /// (Unlike getField, doesn't create a repeated field.)
@@ -79,7 +85,7 @@
       return message._fieldSet._hasRequiredValues();
     }
 
-    List list = value;
+    List<GeneratedMessage> list = value;
     if (list.isEmpty) return true;
 
     // For message types that (recursively) contain no required fields,
diff --git a/lib/src/protobuf/json.dart b/lib/src/protobuf/json.dart
index 4b4b99d..6c3afb1 100644
--- a/lib/src/protobuf/json.dart
+++ b/lib/src/protobuf/json.dart
@@ -85,7 +85,9 @@
 void _appendJsonList(
     _FieldSet fs, List json, FieldInfo fi, ExtensionRegistry registry) {
   List repeated = fs._ensureRepeatedField(fi);
-  for (var value in json) {
+  var length = json.length;
+  for (int i = 0; i < length; ++i) {
+    var value = json[i];
     var convertedValue =
         _convertJsonValue(fs, value, fi.tagNumber, fi.type, registry);
     if (convertedValue != null) {
diff --git a/pubspec.yaml b/pubspec.yaml
index 1aa480a..3b2adb9 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protobuf
-version: 0.5.6-dev
+version: 0.6.0
 author: Dart Team <misc@dartlang.org>
 description: Runtime library for protocol buffers support.
 homepage: https://github.com/dart-lang/protobuf