Change ArrayIndexOutOfBounds message to exclude information about char and index.

The information doesn't seem very useful for debugging, and it isn't possible to have the char+index be accurate while allowing for fast-failure paths that can know an input string won't fit but can't possibly know the exact character that is at the boundary without doing a lot of expensive work instead.

The unit test already reflected the oddity that what it printed wasn't consistent/predictable depending on if it was going to hit a fast-path or not, and that test is fixed to shown the consistency after this change.

PiperOrigin-RevId: 810954092
diff --git a/java/core/src/main/java/com/google/protobuf/Utf8.java b/java/core/src/main/java/com/google/protobuf/Utf8.java
index d520067..3e06c0c 100644
--- a/java/core/src/main/java/com/google/protobuf/Utf8.java
+++ b/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -824,12 +824,8 @@
         Java8Compatibility.position(out, outIx);
       } catch (IndexOutOfBoundsException e) {
         // TODO: Consider making the API throw IndexOutOfBoundsException instead.
-
-        // If we failed in the outer ASCII loop, outIx will not have been updated. In this case,
-        // use inIx to determine the bad write index.
-        int badWriteIndex = out.position() + Math.max(inIx, outIx - out.position() + 1);
         throw new ArrayIndexOutOfBoundsException(
-            "Failed writing " + in.charAt(inIx) + " at index " + badWriteIndex);
+            "Not enough space in output buffer to encode UTF-8 string");
       }
     }
   }
@@ -1058,7 +1054,8 @@
               && (i + 1 == in.length() || !Character.isSurrogatePair(c, in.charAt(i + 1)))) {
             throw new UnpairedSurrogateException(i, utf16Length);
           }
-          throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+          throw new ArrayIndexOutOfBoundsException(
+              "Not enough space in output buffer to encode UTF-8 string");
         }
       }
       return j;
@@ -1449,7 +1446,7 @@
       if (inLimit > length || out.length - length < offset) {
         // Not even enough room for an ASCII-encoded string.
         throw new ArrayIndexOutOfBoundsException(
-            "Failed writing " + in.charAt(inLimit - 1) + " at index " + (offset + length));
+            "Not enough space in output buffer to encode UTF-8 string");
       }
 
       // Designed to take advantage of
@@ -1494,7 +1491,8 @@
             throw new UnpairedSurrogateException(inIx, inLimit);
           }
           // Not enough space in the output buffer.
-          throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+          throw new ArrayIndexOutOfBoundsException(
+              "Not enough space in output buffer to encode UTF-8 string");
         }
       }
 
@@ -1511,7 +1509,7 @@
       if (inLimit > outLimit - outIx) {
         // Not even enough room for an ASCII-encoded string.
         throw new ArrayIndexOutOfBoundsException(
-            "Failed writing " + in.charAt(inLimit - 1) + " at index " + out.limit());
+            "Not enough space in output buffer to encode UTF-8 string");
       }
 
       // Designed to take advantage of
@@ -1557,7 +1555,8 @@
             throw new UnpairedSurrogateException(inIx, inLimit);
           }
           // Not enough space in the output buffer.
-          throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+          throw new ArrayIndexOutOfBoundsException(
+              "Not enough space in output buffer to encode UTF-8 string");
         }
       }
 
diff --git a/java/core/src/test/java/com/google/protobuf/Utf8Test.java b/java/core/src/test/java/com/google/protobuf/Utf8Test.java
index 2a53e82..fd50ba2 100644
--- a/java/core/src/test/java/com/google/protobuf/Utf8Test.java
+++ b/java/core/src/test/java/com/google/protobuf/Utf8Test.java
@@ -142,8 +142,9 @@
     } catch (Throwable t) {
       // Expected
       assertThat(t).isInstanceOf(clazz);
-      // byte[] + safeProcessor will not exit early. We can't match the message since we don't
-      // know which char/index due to random input.
+      assertThat(t)
+          .hasMessageThat()
+          .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
     }
 
     try {
@@ -151,9 +152,9 @@
       assertWithMessage("Expected " + clazz.getSimpleName()).fail();
     } catch (Throwable t) {
       assertThat(t).isInstanceOf(clazz);
-      // byte[] + unsafeProcessor will exit early, so we have can match the message.
-      String pattern = "Failed writing (.) at index " + length;
-      assertThat(t).hasMessageThat().matches(pattern);
+      assertThat(t)
+          .hasMessageThat()
+          .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
     }
 
     try {
@@ -162,8 +163,9 @@
     } catch (Throwable t) {
       // Expected
       assertThat(t).isInstanceOf(clazz);
-      // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't
-      // know which char/index due to random input.
+      assertThat(t)
+          .hasMessageThat()
+          .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
     }
 
     try {
@@ -172,8 +174,9 @@
     } catch (Throwable t) {
       // Expected
       assertThat(t).isInstanceOf(clazz);
-      // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't
-      // know which char/index due to random input.
+      assertThat(t)
+          .hasMessageThat()
+          .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
     }
 
     try {
@@ -182,13 +185,9 @@
     } catch (Throwable t) {
       // Expected
       assertThat(t).isInstanceOf(clazz);
-      // Direct ByteBuffer + unsafeProcessor will exit early if it's not on Android, so we can
-      // match the message. On Android, a direct ByteBuffer will have hasArray() being true and
-      // it will take a different code path and produces a different message.
-      if (!Android.isOnAndroidDevice()) {
-        String pattern = "Failed writing (.) at index " + length;
-        assertThat(t).hasMessageThat().matches(pattern);
-      }
+      assertThat(t)
+          .hasMessageThat()
+          .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
     }
   }