Generate better code for enum `valueOf` using correctly typed Map (#129)

Requires pkg:protobuf ^0.10.3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dfaa61f..e84701f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.10.3
+
+* Remove runtime `as` check of enum `valueOf` by using correctly typed `Map` of
+  values.
+  Generated files must require package:protobuf version 0.10.3 or newer.
+
 ## 0.10.2
 
 * Add link to source file in generated code.
diff --git a/lib/enum_generator.dart b/lib/enum_generator.dart
index 6fe88db..225cae6 100644
--- a/lib/enum_generator.dart
+++ b/lib/enum_generator.dart
@@ -89,10 +89,10 @@
       out.println('];');
       out.println();
 
-      out.println('static final Map<int, dynamic> _byValue ='
+      out.println('static final Map<int, $classname> _byValue ='
           ' $_protobufImportPrefix.ProtobufEnum.initByValue(values);');
       out.println('static ${classname} valueOf(int value) =>'
-          ' _byValue[value] as ${classname};');
+          ' _byValue[value];');
       out.addBlock('static void $checkItem($classname v) {', '}', () {
         out.println('if (v is! $classname)'
             " $_protobufImportPrefix.checkItemFailed(v, '$classname');");
diff --git a/lib/src/descriptor.pbenum.dart b/lib/src/descriptor.pbenum.dart
index b0c06b7..a25cda6 100644
--- a/lib/src/descriptor.pbenum.dart
+++ b/lib/src/descriptor.pbenum.dart
@@ -68,10 +68,9 @@
     TYPE_SINT64,
   ];
 
-  static final Map<int, dynamic> _byValue =
+  static final Map<int, FieldDescriptorProto_Type> _byValue =
       $pb.ProtobufEnum.initByValue(values);
-  static FieldDescriptorProto_Type valueOf(int value) =>
-      _byValue[value] as FieldDescriptorProto_Type;
+  static FieldDescriptorProto_Type valueOf(int value) => _byValue[value];
   static void $checkItem(FieldDescriptorProto_Type v) {
     if (v is! FieldDescriptorProto_Type)
       $pb.checkItemFailed(v, 'FieldDescriptorProto_Type');
@@ -95,10 +94,9 @@
     LABEL_REPEATED,
   ];
 
-  static final Map<int, dynamic> _byValue =
+  static final Map<int, FieldDescriptorProto_Label> _byValue =
       $pb.ProtobufEnum.initByValue(values);
-  static FieldDescriptorProto_Label valueOf(int value) =>
-      _byValue[value] as FieldDescriptorProto_Label;
+  static FieldDescriptorProto_Label valueOf(int value) => _byValue[value];
   static void $checkItem(FieldDescriptorProto_Label v) {
     if (v is! FieldDescriptorProto_Label)
       $pb.checkItemFailed(v, 'FieldDescriptorProto_Label');
@@ -122,10 +120,9 @@
     LITE_RUNTIME,
   ];
 
-  static final Map<int, dynamic> _byValue =
+  static final Map<int, FileOptions_OptimizeMode> _byValue =
       $pb.ProtobufEnum.initByValue(values);
-  static FileOptions_OptimizeMode valueOf(int value) =>
-      _byValue[value] as FileOptions_OptimizeMode;
+  static FileOptions_OptimizeMode valueOf(int value) => _byValue[value];
   static void $checkItem(FileOptions_OptimizeMode v) {
     if (v is! FileOptions_OptimizeMode)
       $pb.checkItemFailed(v, 'FileOptions_OptimizeMode');
@@ -147,10 +144,9 @@
     STRING_PIECE,
   ];
 
-  static final Map<int, dynamic> _byValue =
+  static final Map<int, FieldOptions_CType> _byValue =
       $pb.ProtobufEnum.initByValue(values);
-  static FieldOptions_CType valueOf(int value) =>
-      _byValue[value] as FieldOptions_CType;
+  static FieldOptions_CType valueOf(int value) => _byValue[value];
   static void $checkItem(FieldOptions_CType v) {
     if (v is! FieldOptions_CType) $pb.checkItemFailed(v, 'FieldOptions_CType');
   }
@@ -172,10 +168,9 @@
     JS_NUMBER,
   ];
 
-  static final Map<int, dynamic> _byValue =
+  static final Map<int, FieldOptions_JSType> _byValue =
       $pb.ProtobufEnum.initByValue(values);
-  static FieldOptions_JSType valueOf(int value) =>
-      _byValue[value] as FieldOptions_JSType;
+  static FieldOptions_JSType valueOf(int value) => _byValue[value];
   static void $checkItem(FieldOptions_JSType v) {
     if (v is! FieldOptions_JSType)
       $pb.checkItemFailed(v, 'FieldOptions_JSType');
@@ -199,10 +194,9 @@
     IDEMPOTENT,
   ];
 
-  static final Map<int, dynamic> _byValue =
+  static final Map<int, MethodOptions_IdempotencyLevel> _byValue =
       $pb.ProtobufEnum.initByValue(values);
-  static MethodOptions_IdempotencyLevel valueOf(int value) =>
-      _byValue[value] as MethodOptions_IdempotencyLevel;
+  static MethodOptions_IdempotencyLevel valueOf(int value) => _byValue[value];
   static void $checkItem(MethodOptions_IdempotencyLevel v) {
     if (v is! MethodOptions_IdempotencyLevel)
       $pb.checkItemFailed(v, 'MethodOptions_IdempotencyLevel');
diff --git a/pubspec.yaml b/pubspec.yaml
index 569cff6..d5ba45a 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protoc_plugin
-version: 0.10.2
+version: 0.10.3
 author: Dart Team <misc@dartlang.org>
 description: Protoc compiler plugin to generate Dart code
 homepage: https://github.com/dart-lang/dart-protoc-plugin
@@ -10,7 +10,7 @@
 dependencies:
   fixnum: ^0.10.5
   path: ^1.0.0
-  protobuf: ^0.10.2
+  protobuf: ^0.10.3
   dart_style: ^1.0.6
 
 dev_dependencies:
diff --git a/test/goldens/enum b/test/goldens/enum
index 3f6638a..40de719 100644
--- a/test/goldens/enum
+++ b/test/goldens/enum
@@ -11,8 +11,8 @@
     WORK,
   ];
 
-  static final Map<int, dynamic> _byValue = $pb.ProtobufEnum.initByValue(values);
-  static PhoneType valueOf(int value) => _byValue[value] as PhoneType;
+  static final Map<int, PhoneType> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static PhoneType valueOf(int value) => _byValue[value];
   static void $checkItem(PhoneType v) {
     if (v is! PhoneType) $pb.checkItemFailed(v, 'PhoneType');
   }
diff --git a/test/goldens/messageGeneratorEnums b/test/goldens/messageGeneratorEnums
index 217772d..157bfe1 100644
--- a/test/goldens/messageGeneratorEnums
+++ b/test/goldens/messageGeneratorEnums
@@ -11,8 +11,8 @@
     WORK,
   ];
 
