Remove defunct Reader and Writer interfaces from JavaProto

These interfaces were part of the experimental runtime, and before this change have exactly one concrete implementation each. This CL simply deletes the interfaces and inlines the corresponding concrete type wherever they were named.

PiperOrigin-RevId: 930019405
diff --git a/java/core/BUILD.bazel b/java/core/BUILD.bazel
index 13d6513..4bd8a4e 100644
--- a/java/core/BUILD.bazel
+++ b/java/core/BUILD.bazel
@@ -89,7 +89,6 @@
     "src/main/java/com/google/protobuf/ProtobufArrayList.java",
     "src/main/java/com/google/protobuf/ProtocolStringList.java",
     "src/main/java/com/google/protobuf/RawMessageInfo.java",
-    "src/main/java/com/google/protobuf/Reader.java",
     "src/main/java/com/google/protobuf/RopeByteString.java",
     "src/main/java/com/google/protobuf/RuntimeVersion.java",
     "src/main/java/com/google/protobuf/Schema.java",
@@ -106,7 +105,6 @@
     "src/main/java/com/google/protobuf/UnsafeUtil.java",
     "src/main/java/com/google/protobuf/Utf8.java",
     "src/main/java/com/google/protobuf/WireFormat.java",
-    "src/main/java/com/google/protobuf/Writer.java",
 ]
 
 FULL_SRCS = glob(
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java b/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java
index c7a4eb5..0366532 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java
@@ -20,10 +20,11 @@
 import java.util.List;
 import java.util.Map;
 
-/** An adapter between the {@link Reader} interface and {@link CodedInputStream}. */
+/** A reader of fields from a serialized protobuf message. */
 @CheckReturnValue
 @ExperimentalApi
-final class CodedInputStreamReader implements Reader {
+final class CodedInputStreamReader {
+  static final int READ_DONE = Integer.MAX_VALUE;
   private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1;
   private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1;
   private static final int NEXT_TAG_UNSET = 0;
@@ -45,12 +46,10 @@
     this.input.wrapper = this;
   }
 
-  @Override
   public boolean shouldDiscardUnknownFields() {
     return input.shouldDiscardUnknownFields();
   }
 
-  @Override
   public int getFieldNumber() throws IOException {
     if (nextTag != NEXT_TAG_UNSET) {
       tag = nextTag;
@@ -59,17 +58,15 @@
       tag = input.readTag();
     }
     if (tag == 0 || tag == endGroupTag) {
-      return Reader.READ_DONE;
+      return READ_DONE;
     }
     return WireFormat.getTagFieldNumber(tag);
   }
 
-  @Override
   public int getTag() {
     return tag;
   }
 
-  @Override
   public boolean skipField() throws IOException {
     if (input.isAtEnd() || tag == endGroupTag) {
       return false;
@@ -83,68 +80,57 @@
     }
   }
 
-  @Override
   public double readDouble() throws IOException {
     requireWireType(WIRETYPE_FIXED64);
     return input.readDouble();
   }
 
-  @Override
   public float readFloat() throws IOException {
     requireWireType(WIRETYPE_FIXED32);
     return input.readFloat();
   }
 
-  @Override
   public long readUInt64() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readUInt64();
   }
 
-  @Override
   public long readInt64() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readInt64();
   }
 
-  @Override
   public int readInt32() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readInt32();
   }
 
-  @Override
   public long readFixed64() throws IOException {
     requireWireType(WIRETYPE_FIXED64);
     return input.readFixed64();
   }
 
-  @Override
   public int readFixed32() throws IOException {
     requireWireType(WIRETYPE_FIXED32);
     return input.readFixed32();
   }
 
-  @Override
   public boolean readBool() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readBool();
   }
 
-  @Override
   public String readString() throws IOException {
     requireWireType(WIRETYPE_LENGTH_DELIMITED);
     return input.readString();
   }
 
-  @Override
   public String readStringRequireUtf8() throws IOException {
     requireWireType(WIRETYPE_LENGTH_DELIMITED);
     return input.readStringRequireUtf8();
   }
 
   @SuppressWarnings("unchecked")
-  @Override
   public <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
       throws IOException {
     requireWireType(WIRETYPE_LENGTH_DELIMITED);
@@ -153,7 +139,6 @@
   }
 
   @SuppressWarnings("unchecked")
-  @Override
   public <T> T readMessageBySchemaWithCheck(
       Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
     requireWireType(WIRETYPE_LENGTH_DELIMITED);
@@ -162,7 +147,6 @@
 
   @SuppressWarnings("unchecked")
   @Deprecated
-  @Override
   public <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
       throws IOException {
     requireWireType(WIRETYPE_START_GROUP);
@@ -171,14 +155,12 @@
   }
 
   @Deprecated
-  @Override
   public <T> T readGroupBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
       throws IOException {
     requireWireType(WIRETYPE_START_GROUP);
     return readGroup(schema, extensionRegistry);
   }
 
-  @Override
   public <T> void mergeMessageField(
       T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
     requireWireType(WIRETYPE_LENGTH_DELIMITED);
@@ -209,7 +191,6 @@
     return newInstance;
   }
 
-  @Override
   public <T> void mergeGroupField(
       T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
     requireWireType(WIRETYPE_START_GROUP);
@@ -240,49 +221,41 @@
     return newInstance;
   }
 
-  @Override
   public ByteString readBytes() throws IOException {
     requireWireType(WIRETYPE_LENGTH_DELIMITED);
     return input.readBytes();
   }
 
-  @Override
   public int readUInt32() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readUInt32();
   }
 
-  @Override
   public int readEnum() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readEnum();
   }
 
-  @Override
   public int readSFixed32() throws IOException {
     requireWireType(WIRETYPE_FIXED32);
     return input.readSFixed32();
   }
 
-  @Override
   public long readSFixed64() throws IOException {
     requireWireType(WIRETYPE_FIXED64);
     return input.readSFixed64();
   }
 
-  @Override
   public int readSInt32() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readSInt32();
   }
 
-  @Override
   public long readSInt64() throws IOException {
     requireWireType(WIRETYPE_VARINT);
     return input.readSInt64();
   }
 
-  @Override
   public void readDoubleList(List<Double> target) throws IOException {
     if (target instanceof DoubleArrayList) {
       DoubleArrayList plist = (DoubleArrayList) target;
@@ -340,7 +313,6 @@
     }
   }
 
-  @Override
   public void readFloatList(List<Float> target) throws IOException {
     if (target instanceof FloatArrayList) {
       FloatArrayList plist = (FloatArrayList) target;
@@ -398,7 +370,6 @@
     }
   }
 
-  @Override
   public void readUInt64List(List<Long> target) throws IOException {
     if (target instanceof LongArrayList) {
       LongArrayList plist = (LongArrayList) target;
@@ -456,7 +427,6 @@
     }
   }
 
-  @Override
   public void readInt64List(List<Long> target) throws IOException {
     if (target instanceof LongArrayList) {
       LongArrayList plist = (LongArrayList) target;
@@ -514,7 +484,6 @@
     }
   }
 
-  @Override
   public void readInt32List(List<Integer> target) throws IOException {
     if (target instanceof IntArrayList) {
       IntArrayList plist = (IntArrayList) target;
@@ -572,7 +541,6 @@
     }
   }
 
-  @Override
   public void readFixed64List(List<Long> target) throws IOException {
     if (target instanceof LongArrayList) {
       LongArrayList plist = (LongArrayList) target;
@@ -630,7 +598,6 @@
     }
   }
 
