Skip to content

Commit 98bddd5

Browse files
committed
Handle encoding checks as in strTranscode
Logic in strTranscode evolved over the years to allow same-encoding requests to be no-ops. Those changes were never applied to rbByteEncode, resulting in same-encoding requests triggering errors when the transcoding subsystem saw nothing would be done. This complicated efforts to solve jruby#8682 by passing an encoding to the IOOutputStream constructor (ruby/json#759 and ruby/json#760). This patch allows using IOOutputStream and the byte[] IO API it calls with an externally-encoded IO by passing in an expected encoding for incoming bytes. All bytes will be treated as being encoded properly, and if the source and destination encoding is the same, rbByteEncode will return null to indicate no-op. Note that this misses some functionality of strTranscode in that it does not scrub the string for same-encoding requests. Partially addresses ruby/json#760. Fixes jruby#8686.
1 parent 51f66e8 commit 98bddd5

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

core/src/main/java/org/jruby/util/io/EncodingUtils.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -934,18 +934,31 @@ public static IRubyObject rbStrEncode(ThreadContext context, IRubyObject str, IR
934934
return strTranscode1(context, to, (RubyString) str, ecflags, ecopt, EncodingUtils::encodedDup);
935935
}
936936

937-
// rb_str_encode
937+
/**
938+
* A version of rbStrEncode that works directly with bytes.
939+
*
940+
* MRI: rb_str_encode but consuming only a byte array range and producing a ByteList.
941+
*
942+
* @param context
943+
* @param bytes
944+
* @param start
945+
* @param length
946+
* @param encoding
947+
* @param cr
948+
* @param to
949+
* @param ecflags
950+
* @param ecopt
951+
* @return
952+
*/
938953
public static ByteList rbByteEncode(ThreadContext context, byte[] bytes, int start, int length, Encoding encoding, int cr, Encoding to, int ecflags, IRubyObject ecopt) {
939954
byte[] sname, dname;
940955

941956
sname = encoding.getName();
942957
dname = to.getName();
943958

944959
if (noDecorators(ecflags)) {
945-
if (encoding.isAsciiCompatible() && to.isAsciiCompatible()) {
946-
if (cr == StringSupport.CR_7BIT) {
947-
return null;
948-
}
960+
if (is7BitCompat(cr, encoding, to)) {
961+
return null;
949962
} else if (encodingEqual(sname, dname)) {
950963
return null;
951964
}
@@ -1106,6 +1119,12 @@ private static boolean is7BitCompat(RubyString str, Encoding denc, Encoding senc
11061119
&& str.scanForCodeRange() == StringSupport.CR_7BIT;
11071120
}
11081121

1122+
private static boolean is7BitCompat(int cr, Encoding denc, Encoding senc) {
1123+
return senc != null && denc != null
1124+
&& senc.isAsciiCompatible() && denc.isAsciiCompatible()
1125+
&& cr == StringSupport.CR_7BIT;
1126+
}
1127+
11091128
private static RubyString strTranscodeScrub(ThreadContext context, IRubyObject forceEncoding, RubyString str, int ecflags, IRubyObject ecopts, TranscodeResult result, boolean explicitlyInvalidReplace, Encoding denc, Encoding senc) {
11101129
RubyString dest = str;
11111130
if ((ecflags & EConvFlags.INVALID_MASK) != 0 && explicitlyInvalidReplace) {

0 commit comments

Comments
 (0)