Sync a few small CLs: (#1060)

- cl/660721933: moves some proto3 parsing functions to utils to allow reusing
  internally in a library when parsing an internal format.

- cl/646759129: Update `CodedBufferReader` default depth limit to 100, to be
  consistent with the C++ and Java implementations.

- cl/704280814: Update `CodedBufferReader` default size limit to max 32-bit
  signed integer to be consistent with the C++, Java, Objective-C
  implementations.

- Also a minor change, not a CL: Type casts in `coded_buffer_writer.dart` was
  updated in this repo probably accidentally, as we never want to type cast
  with `as` in this repo. Revert it to the internal version which uses implicit
  casts.

With this, about half of the protobuf files become identical with the internal
version.
diff --git a/protobuf/CHANGELOG.md b/protobuf/CHANGELOG.md
index 2874f12..5b911ad 100644
--- a/protobuf/CHANGELOG.md
+++ b/protobuf/CHANGELOG.md
@@ -1,3 +1,12 @@
+## 5.1.0-wip
+
+* Update default size limit of `CodedBufferReader` from 67,108,864 bytes to
+  2,147,483,647 bytes, and default recursion limit from 64 to 100.
+
+  The new limits are consistent with the Java and C++ implementations. ([#1060])
+
+[#1060]: https://github.com/google/protobuf.dart/pull/1060
+
 ## 5.0.0
 
 * Improve performance of `GeneratedMessage.deepCopy`. ([#742])
diff --git a/protobuf/lib/src/protobuf/coded_buffer_reader.dart b/protobuf/lib/src/protobuf/coded_buffer_reader.dart
index bb1f585..28d2699 100644
--- a/protobuf/lib/src/protobuf/coded_buffer_reader.dart
+++ b/protobuf/lib/src/protobuf/coded_buffer_reader.dart
@@ -8,9 +8,10 @@
 /// [GeneratedMessage]s.
 class CodedBufferReader {
   // ignore: constant_identifier_names
-  static const int DEFAULT_RECURSION_LIMIT = 64;
+  static const int DEFAULT_RECURSION_LIMIT = 100;
+  // Maximum value of a 32-bit signed integer.
   // ignore: constant_identifier_names
-  static const int DEFAULT_SIZE_LIMIT = 64 << 20;
+  static const int DEFAULT_SIZE_LIMIT = (1 << 31) - 1;
 
   final Uint8List _buffer;
 
diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart
index a01e633..8d0e198 100644
--- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart
+++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart
@@ -64,11 +64,11 @@
     _commitChunk(true);
   }
 
-  void writeField(int fieldNumber, int fieldType, Object? fieldValue) {
+  void writeField(int fieldNumber, int fieldType, dynamic fieldValue) {
     final valueType = PbFieldType.baseType(fieldType);
 
     if ((fieldType & PbFieldType.PACKED_BIT) != 0) {
-      final list = fieldValue as List;
+      final List list = fieldValue;
       if (list.isNotEmpty) {
         _writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
         final mark = _startLengthDelimited();
@@ -81,7 +81,7 @@
     }
 
     if ((fieldType & PbFieldType.MAP_BIT) != 0) {
-      final map = fieldValue as PbMap;
+      final PbMap map = fieldValue;
       final keyWireFormat = _wireTypes[_valueTypeIndex(map.keyFieldType)];
       final valueWireFormat = _wireTypes[_valueTypeIndex(map.valueFieldType)];
 
@@ -108,7 +108,7 @@
     final wireFormat = _wireTypes[_valueTypeIndex(valueType)];
 
     if ((fieldType & PbFieldType.REPEATED_BIT) != 0) {
-      final list = fieldValue as List;
+      final List list = fieldValue;
       for (var i = 0; i < list.length; i++) {
         _writeValue(fieldNumber, valueType, list[i], wireFormat);
       }
diff --git a/protobuf/lib/src/protobuf/exceptions.dart b/protobuf/lib/src/protobuf/exceptions.dart
index f55e9be..cb1852d 100644
--- a/protobuf/lib/src/protobuf/exceptions.dart
+++ b/protobuf/lib/src/protobuf/exceptions.dart
@@ -35,7 +35,8 @@
   InvalidProtocolBufferException.recursionLimitExceeded()
     : this._('''
 Protocol message had too many levels of nesting. May be malicious.
-Use CodedBufferReader.setRecursionLimit() to increase the depth limit.
+Use a CodedBufferReader with a defined recursion depth limit if you need to
+parse deeply nested messages.
 ''');
 
   InvalidProtocolBufferException.truncatedMessage()
diff --git a/protobuf/lib/src/protobuf/field_type.dart b/protobuf/lib/src/protobuf/field_type.dart
index 67b3194..ea08419 100644
--- a/protobuf/lib/src/protobuf/field_type.dart
+++ b/protobuf/lib/src/protobuf/field_type.dart
@@ -7,23 +7,18 @@
 
 /// Defines constants and functions for dealing with fieldType bits.
 class PbFieldType {
-  static bool isRepeated(int fieldType) =>
-      (fieldType & PbFieldType.REPEATED_BIT) != 0;
+  static bool isRepeated(int fieldType) => (fieldType & REPEATED_BIT) != 0;
 
-  static bool isRequired(int fieldType) =>
-      (fieldType & PbFieldType.REQUIRED_BIT) != 0;
+  static bool isRequired(int fieldType) => (fieldType & REQUIRED_BIT) != 0;
 
-  static bool isEnum(int fieldType) =>
-      PbFieldType.baseType(fieldType) == PbFieldType.ENUM_BIT;
+  static bool isEnum(int fieldType) => baseType(fieldType) == ENUM_BIT;
 
-  static bool isBytes(int fieldType) =>
-      PbFieldType.baseType(fieldType) == PbFieldType.BYTES_BIT;
+  static bool isBytes(int fieldType) => baseType(fieldType) == BYTES_BIT;
 
   static bool isGroupOrMessage(int fieldType) =>
-      (fieldType & (PbFieldType.GROUP_BIT | PbFieldType.MESSAGE_BIT)) != 0;
+      (fieldType & (GROUP_BIT | MESSAGE_BIT)) != 0;
 
-  static bool isMapField(int fieldType) =>
-      (fieldType & PbFieldType.MAP_BIT) != 0;
+  static bool isMapField(int fieldType) => (fieldType & MAP_BIT) != 0;
 
   /// Returns the base field type without any of the required, repeated
   /// and packed bits.
@@ -176,6 +171,7 @@
   static const int PACKED_SFIXED64 = REPEATED_BIT | PACKED_BIT | SFIXED64_BIT;
 
   static const int MAP = MAP_BIT | MESSAGE_BIT;
+
   // Short names for use in generated code.
 
   // _O_ptional.
diff --git a/protobuf/lib/src/protobuf/proto3_json.dart b/protobuf/lib/src/protobuf/proto3_json.dart
index 760f873..5da0531 100644
--- a/protobuf/lib/src/protobuf/proto3_json.dart
+++ b/protobuf/lib/src/protobuf/proto3_json.dart
@@ -191,33 +191,6 @@
   return result;
 }
 
-int _tryParse32BitProto3(String s, JsonParsingContext context) {
-  return int.tryParse(s) ??
-      (throw context.parseException('expected integer', s));
-}
-
-int _check32BitSignedProto3(int n, JsonParsingContext context) {
-  if (n < -2147483648 || n > 2147483647) {
-    throw context.parseException('expected 32 bit signed integer', n);
-  }
-  return n;
-}
-
-int _check32BitUnsignedProto3(int n, JsonParsingContext context) {
-  if (n < 0 || n > 0xFFFFFFFF) {
-    throw context.parseException('expected 32 bit unsigned integer', n);
-  }
-  return n;
-}
-
-Int64 _tryParse64BitProto3(Object? json, String s, JsonParsingContext context) {
-  try {
-    return Int64.parseInt(s);
-  } on FormatException {
-    throw context.parseException('expected integer', json);
-  }
-}
-
 /// TODO(paulberry): find a better home for this?
 extension _FindFirst<E> on Iterable<E> {
   E? findFirst(bool Function(E) test) {
@@ -384,14 +357,14 @@
           if (value is int) {
             result = value;
           } else if (value is String) {
-            result = _tryParse32BitProto3(value, context);
+            result = Proto3ParseUtils.tryParse32Bit(value, context);
           } else {
             throw context.parseException(
               'Expected int or stringified int',
               value,
             );
           }
-          return _check32BitUnsignedProto3(result, context);
+          return Proto3ParseUtils.check32BitUnsigned(result, context);
         case PbFieldType.INT32_BIT:
         case PbFieldType.SINT32_BIT:
         case PbFieldType.SFIXED32_BIT:
@@ -399,21 +372,21 @@
           if (value is int) {
             result = value;
           } else if (value is String) {
-            result = _tryParse32BitProto3(value, context);
+            result = Proto3ParseUtils.tryParse32Bit(value, context);
           } else {
             throw context.parseException(
               'Expected int or stringified int',
               value,
             );
           }
-          _check32BitSignedProto3(result, context);
+          Proto3ParseUtils.check32BitSigned(result, context);
           return result;
         case PbFieldType.UINT64_BIT:
           Int64 result;
           if (value is int) {
             result = Int64(value);
           } else if (value is String) {
-            result = _tryParse64BitProto3(json, value, context);
+            result = Proto3ParseUtils.tryParse64Bit(json, value, context);
           } else {
             throw context.parseException(
               'Expected int or stringified int',
@@ -469,23 +442,23 @@
         case PbFieldType.UINT64_BIT:
           // TODO(sigurdm): We do not throw on negative values here.
           // That would probably require going via bignum.
-          return _tryParse64BitProto3(json, key, context);
+          return Proto3ParseUtils.tryParse64Bit(json, key, context);
         case PbFieldType.INT64_BIT:
         case PbFieldType.SINT64_BIT:
         case PbFieldType.SFIXED64_BIT:
         case PbFieldType.FIXED64_BIT:
-          return _tryParse64BitProto3(json, key, context);
+          return Proto3ParseUtils.tryParse64Bit(json, key, context);
         case PbFieldType.INT32_BIT:
         case PbFieldType.SINT32_BIT:
         case PbFieldType.FIXED32_BIT:
         case PbFieldType.SFIXED32_BIT:
-          return _check32BitSignedProto3(
-            _tryParse32BitProto3(key, context),
+          return Proto3ParseUtils.check32BitSigned(
+            Proto3ParseUtils.tryParse32Bit(key, context),
             context,
           );
         case PbFieldType.UINT32_BIT:
-          return _check32BitUnsignedProto3(
-            _tryParse32BitProto3(key, context),
+          return Proto3ParseUtils.check32BitUnsigned(
+            Proto3ParseUtils.tryParse32Bit(key, context),
             context,
           );
         default:
diff --git a/protobuf/lib/src/protobuf/utils.dart b/protobuf/lib/src/protobuf/utils.dart
index b4bb8bc..7de5c1e 100644
--- a/protobuf/lib/src/protobuf/utils.dart
+++ b/protobuf/lib/src/protobuf/utils.dart
@@ -2,7 +2,10 @@
 // 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.
 
+import 'package:fixnum/fixnum.dart' show Int64;
+
 import 'internal.dart';
+import 'json_parsing_context.dart';
 
 // TODO(antonm): reconsider later if PbList should take care of equality.
 bool deepEquals(Object lhs, Object rhs) {
@@ -53,3 +56,36 @@
   static int hash2(dynamic a, dynamic b) =>
       _finish(combine(combine(0, a.hashCode), b.hashCode));
 }
+
+class Proto3ParseUtils {
+  static int tryParse32Bit(String s, JsonParsingContext context) {
+    return int.tryParse(s) ??
+        (throw context.parseException('expected integer', s));
+  }
+
+  static int check32BitSigned(int n, JsonParsingContext context) {
+    if (n < -2147483648 || n > 2147483647) {
+      throw context.parseException('expected 32 bit signed integer', n);
+    }
+    return n;
+  }
+
+  static int check32BitUnsigned(int n, JsonParsingContext context) {
+    if (n < 0 || n > 0xFFFFFFFF) {
+      throw context.parseException('expected 32 bit unsigned integer', n);
+    }
+    return n;
+  }
+
+  static Int64 tryParse64Bit(
+    Object? json,
+    String s,
+    JsonParsingContext context,
+  ) {
+    try {
+      return Int64.parseInt(s);
+    } on FormatException {
+      throw context.parseException('expected integer', json);
+    }
+  }
+}
diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml
index 162dadc..84b70d0 100644
--- a/protobuf/pubspec.yaml
+++ b/protobuf/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protobuf
-version: 5.0.0
+version: 5.1.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/generated_message_test.dart b/protoc_plugin/test/generated_message_test.dart
index 1a769a3..1f62b9e 100644
--- a/protoc_plugin/test/generated_message_test.dart
+++ b/protoc_plugin/test/generated_message_test.dart
@@ -268,16 +268,27 @@
       }
     }
 
-    final List<int> data64 = makeRecursiveMessage(64).writeToBuffer();
-    final List<int> data65 = makeRecursiveMessage(65).writeToBuffer();
+    // Message with exactly `DEFAULT_RECURSION_LIMIT` levels of nesting.
+    final List<int> dataShallow =
+        makeRecursiveMessage(
+          CodedBufferReader.DEFAULT_RECURSION_LIMIT,
+        ).writeToBuffer();
+    // Message with more than `DEFAULT_RECURSION_LIMIT` levels of nesting.
+    final List<int> dataDeep =
+        makeRecursiveMessage(
+          CodedBufferReader.DEFAULT_RECURSION_LIMIT + 1,
+        ).writeToBuffer();
 
-    assertMessageDepth(TestRecursiveMessage.fromBuffer(data64), 64);
+    assertMessageDepth(
+      TestRecursiveMessage.fromBuffer(dataShallow),
+      CodedBufferReader.DEFAULT_RECURSION_LIMIT,
+    );
 
     expect(() {
-      TestRecursiveMessage.fromBuffer(data65);
+      TestRecursiveMessage.fromBuffer(dataDeep);
     }, throwsInvalidProtocolBufferException);
 
-    final input = CodedBufferReader(data64, recursionLimit: 8);
+    final input = CodedBufferReader(dataShallow, recursionLimit: 8);
     expect(() {
       // Uncomfortable alternative to below...
       TestRecursiveMessage().mergeFromCodedBufferReader(input);