-  @Override
   public void readFixed32List(List<Integer> target) throws IOException {
     if (target instanceof IntArrayList) {
       IntArrayList plist = (IntArrayList) target;
@@ -688,7 +655,6 @@
     }
   }
 
-  @Override
   public void readBoolList(List<Boolean> target) throws IOException {
     if (target instanceof BooleanArrayList) {
       BooleanArrayList plist = (BooleanArrayList) target;
@@ -746,12 +712,10 @@
     }
   }
 
-  @Override
   public void readStringList(List<String> target) throws IOException {
     readStringListInternal(target, false);
   }
 
-  @Override
   public void readStringListRequireUtf8(List<String> target) throws IOException {
     readStringListInternal(target, true);
   }
@@ -792,7 +756,6 @@
   }
 
   @SuppressWarnings("unchecked")
-  @Override
   public <T> void readMessageList(
       List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
       throws IOException {
@@ -800,7 +763,6 @@
     readMessageList(target, schema, extensionRegistry);
   }
 
-  @Override
   public <T> void readMessageList(
       List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
       throws IOException {
@@ -824,7 +786,6 @@
 
   @SuppressWarnings("unchecked")
   @Deprecated
-  @Override
   public <T> void readGroupList(
       List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
       throws IOException {
@@ -833,7 +794,6 @@
   }
 
   @Deprecated
-  @Override
   public <T> void readGroupList(
       List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
       throws IOException {
@@ -855,7 +815,6 @@
     }
   }
 
-  @Override
   public void readBytesList(List<ByteString> target) throws IOException {
     if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
       throw InvalidProtocolBufferException.invalidWireType();
@@ -875,7 +834,6 @@
     }
   }
 
-  @Override
   public void readUInt32List(List<Integer> target) throws IOException {
     if (target instanceof IntArrayList) {
       IntArrayList plist = (IntArrayList) target;
@@ -933,7 +891,6 @@
     }
   }
 
-  @Override
   public void readEnumList(List<Integer> target) throws IOException {
     if (target instanceof IntArrayList) {
       IntArrayList plist = (IntArrayList) target;
@@ -991,7 +948,6 @@
     }
   }
 
-  @Override
   public void readSFixed32List(List<Integer> target) throws IOException {
     if (target instanceof IntArrayList) {
       IntArrayList plist = (IntArrayList) target;
@@ -1049,7 +1005,6 @@
     }
   }
 
-  @Override
   public void readSFixed64List(List<Long> target) throws IOException {
     if (target instanceof LongArrayList) {
       LongArrayList plist = (LongArrayList) target;
@@ -1107,7 +1062,6 @@
     }
   }
 
-  @Override
   public void readSInt32List(List<Integer> target) throws IOException {
     if (target instanceof IntArrayList) {
       IntArrayList plist = (IntArrayList) target;
@@ -1165,7 +1119,6 @@
     }
   }
 
-  @Override
   public void readSInt64List(List<Long> target) throws IOException {
     if (target instanceof LongArrayList) {
       LongArrayList plist = (LongArrayList) target;
@@ -1231,7 +1184,6 @@
   }
 
   @SuppressWarnings("unchecked")
-  @Override
   public <K, V> void readMap(
       Map<K, V> target,
       MapEntryLite.Metadata<K, V> metadata,
diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java
index 54b9719..2be1f72 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java
@@ -15,11 +15,11 @@
 import java.util.List;
 import java.util.Map;
 
-/** An adapter between the {@link Writer} interface and {@link CodedOutputStream}. */
+/** A writer that performs serialization of protobuf message fields. */
 @CheckReturnValue
 @ExperimentalApi
 @SuppressWarnings({"unchecked", "rawtypes"})
-final class CodedOutputStreamWriter implements Writer {
+final class CodedOutputStreamWriter {
   private final CodedOutputStream output;
 
   public static CodedOutputStreamWriter forCodedOutput(CodedOutputStream output) {
@@ -37,94 +37,59 @@
   public int getTotalBytesWritten() {
     return output.getTotalBytesWritten();
   }
-
-  @Override
   public void writeSFixed32(int fieldNumber, int value) throws IOException {
     output.writeSFixed32(fieldNumber, value);
   }
-
-  @Override
   public void writeInt64(int fieldNumber, long value) throws IOException {
     output.writeInt64(fieldNumber, value);
   }
-
-  @Override
   public void writeSFixed64(int fieldNumber, long value) throws IOException {
     output.writeSFixed64(fieldNumber, value);
   }
-
-  @Override
   public void writeFloat(int fieldNumber, float value) throws IOException {
     output.writeFloat(fieldNumber, value);
   }
-
-  @Override
   public void writeDouble(int fieldNumber, double value) throws IOException {
     output.writeDouble(fieldNumber, value);
   }
-
-  @Override
   public void writeEnum(int fieldNumber, int value) throws IOException {
     output.writeEnum(fieldNumber, value);
   }
-
-  @Override
   public void writeUInt64(int fieldNumber, long value) throws IOException {
     output.writeUInt64(fieldNumber, value);
   }
-
-  @Override
   public void writeInt32(int fieldNumber, int value) throws IOException {
     output.writeInt32(fieldNumber, value);
   }
-
-  @Override
   public void writeFixed64(int fieldNumber, long value) throws IOException {
     output.writeFixed64(fieldNumber, value);
   }
-
-  @Override
   public void writeFixed32(int fieldNumber, int value) throws IOException {
     output.writeFixed32(fieldNumber, value);
   }
-
-  @Override
   public void writeBool(int fieldNumber, boolean value) throws IOException {
     output.writeBool(fieldNumber, value);
   }
-
-  @Override
   public void writeString(int fieldNumber, String value) throws IOException {
     output.writeString(fieldNumber, value);
   }
-
-  @Override
   public void writeBytes(int fieldNumber, ByteString value) throws IOException {
     output.writeBytes(fieldNumber, value);
   }
-
-  @Override
   public void writeUInt32(int fieldNumber, int value) throws IOException {
     output.writeUInt32(fieldNumber, value);
   }
-
-  @Override
   public void writeSInt32(int fieldNumber, int value) throws IOException {
     output.writeSInt32(fieldNumber, value);
   }
-
-  @Override
   public void writeSInt64(int fieldNumber, long value) throws IOException {
     output.writeSInt64(fieldNumber, value);
   }
-
-  @Override
   public void writeMessage(int fieldNumber, Object value) throws IOException {
     output.writeMessage(fieldNumber, (MessageLite) value);
   }
 
   @SuppressWarnings({"unchecked", "rawtypes"})
-  @Override
   public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
     AbstractMessageLite<?, ?> message = (AbstractMessageLite) value;
     output.writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
@@ -133,13 +98,11 @@
   }
 
   @Deprecated
-  @Override
   public void writeGroup(int fieldNumber, Object value) throws IOException {
     output.writeGroup(fieldNumber, (MessageLite) value);
   }
 
   @SuppressWarnings({"unchecked", "rawtypes"})
-  @Override
   public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
     AbstractMessageLite<?, ?> message = (AbstractMessageLite) value;
     output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
@@ -148,18 +111,14 @@
   }
 
   @Deprecated
-  @Override
   public void writeStartGroup(int fieldNumber) throws IOException {
     output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
   }
 
   @Deprecated
-  @Override
   public void writeEndGroup(int fieldNumber) throws IOException {
     output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
   }
-
-  @Override
   public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException {
     if (value instanceof ByteString) {
       output.writeRawMessageSetExtension(fieldNumber, (ByteString) value);
@@ -167,8 +126,6 @@
       output.writeMessageSetExtension(fieldNumber, (MessageLite) value);
     }
   }
-
-  @Override
   public void writeInt32List(int fieldNumber, List<Integer> value, boolean packed)
       throws IOException {
     if (value instanceof IntArrayList) {
@@ -223,8 +180,6 @@
       }
     }
   }
-
-  @Override
   public void writeFixed32List(int fieldNumber, List<Integer> value, boolean packed)
       throws IOException {
     if (value instanceof IntArrayList) {
@@ -279,8 +234,6 @@
       }
     }
   }
-
-  @Override
   public void writeInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException {
     if (value instanceof LongArrayList) {
       writeInt64ListInternal(fieldNumber, (LongArrayList) value, packed);
@@ -334,8 +287,6 @@
       }
     }
   }
-
-  @Override
   public void writeUInt64List(int fieldNumber, List<Long> value, boolean packed)
       throws IOException {
     if (value instanceof LongArrayList) {
@@ -390,8 +341,6 @@
       }
     }
   }
-
-  @Override
   public void writeFixed64List(int fieldNumber, List<Long> value, boolean packed)
       throws IOException {
     if (value instanceof LongArrayList) {
@@ -446,8 +395,6 @@
       }
     }
   }
-
-  @Override
   public void writeFloatList(int fieldNumber, List<Float> value, boolean packed)
       throws IOException {
     if (value instanceof FloatArrayList) {
@@ -502,8 +449,6 @@
       }
     }
   }