-  static final Map<int, dynamic> _byValue = $pb.ProtobufEnum.initByValue(values);
-  static PhoneNumber_PhoneType valueOf(int value) => _byValue[value] as PhoneNumber_PhoneType;
+  static final Map<int, PhoneNumber_PhoneType> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static PhoneNumber_PhoneType valueOf(int value) => _byValue[value];
   static void $checkItem(PhoneNumber_PhoneType v) {
     if (v is! PhoneNumber_PhoneType) $pb.checkItemFailed(v, 'PhoneNumber_PhoneType');
   }
diff --git a/test/goldens/topLevelEnum.pbenum b/test/goldens/topLevelEnum.pbenum
index 147d13d..bb618eb 100644
--- a/test/goldens/topLevelEnum.pbenum
+++ b/test/goldens/topLevelEnum.pbenum
@@ -21,8 +21,8 @@
     WORK,
   ];
 
-  static final Map<int, dynamic> _byValue = $pb.ProtobufEnum.initByValue(values);
-  static PhoneType valueOf(int value) => _byValue[value] as PhoneType;
+  static final Map<int, PhoneType> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static PhoneType valueOf(int value) => _byValue[value];
   static void $checkItem(PhoneType v) {
     if (v is! PhoneType) $pb.checkItemFailed(v, 'PhoneType');
   }