-
-  @Override
   public void writeDoubleList(int fieldNumber, List<Double> value, boolean packed)
       throws IOException {
     if (value instanceof DoubleArrayList) {
@@ -558,8 +503,6 @@
       }
     }
   }
-
-  @Override
   public void writeEnumList(int fieldNumber, List<Integer> value, boolean packed)
       throws IOException {
     if (value instanceof IntArrayList) {
@@ -614,8 +557,6 @@
       }
     }
   }
-
-  @Override
   public void writeBoolList(int fieldNumber, List<Boolean> value, boolean packed)
       throws IOException {
     if (value instanceof BooleanArrayList) {
@@ -670,8 +611,6 @@
       }
     }
   }
-
-  @Override
   public void writeStringList(int fieldNumber, List<String> value) throws IOException {
     if (value instanceof LazyStringList) {
       final LazyStringList lazyList = (LazyStringList) value;
@@ -692,15 +631,11 @@
       output.writeBytes(fieldNumber, (ByteString) value);
     }
   }
-
-  @Override
   public void writeBytesList(int fieldNumber, List<ByteString> value) throws IOException {
     for (int i = 0; i < value.size(); ++i) {
       output.writeBytes(fieldNumber, value.get(i));
     }
   }
-
-  @Override
   public void writeUInt32List(int fieldNumber, List<Integer> value, boolean packed)
       throws IOException {
     if (value instanceof IntArrayList) {
@@ -755,8 +690,6 @@
       }
     }
   }
-
-  @Override
   public void writeSFixed32List(int fieldNumber, List<Integer> value, boolean packed)
       throws IOException {
     if (value instanceof IntArrayList) {
@@ -811,8 +744,6 @@
       }
     }
   }
-
-  @Override
   public void writeSFixed64List(int fieldNumber, List<Long> value, boolean packed)
       throws IOException {
     if (value instanceof LongArrayList) {
@@ -867,8 +798,6 @@
       }
     }
   }
-
-  @Override
   public void writeSInt32List(int fieldNumber, List<Integer> value, boolean packed)
       throws IOException {
     if (value instanceof IntArrayList) {
@@ -923,8 +852,6 @@
       }
     }
   }
-
-  @Override
   public void writeSInt64List(int fieldNumber, List<Long> value, boolean packed)
       throws IOException {
     if (value instanceof LongArrayList) {
@@ -979,15 +906,11 @@
       }
     }
   }
-
-  @Override
   public void writeMessageList(int fieldNumber, List<?> value) throws IOException {
     for (int i = 0; i < value.size(); ++i) {
       writeMessage(fieldNumber, value.get(i));
     }
   }
-
-  @Override
   public void writeMessageList(int fieldNumber, List<?> value, Schema schema) throws IOException {
     for (int i = 0; i < value.size(); ++i) {
       writeMessage(fieldNumber, value.get(i), schema);
@@ -995,21 +918,16 @@
   }
 
   @Deprecated
-  @Override
   public void writeGroupList(int fieldNumber, List<?> value) throws IOException {
     for (int i = 0; i < value.size(); ++i) {
       writeGroup(fieldNumber, value.get(i));
     }
   }
-
-  @Override
   public void writeGroupList(int fieldNumber, List<?> value, Schema schema) throws IOException {
     for (int i = 0; i < value.size(); ++i) {
       writeGroup(fieldNumber, value.get(i), schema);
     }
   }
-
-  @Override
   public <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)
       throws IOException {
     if (output.isSerializationDeterministic()) {
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java
index 3b21d7f..1524235 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java
@@ -38,7 +38,7 @@
    */
   abstract <UT, UB> UB parseExtension(
       Object containerMessage,
-      Reader reader,
+      CodedInputStreamReader reader,
       Object extension,
       ExtensionRegistryLite extensionRegistry,
       FieldSet<T> extensions,
@@ -50,7 +50,8 @@
   abstract int extensionNumber(Map.Entry<?, ?> extension);
 
   /** Serializes one extension entry. */
-  abstract void serializeExtension(Writer writer, Map.Entry<?, ?> extension) throws IOException;
+  abstract void serializeExtension(CodedOutputStreamWriter writer, Map.Entry<?, ?> extension)
+      throws IOException;
 
   /** Finds an extension by field number. */
   abstract Object findExtensionByNumber(
@@ -58,7 +59,7 @@
 
   /** Parses a length-prefixed MessageSet item from the reader. */
   abstract void parseLengthPrefixedMessageSetItem(
-      Reader reader,
+      CodedInputStreamReader reader,
       Object extension,
       ExtensionRegistryLite extensionRegistry,
       FieldSet<T> extensions)
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java
index 40975c1..8d70799 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java
@@ -45,7 +45,7 @@
   @Override
   <UT, UB> UB parseExtension(
       Object containerMessage,
-      Reader reader,
+      CodedInputStreamReader reader,
       Object extensionObject,
       ExtensionRegistryLite extensionRegistry,
       FieldSet<ExtensionDescriptor> extensions,
@@ -312,7 +312,8 @@
   }
 
   @Override
-  void serializeExtension(Writer writer, Map.Entry<?, ?> extension) throws IOException {
+  void serializeExtension(CodedOutputStreamWriter writer, Map.Entry<?, ?> extension)
+      throws IOException {
     GeneratedMessageLite.ExtensionDescriptor descriptor =
         (GeneratedMessageLite.ExtensionDescriptor) extension.getKey();
     if (descriptor.isRepeated()) {
@@ -526,7 +527,7 @@
 
   @Override
   void parseLengthPrefixedMessageSetItem(
-      Reader reader,
+      CodedInputStreamReader reader,
       Object extensionObject,
       ExtensionRegistryLite extensionRegistry,
       FieldSet<ExtensionDescriptor> extensions)
diff --git a/java/core/src/main/java/com/google/protobuf/InternalLazyField.java b/java/core/src/main/java/com/google/protobuf/InternalLazyField.java
index 40944e2..81b106a 100644
--- a/java/core/src/main/java/com/google/protobuf/InternalLazyField.java
+++ b/java/core/src/main/java/com/google/protobuf/InternalLazyField.java
@@ -280,7 +280,7 @@
         + computeSize(WireFormat.MESSAGE_SET_MESSAGE);
   }
 
-  void writeTo(Writer writer, int fieldNumber) throws IOException {
+  void writeTo(CodedOutputStreamWriter writer, int fieldNumber) throws IOException {
     if (bytes != null) {
       writer.writeBytes(fieldNumber, bytes);
     } else {
diff --git a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
index 7cbcf8e..55be352 100644
--- a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
+++ b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
@@ -452,8 +452,8 @@
         + computeSize(WireFormat.MESSAGE_SET_MESSAGE);
   }
 
-  /** Writes this lazy field into a {@link Writer}. */
-  void writeTo(Writer writer, int fieldNumber) throws IOException {
+  /** Writes this lazy field into a {@link CodedOutputStreamWriter}. */
+  void writeTo(CodedOutputStreamWriter writer, int fieldNumber) throws IOException {
     if (memoizedBytes != null) {
       writer.writeBytes(fieldNumber, memoizedBytes);
     } else if (delayedBytes != null) {
diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
index 20d79b8..d22002d 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
@@ -2026,7 +2026,7 @@
   // TODO: Consider serializing oneof fields last so that only one entry per
   // oneof is actually serialized. This would mean that we would violate the serialization order
   // contract. It should also be noted that Go currently does this.
-  public void writeTo(T message, Writer writer) throws IOException {
+  public void writeTo(T message, CodedOutputStreamWriter writer) throws IOException {
     Iterator<? extends Map.Entry<?, ?>> extensionIterator = null;
     Map.Entry nextExtension = null;
     if (hasExtensions) {
@@ -2428,8 +2428,8 @@
     writeUnknownInMessageTo(unknownFieldSchema, message, writer);
   }
 
-  private <K, V> void writeMapHelper(Writer writer, int number, Object mapField, int pos)
-      throws IOException {
+  private <K, V> void writeMapHelper(
+      CodedOutputStreamWriter writer, int number, Object mapField, int pos) throws IOException {
     if (mapField != null) {
       writer.writeMap(
           number,
@@ -2439,12 +2439,14 @@
   }
 
   private <UT, UB> void writeUnknownInMessageTo(
-      UnknownFieldSchema<UT, UB> schema, T message, Writer writer) throws IOException {
+      UnknownFieldSchema<UT, UB> schema, T message, CodedOutputStreamWriter writer)
+      throws IOException {
     schema.writeTo(schema.getFromMessage(message), writer);
   }
 
   @Override
-  public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
+  public void mergeFrom(
+      T message, CodedInputStreamReader reader, ExtensionRegistryLite extensionRegistry)
       throws IOException {
     checkNotNull(extensionRegistry);
     checkMutable(message);
@@ -2459,7 +2461,7 @@
       UnknownFieldSchema<UT, UB> unknownFieldSchema,
       ExtensionSchema<ET> extensionSchema,
       T message,
-      Reader reader,
+      CodedInputStreamReader reader,
       ExtensionRegistryLite extensionRegistry)
       throws IOException {
     UB unknownFields = null;
@@ -2469,7 +2471,7 @@
         final int number = reader.getFieldNumber();
         final int pos = positionForFieldNumber(number);
         if (pos < 0) {
-          if (number == Reader.READ_DONE) {
+          if (number == CodedInputStreamReader.READ_DONE) {
             return;
           }
           // Check if it's an extension.
@@ -3897,7 +3899,7 @@
       int pos,
       Object mapDefaultEntry,
       ExtensionRegistryLite extensionRegistry,
-      Reader reader)
+      CodedInputStreamReader reader)
       throws IOException {
     long offset = offset(typeAndOffsetAt(pos));
     Object mapField = UnsafeUtil.getObject(message, offset);
@@ -4096,7 +4098,8 @@
     return true;
   }
 
-  private void writeString(int fieldNumber, Object value, Writer writer) throws IOException {
+  private void writeString(int fieldNumber, Object value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value instanceof String) {
       writer.writeString(fieldNumber, (String) value);
     } else {
@@ -4104,7 +4107,8 @@
     }
   }
 
-  private void readString(Object message, int typeAndOffset, Reader reader) throws IOException {
+  private void readString(Object message, int typeAndOffset, CodedInputStreamReader reader)
+      throws IOException {
     if (isEnforceUtf8(typeAndOffset)) {
       // Enforce valid UTF-8 on the read.
       UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readStringRequireUtf8());
@@ -4119,7 +4123,8 @@
     }
   }
 
-  private void readStringList(Object message, int typeAndOffset, Reader reader) throws IOException {
+  private void readStringList(Object message, int typeAndOffset, CodedInputStreamReader reader)
+      throws IOException {
     if (isEnforceUtf8(typeAndOffset)) {
       reader.readStringListRequireUtf8(
           listFieldSchema.<String>mutableListAt(message, offset(typeAndOffset)));
@@ -4131,7 +4136,7 @@
   private <E> void readMessageList(
       Object message,
       int typeAndOffset,
-      Reader reader,
+      CodedInputStreamReader reader,
       Schema<E> schema,
       ExtensionRegistryLite extensionRegistry)
       throws IOException {
@@ -4143,7 +4148,7 @@
   private <E> void readGroupList(
       Object message,
       long offset,
-      Reader reader,
+      CodedInputStreamReader reader,
       Schema<E> schema,
       ExtensionRegistryLite extensionRegistry)
       throws IOException {
diff --git a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
index bba5b3a..921a975 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
@@ -83,7 +83,7 @@
 
   @SuppressWarnings("unchecked")
   @Override
-  public void writeTo(T message, Writer writer) throws IOException {
+  public void writeTo(T message, CodedOutputStreamWriter writer) throws IOException {
     FieldSet<?> extensions = extensionSchema.getExtensions(message);
     Iterator<?> iterator = extensions.iterator();
     while (iterator.hasNext()) {
@@ -107,7 +107,8 @@
    * https://docs.oracle.com/javase/tutorial/java/generics/capture.html
    */
   private <UT, UB> void writeUnknownFieldsHelper(
-      UnknownFieldSchema<UT, UB> unknownFieldSchema, T message, Writer writer) throws IOException {
+      UnknownFieldSchema<UT, UB> unknownFieldSchema, T message, CodedOutputStreamWriter writer)
+      throws IOException {
     unknownFieldSchema.writeAsMessageSetTo(unknownFieldSchema.getFromMessage(message), writer);
   }
 
@@ -222,7 +223,8 @@
   }
 
   @Override
-  public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
+  public void mergeFrom(
+      T message, CodedInputStreamReader reader, ExtensionRegistryLite extensionRegistry)
       throws IOException {
     mergeFromHelper(unknownFieldSchema, extensionSchema, message, reader, extensionRegistry);
   }
@@ -235,7 +237,7 @@
       UnknownFieldSchema<UT, UB> unknownFieldSchema,
       ExtensionSchema<ET> extensionSchema,
       T message,
-      Reader reader,
+      CodedInputStreamReader reader,
       ExtensionRegistryLite extensionRegistry)
       throws IOException {
     UB unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
@@ -243,7 +245,7 @@
     try {
       while (true) {
         final int number = reader.getFieldNumber();
-        if (number == Reader.READ_DONE) {
+        if (number == CodedInputStreamReader.READ_DONE) {
           return;
         }
         if (parseMessageSetItemOrUnknownField(
@@ -271,7 +273,7 @@
 
   private <UT, UB, ET extends FieldSet.FieldDescriptorLite<ET>>
       boolean parseMessageSetItemOrUnknownField(
-          Reader reader,
+          CodedInputStreamReader reader,
           ExtensionRegistryLite extensionRegistry,
           ExtensionSchema<ET> extensionSchema,
           FieldSet<ET> extensions,
@@ -321,7 +323,7 @@
     loop:
     while (true) {
       final int number = reader.getFieldNumber();
-      if (number == Reader.READ_DONE) {
+      if (number == CodedInputStreamReader.READ_DONE) {
         break;
       }
 
@@ -357,7 +359,7 @@
     if (rawBytes != null) {
       if (extension != null) { // We known the type
         // TODO: Instead of reading into a temporary ByteString, maybe there is a way
-        // to read directly from Reader to the submessage?
+        // to read directly from CodedInputStreamReader to the submessage?
         extensionSchema.parseMessageSetItem(rawBytes, extension, extensionRegistry, extensions);
       } else {
         unknownFieldSchema.addLengthDelimited(unknownFields, typeId, rawBytes);
diff --git a/java/core/src/main/java/com/google/protobuf/Protobuf.java b/java/core/src/main/java/com/google/protobuf/Protobuf.java
index 10f556a..850a055 100644
--- a/java/core/src/main/java/com/google/protobuf/Protobuf.java
+++ b/java/core/src/main/java/com/google/protobuf/Protobuf.java
@@ -29,14 +29,18 @@
     return INSTANCE;
   }
 
-  /** Writes the given message to the target {@link Writer}. */
-  <T extends GeneratedMessageLite<?, ?>> void writeTo(T message, Writer writer) throws IOException {
+  /** Writes the given message to the target {@link CodedOutputStreamWriter}. */
+  <T extends GeneratedMessageLite<?, ?>> void writeTo(T message, CodedOutputStreamWriter writer)
+      throws IOException {
     schemaFor(message).writeTo(message, writer);
   }
 
-  /** Reads fields from the given {@link Reader} and merges them into the message. */
+  /**
+   * Reads fields from the given {@link CodedInputStreamReader} and merges them into the message.
+   */
   <T extends GeneratedMessageLite<?, ?>> void mergeFrom(
-      T message, Reader reader, ExtensionRegistryLite extensionRegistry) throws IOException {
+      T message, CodedInputStreamReader reader, ExtensionRegistryLite extensionRegistry)
+      throws IOException {
     schemaFor(message).mergeFrom(message, reader, extensionRegistry);
   }
 
diff --git a/java/core/src/main/java/com/google/protobuf/Reader.java b/java/core/src/main/java/com/google/protobuf/Reader.java
deleted file mode 100644
index 097e47b..0000000
--- a/java/core/src/main/java/com/google/protobuf/Reader.java
+++ /dev/null
@@ -1,365 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package com.google.protobuf;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-/** A reader of fields from a serialized protobuf message. */
-// TODO: Refactor to allow the reader to allocate properly sized lists.
-@ExperimentalApi
-@CheckReturnValue
-interface Reader {
-  /** Value used to indicate that the end of input has been reached. */
-  int READ_DONE = Integer.MAX_VALUE;
-
-  /** Value used to indicate that the reader does not know the tag about the field. */
-  int TAG_UNKNOWN = 0;
-
-  boolean shouldDiscardUnknownFields();
-
-  /**
-   * Gets the field number for the current field being read.
-   *
-   * <p>TODO: Rename it to make it more explicit about the side effect on the underlying
-   * buffer.
-   *
-   * @return the current field number or {@link #READ_DONE} if the end of input has been reached.
-   */
-  int getFieldNumber() throws IOException;
-
-  /**
-   * Gets the wire tag of the current field.
-   *
-   * @return the current wire tag or {@link #TAG_UNKNOWN} if the reader does not know the tag of the
-   *     current field.
-   */
-  int getTag();
-
-  /**
-   * Skips the current field and advances the reader to the next field.
-   *
-   * @return {@code true} if there are more fields or {@code false} if the end of input has been
-   *     reached.
-   */
-  boolean skipField() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code DOUBLE} and advances the reader to the next
-   * field.
-   */
-  double readDouble() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code FLOAT} and advances the reader to the next
-   * field.
-   */
-  float readFloat() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code UINT64} and advances the reader to the next
-   * field.
-   */
-  long readUInt64() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code INT64} and advances the reader to the next
-   * field.
-   */
-  long readInt64() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code INT32} and advances the reader to the next
-   * field.
-   */
-  int readInt32() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code FIXED64} and advances the reader to the next
-   * field.
-   */
-  long readFixed64() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code FIXED32} and advances the reader to the next
-   * field.
-   */
-  int readFixed32() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code BOOL} and advances the reader to the next
-   * field.
-   */
-  boolean readBool() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code STRING} and advances the reader to the next
-   * field. If the stream contains malformed UTF-8, replace the offending bytes with the standard
-   * UTF-8 replacement character.
-   */
-  String readString() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code STRING} and advances the reader to the next
-   * field. If the stream contains malformed UTF-8, throw exception {@link
-   * InvalidProtocolBufferException}.
-   */
-  String readStringRequireUtf8() throws IOException;
-
-  // TODO: the lack of other opinions for whether to expose this on the interface
-  <T> T readMessageBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code MESSAGE} and advances the reader to the next
-   * field.
-   */
-  <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry) throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code GROUP} and advances the reader to the next
-   * field.
-   *
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry) throws IOException;
-
-  // TODO: the lack of other opinions for whether to expose this on the interface
-  @Deprecated
-  <T> T readGroupBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-
-  /** Read a message field from the wire format and merge the results into the given target. */
-  <T> void mergeMessageField(T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-
-  /** Read a group field from the wire format and merge the results into the given target. */
-  <T> void mergeGroupField(T target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code BYTES} and advances the reader to the next
-   * field.
-   */
-  ByteString readBytes() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code UINT32} and advances the reader to the next
-   * field.
-   */
-  int readUInt32() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code ENUM} and advances the reader to the next
-   * field.
-   */
-  int readEnum() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code SFIXED32} and advances the reader to the next
-   * field.
-   */
-  int readSFixed32() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code SFIXED64} and advances the reader to the next
-   * field.
-   */
-  long readSFixed64() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code SINT32} and advances the reader to the next
-   * field.
-   */
-  int readSInt32() throws IOException;
-
-  /**
-   * Reads and returns the next field of type {@code SINT64} and advances the reader to the next
-   * field.
-   */
-  long readSInt64() throws IOException;
-
-  /**
-   * Reads the next field of type {@code DOUBLE_LIST} or {@code DOUBLE_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readDoubleList(List<Double> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code FLOAT_LIST} or {@code FLOAT_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readFloatList(List<Float> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code UINT64_LIST} or {@code UINT64_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readUInt64List(List<Long> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code INT64_LIST} or {@code INT64_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readInt64List(List<Long> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code INT32_LIST} or {@code INT32_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readInt32List(List<Integer> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code FIXED64_LIST} or {@code FIXED64_LIST_PACKED} and advances
-   * the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readFixed64List(List<Long> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code FIXED32_LIST} or {@code FIXED32_LIST_PACKED} and advances
-   * the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readFixed32List(List<Integer> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code BOOL_LIST} or {@code BOOL_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readBoolList(List<Boolean> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code STRING_LIST} and advances the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readStringList(List<String> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code STRING_LIST} and advances the reader to the next field. If
-   * the stream contains malformed UTF-8, throw exception {@link InvalidProtocolBufferException}.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readStringListRequireUtf8(List<String> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code MESSAGE_LIST} and advances the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   * @param targetType the type of the elements stored in the {@code target} list.
-   */
-  <T> void readMessageList(
-      List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException;
-
-  <T> void readMessageList(
-      List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-
-  /**
-   * Reads the next field of type {@code GROUP_LIST} and advances the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   * @param targetType the type of the elements stored in the {@code target} list.
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  <T> void readGroupList(
-      List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-
-  @Deprecated
-  <T> void readGroupList(
-      List<T> target, Schema<T> targetType, ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-
-  /**
-   * Reads the next field of type {@code BYTES_LIST} and advances the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readBytesList(List<ByteString> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code UINT32_LIST} or {@code UINT32_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readUInt32List(List<Integer> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code ENUM_LIST} or {@code ENUM_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readEnumList(List<Integer> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code SFIXED32_LIST} or {@code SFIXED32_LIST_PACKED} and advances
-   * the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readSFixed32List(List<Integer> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code SFIXED64_LIST} or {@code SFIXED64_LIST_PACKED} and advances
-   * the reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readSFixed64List(List<Long> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code SINT32_LIST} or {@code SINT32_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readSInt32List(List<Integer> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code SINT64_LIST} or {@code SINT64_LIST_PACKED} and advances the
-   * reader to the next field.
-   *
-   * @param target the list that will receive the read values.
-   */
-  void readSInt64List(List<Long> target) throws IOException;
-
-  /**
-   * Reads the next field of type {@code MAP} and advances the reader to the next field.
-   *
-   * @param target the mutable map that will receive the read values.
-   * @param mapDefaultEntry the default entry of the map field.
-   * @param extensionRegistry the extension registry for parsing message value fields.
-   */
-  <K, V> void readMap(
-      Map<K, V> target,
-      MapEntryLite.Metadata<K, V> mapDefaultEntry,
-      ExtensionRegistryLite extensionRegistry)
-      throws IOException;
-}
diff --git a/java/core/src/main/java/com/google/protobuf/Schema.java b/java/core/src/main/java/com/google/protobuf/Schema.java
index fe87af1..e120d9b 100644
--- a/java/core/src/main/java/com/google/protobuf/Schema.java
+++ b/java/core/src/main/java/com/google/protobuf/Schema.java
@@ -17,15 +17,15 @@
 @ExperimentalApi
 @CheckReturnValue
 interface Schema<T> {
-  /** Writes the given message to the target {@link Writer}. */
-  void writeTo(T message, Writer writer) throws IOException;
+  /** Writes the given message to the target {@link CodedOutputStreamWriter}. */
+  void writeTo(T message, CodedOutputStreamWriter writer) throws IOException;
 
   /**
-   * Reads fields from the given {@link Reader} and merges them into the message. It doesn't make
-   * the message immutable after parsing is done. To make the message immutable, use {@link
-   * #makeImmutable}.
+   * Reads fields from the given {@link CodedInputStreamReader} and merges them into the message. It
+   * doesn't make the message immutable after parsing is done. To make the message immutable, use
+   * {@link #makeImmutable}.
    */
-  void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
+  void mergeFrom(T message, CodedInputStreamReader reader, ExtensionRegistryLite extensionRegistry)
       throws IOException;
 
   /**
diff --git a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java
index 6f74e3d..858b00a 100644
--- a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java
@@ -45,91 +45,106 @@
     }
   }
 
-  public static void writeDouble(int fieldNumber, double value, Writer writer) throws IOException {
+  public static void writeDouble(int fieldNumber, double value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (Double.doubleToRawLongBits(value) != 0) {
       writer.writeDouble(fieldNumber, value);
     }
   }
 
-  public static void writeFloat(int fieldNumber, float value, Writer writer) throws IOException {
+  public static void writeFloat(int fieldNumber, float value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (Float.floatToRawIntBits(value) != 0) {
       writer.writeFloat(fieldNumber, value);
     }
   }
 
-  public static void writeInt64(int fieldNumber, long value, Writer writer) throws IOException {
+  public static void writeInt64(int fieldNumber, long value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeInt64(fieldNumber, value);
     }
   }
 
-  public static void writeUInt64(int fieldNumber, long value, Writer writer) throws IOException {
+  public static void writeUInt64(int fieldNumber, long value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeUInt64(fieldNumber, value);
     }
   }
 
-  public static void writeSInt64(int fieldNumber, long value, Writer writer) throws IOException {
+  public static void writeSInt64(int fieldNumber, long value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeSInt64(fieldNumber, value);
     }
   }
 
-  public static void writeFixed64(int fieldNumber, long value, Writer writer) throws IOException {
+  public static void writeFixed64(int fieldNumber, long value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeFixed64(fieldNumber, value);
     }
   }
 
-  public static void writeSFixed64(int fieldNumber, long value, Writer writer) throws IOException {
+  public static void writeSFixed64(int fieldNumber, long value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeSFixed64(fieldNumber, value);
     }
   }
 
-  public static void writeInt32(int fieldNumber, int value, Writer writer) throws IOException {
+  public static void writeInt32(int fieldNumber, int value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeInt32(fieldNumber, value);
     }
   }
 
-  public static void writeUInt32(int fieldNumber, int value, Writer writer) throws IOException {
+  public static void writeUInt32(int fieldNumber, int value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeUInt32(fieldNumber, value);
     }
   }
 
-  public static void writeSInt32(int fieldNumber, int value, Writer writer) throws IOException {
+  public static void writeSInt32(int fieldNumber, int value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeSInt32(fieldNumber, value);
     }
   }
 
-  public static void writeFixed32(int fieldNumber, int value, Writer writer) throws IOException {
+  public static void writeFixed32(int fieldNumber, int value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeFixed32(fieldNumber, value);
     }
   }
 
-  public static void writeSFixed32(int fieldNumber, int value, Writer writer) throws IOException {
+  public static void writeSFixed32(int fieldNumber, int value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeSFixed32(fieldNumber, value);
     }
   }
 
-  public static void writeEnum(int fieldNumber, int value, Writer writer) throws IOException {
+  public static void writeEnum(int fieldNumber, int value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != 0) {
       writer.writeEnum(fieldNumber, value);
     }
   }
 
-  public static void writeBool(int fieldNumber, boolean value, Writer writer) throws IOException {
+  public static void writeBool(int fieldNumber, boolean value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value) {
       writer.writeBool(fieldNumber, true);
     }
   }
 
-  public static void writeString(int fieldNumber, Object value, Writer writer) throws IOException {
+  public static void writeString(int fieldNumber, Object value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value instanceof String) {
       writeStringInternal(fieldNumber, (String) value, writer);
     } else {
@@ -137,153 +152,170 @@
     }
   }
 
-  private static void writeStringInternal(int fieldNumber, String value, Writer writer)
-      throws IOException {
+  private static void writeStringInternal(
+      int fieldNumber, String value, CodedOutputStreamWriter writer) throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeString(fieldNumber, value);
     }
   }
 
-  public static void writeBytes(int fieldNumber, ByteString value, Writer writer)
+  public static void writeBytes(int fieldNumber, ByteString value, CodedOutputStreamWriter writer)
       throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeBytes(fieldNumber, value);
     }
   }
 
-  public static void writeMessage(int fieldNumber, Object value, Writer writer) throws IOException {
+  public static void writeMessage(int fieldNumber, Object value, CodedOutputStreamWriter writer)
+      throws IOException {
     if (value != null) {
       writer.writeMessage(fieldNumber, value);
     }
   }
 
   public static void writeDoubleList(
-      int fieldNumber, List<Double> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Double> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeDoubleList(fieldNumber, value, packed);
     }
   }
 
   public static void writeFloatList(
-      int fieldNumber, List<Float> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Float> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeFloatList(fieldNumber, value, packed);
     }
   }
 
   public static void writeInt64List(
-      int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Long> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeInt64List(fieldNumber, value, packed);
     }
   }
 
   public static void writeUInt64List(
-      int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Long> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeUInt64List(fieldNumber, value, packed);
     }
   }
 
   public static void writeSInt64List(
-      int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Long> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeSInt64List(fieldNumber, value, packed);
     }
   }
 
   public static void writeFixed64List(
-      int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Long> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeFixed64List(fieldNumber, value, packed);
     }
   }
 
   public static void writeSFixed64List(
-      int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Long> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeSFixed64List(fieldNumber, value, packed);
     }
   }
 
   public static void writeInt32List(
-      int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Integer> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeInt32List(fieldNumber, value, packed);
     }
   }
 
   public static void writeUInt32List(
-      int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Integer> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeUInt32List(fieldNumber, value, packed);
     }
   }
 
   public static void writeSInt32List(
-      int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Integer> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeSInt32List(fieldNumber, value, packed);
     }
   }
 
   public static void writeFixed32List(
-      int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Integer> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeFixed32List(fieldNumber, value, packed);
     }
   }
 
   public static void writeSFixed32List(
-      int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Integer> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeSFixed32List(fieldNumber, value, packed);
     }
   }
 
   public static void writeEnumList(
-      int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Integer> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeEnumList(fieldNumber, value, packed);
     }
   }
 
   public static void writeBoolList(
-      int fieldNumber, List<Boolean> value, Writer writer, boolean packed) throws IOException {
+      int fieldNumber, List<Boolean> value, CodedOutputStreamWriter writer, boolean packed)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeBoolList(fieldNumber, value, packed);
     }
   }
 
-  public static void writeStringList(int fieldNumber, List<String> value, Writer writer)
-      throws IOException {
+  public static void writeStringList(
+      int fieldNumber, List<String> value, CodedOutputStreamWriter writer) throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeStringList(fieldNumber, value);
     }
   }
 
-  public static void writeBytesList(int fieldNumber, List<ByteString> value, Writer writer)
-      throws IOException {
+  public static void writeBytesList(
+      int fieldNumber, List<ByteString> value, CodedOutputStreamWriter writer) throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeBytesList(fieldNumber, value);
     }
   }
 
-  public static void writeMessageList(int fieldNumber, List<?> value, Writer writer)
-      throws IOException {
+  public static void writeMessageList(
+      int fieldNumber, List<?> value, CodedOutputStreamWriter writer) throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeMessageList(fieldNumber, value);
     }
   }
 
   public static void writeMessageList(
-      int fieldNumber, List<?> value, Writer writer, Schema<?> schema) throws IOException {
+      int fieldNumber, List<?> value, CodedOutputStreamWriter writer, Schema<?> schema)
+      throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeMessageList(fieldNumber, value, schema);
     }
   }
 
-  public static void writeLazyFieldList(int fieldNumber, List<?> value, Writer writer)
+  public static void writeLazyFieldList(int fieldNumber, List<?> value, CodedOutputStreamWriter
+  writer)
       throws IOException {
     if (value != null && !value.isEmpty()) {
       for (Object item : value) {
@@ -292,14 +324,15 @@
     }
   }
 
-  public static void writeGroupList(int fieldNumber, List<?> value, Writer writer)
+  public static void writeGroupList(int fieldNumber, List<?> value, CodedOutputStreamWriter writer)
       throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeGroupList(fieldNumber, value);
     }
   }
 
-  public static void writeGroupList(int fieldNumber, List<?> value, Writer writer, Schema<?> schema)
+  public static void writeGroupList(
+      int fieldNumber, List<?> value, CodedOutputStreamWriter writer, Schema<?> schema)
       throws IOException {
     if (value != null && !value.isEmpty()) {
       writer.writeGroupList(fieldNumber, value, schema);
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
index 5e2683d..ad4ac13 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
@@ -19,7 +19,7 @@
   private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT;
 
   /** Whether unknown fields should be dropped. */
-  abstract boolean shouldDiscardUnknownFields(Reader reader);
+  abstract boolean shouldDiscardUnknownFields(CodedInputStreamReader reader);
 
   /** Adds a varint value to the unknown fields. */
   abstract void addVarint(B fields, int number, long value);
@@ -61,7 +61,7 @@
   abstract void makeImmutable(Object message);
 
   /** Merges one field into the unknown fields. */
-  final boolean mergeOneFieldFrom(B unknownFields, Reader reader, int currentDepth)
+  final boolean mergeOneFieldFrom(B unknownFields, CodedInputStreamReader reader, int currentDepth)
       throws IOException {
     int tag = reader.getTag();
     int fieldNumber = WireFormat.getTagFieldNumber(tag);
@@ -102,19 +102,20 @@
     }
   }
 
-  private final void mergeFrom(B unknownFields, Reader reader, int currentDepth)
+  private final void mergeFrom(B unknownFields, CodedInputStreamReader reader, int currentDepth)
       throws IOException {
     while (true) {
-      if (reader.getFieldNumber() == Reader.READ_DONE
+      if (reader.getFieldNumber() == CodedInputStreamReader.READ_DONE
           || !mergeOneFieldFrom(unknownFields, reader, currentDepth)) {
         break;
       }
     }
   }
 
-  abstract void writeTo(T unknownFields, Writer writer) throws IOException;
+  abstract void writeTo(T unknownFields, CodedOutputStreamWriter writer) throws IOException;
 
-  abstract void writeAsMessageSetTo(T unknownFields, Writer writer) throws IOException;
+  abstract void writeAsMessageSetTo(T unknownFields, CodedOutputStreamWriter writer)
+      throws IOException;
 
   /** Merges {@code source} into {@code destination} and returns the merged instance. */
   abstract T merge(T destination, T source);
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 16a52e2..be8ef63 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -209,7 +209,7 @@
   }
 
   /** Serializes the set and writes it to {@code writer}. */
-  void writeTo(Writer writer) throws IOException {
+  void writeTo(CodedOutputStreamWriter writer) throws IOException {
     if (fields.isEmpty()) {
       // Avoid allocating an iterator.
       return;
@@ -221,7 +221,7 @@
   }
 
   /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */
-  void writeAsMessageSetTo(Writer writer) throws IOException {
+  void writeAsMessageSetTo(CodedOutputStreamWriter writer) throws IOException {
     if (fields.isEmpty()) {
       // Avoid allocating an iterator.
       return;
@@ -837,7 +837,7 @@
     }
 
     /** Serializes the field, including field number, and writes it to {@code writer}. */
-    void writeTo(int fieldNumber, Writer writer) throws IOException {
+    void writeTo(int fieldNumber, CodedOutputStreamWriter writer) throws IOException {
       writer.writeInt64List(fieldNumber, varint, false);
       writer.writeFixed32List(fieldNumber, fixed32, false);
       writer.writeFixed64List(fieldNumber, fixed64, false);
@@ -856,7 +856,8 @@
      * MessageSet} wire format.
      */
     @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) // No iterator allocation.
-    private void writeAsMessageSetExtensionTo(int fieldNumber, Writer writer) throws IOException {
+    private void writeAsMessageSetExtensionTo(int fieldNumber, CodedOutputStreamWriter writer)
+        throws IOException {
       // Write in ascending field order.
       for (int i = 0; i < lengthDelimited.size(); i++) {
         ByteString value = lengthDelimited.get(i);
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
index cc5640d..d8013c4 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
@@ -148,7 +148,7 @@
   }
 
   /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */
-  void writeAsMessageSetTo(Writer writer) throws IOException {
+  void writeAsMessageSetTo(CodedOutputStreamWriter writer) throws IOException {
     // Write fields in ascending order.
     for (int i = 0; i < count; i++) {
       int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
@@ -157,7 +157,7 @@
   }
 
   /** Serializes the set and writes it to {@code writer}. */
-  public void writeTo(Writer writer) throws IOException {
+  public void writeTo(CodedOutputStreamWriter writer) throws IOException {
     if (count == 0) {
       return;
     }
@@ -168,7 +168,8 @@
     }
   }
 
-  private static void writeField(int tag, Object object, Writer writer) throws IOException {
+  private static void writeField(int tag, Object object, CodedOutputStreamWriter writer)
+      throws IOException {
     int fieldNumber = WireFormat.getTagFieldNumber(tag);
     switch (WireFormat.getTagWireType(tag)) {
       case WireFormat.WIRETYPE_VARINT:
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java
index de2845b..8fe777f 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java
@@ -16,7 +16,7 @@
   UnknownFieldSetLiteSchema() {}
 
   @Override
-  boolean shouldDiscardUnknownFields(Reader reader) {
+  boolean shouldDiscardUnknownFields(CodedInputStreamReader reader) {
     // We never drop unknown fields in lite.
     return false;
   }
@@ -90,12 +90,13 @@
   }
 
   @Override
-  void writeTo(UnknownFieldSetLite fields, Writer writer) throws IOException {
+  void writeTo(UnknownFieldSetLite fields, CodedOutputStreamWriter writer) throws IOException {
     fields.writeTo(writer);
   }
 
   @Override
-  void writeAsMessageSetTo(UnknownFieldSetLite fields, Writer writer) throws IOException {
+  void writeAsMessageSetTo(UnknownFieldSetLite fields, CodedOutputStreamWriter writer)
+      throws IOException {
     fields.writeAsMessageSetTo(writer);
   }
 
diff --git a/java/core/src/main/java/com/google/protobuf/Writer.java b/java/core/src/main/java/com/google/protobuf/Writer.java
deleted file mode 100644
index b304515..0000000
--- a/java/core/src/main/java/com/google/protobuf/Writer.java
+++ /dev/null
@@ -1,185 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package com.google.protobuf;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-/** A writer that performs serialization of protobuf message fields. */
-@ExperimentalApi
-@CheckReturnValue
-@SuppressWarnings({"unchecked", "rawtypes"})
-interface Writer {
-  /** Writes a field of type {@link FieldType#SFIXED32}. */
-  void writeSFixed32(int fieldNumber, int value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#INT64}. */
-  void writeInt64(int fieldNumber, long value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#SFIXED64}. */
-  void writeSFixed64(int fieldNumber, long value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#FLOAT}. */
-  void writeFloat(int fieldNumber, float value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#DOUBLE}. */
-  void writeDouble(int fieldNumber, double value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#ENUM}. */
-  void writeEnum(int fieldNumber, int value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#UINT64}. */
-  void writeUInt64(int fieldNumber, long value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#INT32}. */
-  void writeInt32(int fieldNumber, int value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#FIXED64}. */
-  void writeFixed64(int fieldNumber, long value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#FIXED32}. */
-  void writeFixed32(int fieldNumber, int value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#BOOL}. */
-  void writeBool(int fieldNumber, boolean value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#STRING}. */
-  void writeString(int fieldNumber, String value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#BYTES}. */
-  void writeBytes(int fieldNumber, ByteString value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#UINT32}. */
-  void writeUInt32(int fieldNumber, int value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#SINT32}. */
-  void writeSInt32(int fieldNumber, int value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#SINT64}. */
-  void writeSInt64(int fieldNumber, long value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#MESSAGE}. */
-  void writeMessage(int fieldNumber, Object value) throws IOException;
-
-  /** Writes a field of type {@link FieldType#MESSAGE}. */
-  void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException;
-
-  /**
-   * Writes a field of type {@link FieldType#GROUP}.
-   *
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  void writeGroup(int fieldNumber, Object value) throws IOException;
-
-  /**
-   * Writes a field of type {@link FieldType#GROUP}.
-   *
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException;
-
-  /**
-   * Writes a single start group tag.
-   *
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  void writeStartGroup(int fieldNumber) throws IOException;
-
-  /**
-   * Writes a single end group tag.
-   *
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  void writeEndGroup(int fieldNumber) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#INT32}. */
-  void writeInt32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#FIXED32}. */
-  void writeFixed32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#INT64}. */
-  void writeInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#UINT64}. */
-  void writeUInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#FIXED64}. */
-  void writeFixed64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#FLOAT}. */
-  void writeFloatList(int fieldNumber, List<Float> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#DOUBLE}. */
-  void writeDoubleList(int fieldNumber, List<Double> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#ENUM}. */
-  void writeEnumList(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#BOOL}. */
-  void writeBoolList(int fieldNumber, List<Boolean> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#STRING}. */
-  void writeStringList(int fieldNumber, List<String> value) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#BYTES}. */
-  void writeBytesList(int fieldNumber, List<ByteString> value) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#UINT32}. */
-  void writeUInt32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#SFIXED32}. */
-  void writeSFixed32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#SFIXED64}. */
-  void writeSFixed64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#SINT32}. */
-  void writeSInt32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#SINT64}. */
-  void writeSInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#MESSAGE}. */
-  void writeMessageList(int fieldNumber, List<?> value) throws IOException;
-
-  /** Writes a list field of type {@link FieldType#MESSAGE}. */
-  void writeMessageList(int fieldNumber, List<?> value, Schema schema) throws IOException;
-
-  /**
-   * Writes a list field of type {@link FieldType#GROUP}.
-   *
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  void writeGroupList(int fieldNumber, List<?> value) throws IOException;
-
-  /**
-   * Writes a list field of type {@link FieldType#GROUP}.
-   *
-   * @deprecated groups fields are deprecated.
-   */
-  @Deprecated
-  void writeGroupList(int fieldNumber, List<?> value, Schema schema) throws IOException;
-
-  /**
-   * Writes a message field in {@code MessageSet} wire-format.
-   *
-   * @param value A message instance or an opaque {@link ByteString} for an unknown field.
-   */
-  void writeMessageSetItem(int fieldNumber, Object value) throws IOException;
-
-  /** Writes a map field. */
-  <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)
-      throws IOException;
-}
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java
index 8b66db8..6637ae9 100644
--- a/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java
+++ b/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java
@@ -43,7 +43,7 @@
   @Test
   public void invalidUtf8StringParsing() throws IOException {
     for (ByteBuffer invalidUtf8Bytes : serializedBytesWithInvalidUtf8()) {
-      Reader reader =
+      CodedInputStreamReader reader =
           CodedInputStreamReader.forCodedInput(CodedInputStream.newInstance(invalidUtf8Bytes));
 
       T newMsg = schema.newInstance();
@@ -95,7 +95,7 @@
       assertWithMessage(failureMessage).that(newMsg).isEqualTo(msg);
     }
     M newMsg = schema.newInstance();
-    Reader reader =
+    CodedInputStreamReader reader =
         CodedInputStreamReader.forCodedInput(CodedInputStream.newInstance(serializedBytes));
     schema.mergeFrom(newMsg, reader, ExtensionRegistryLite.getEmptyRegistry());
     schema.makeImmutable(newMsg);