diff --git a/lang/java/avro/src/main/java/org/apache/avro/Conversions.java b/lang/java/avro/src/main/java/org/apache/avro/Conversions.java index 6b90ee68ed2..d8da2d9a2b9 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/Conversions.java +++ b/lang/java/avro/src/main/java/org/apache/avro/Conversions.java @@ -45,16 +45,6 @@ public class Conversions { public static class UUIDConversion extends Conversion { - private final boolean isBigEndian; - - public UUIDConversion() { - this(ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN); - } - - public UUIDConversion(final boolean isBigEndian) { - this.isBigEndian = isBigEndian; - } - @Override public Class getConvertedType() { return UUID.class; @@ -82,36 +72,18 @@ public CharSequence toCharSequence(UUID value, Schema schema, LogicalType type) @Override public UUID fromFixed(final GenericFixed value, final Schema schema, final LogicalType type) { - long mostSigBits = 0; - long leastSigBits = 0; - byte[] bytes = value.bytes(); - for (int i = 0; i < Long.BYTES; i++) { - mostSigBits |= ((long) (bytes[i] & 255)) << (Byte.SIZE * i); - leastSigBits |= ((long) (bytes[i + Long.BYTES] & 255)) << (Byte.SIZE * i); - } - - return new UUID(this.convert(mostSigBits), this.convert(leastSigBits)); - } - - private long convert(long value) { - if (this.isBigEndian) { - return value; - } else { - return Long.reverseBytes(value); - } + ByteBuffer buffer = ByteBuffer.wrap(value.bytes()); + long mostSigBits = buffer.getLong(); + long leastSigBits = buffer.getLong(); + return new UUID(mostSigBits, leastSigBits); } @Override public GenericFixed toFixed(final UUID value, final Schema schema, final LogicalType type) { - final long mostSigBits = this.convert(value.getMostSignificantBits()); - final long leastSigBits = this.convert(value.getLeastSignificantBits()); - byte[] result = new byte[2 * Long.BYTES]; - for (int i = 0; i < Long.BYTES; i++) { - result[i] = (byte) ((mostSigBits >> (i * Byte.SIZE)) & 255); - result[i + Long.BYTES] = (byte) ((leastSigBits >> (i * Byte.SIZE)) & 255); - } - - return new GenericData.Fixed(schema, result); + ByteBuffer buffer = ByteBuffer.allocate(2 * Long.BYTES); + buffer.putLong(value.getMostSignificantBits()); + buffer.putLong(value.getLeastSignificantBits()); + return new GenericData.Fixed(schema, buffer.array()); } } diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestUuidConversions.java b/lang/java/avro/src/test/java/org/apache/avro/TestUuidConversions.java index ffd1f530303..640bf1a2bb5 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/TestUuidConversions.java +++ b/lang/java/avro/src/test/java/org/apache/avro/TestUuidConversions.java @@ -24,6 +24,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import java.math.BigInteger; import java.util.UUID; import java.util.stream.Stream; @@ -32,29 +33,34 @@ public class TestUuidConversions { private Conversions.UUIDConversion uuidConversion = new Conversions.UUIDConversion(); private Schema fixed = Schema.createFixed("fixed", "doc", "", Long.BYTES * 2); - private Schema fixedUUid = LogicalTypes.uuid().addToSchema(fixed); + private Schema fixedUuid = LogicalTypes.uuid().addToSchema(fixed); + + private Schema string = Schema.createFixed("fixed", "doc", "", Long.BYTES * 2); + private Schema stringUuid = LogicalTypes.uuid().addToSchema(string); @ParameterizedTest @MethodSource("uuidData") void uuidFixed(UUID uuid) { - GenericFixed value = uuidConversion.toFixed(uuid, fixedUUid, LogicalTypes.uuid()); - UUID uuid1 = uuidConversion.fromFixed(value, fixedUUid, LogicalTypes.uuid()); + GenericFixed value = uuidConversion.toFixed(uuid, fixedUuid, LogicalTypes.uuid()); + + byte[] b = new byte[Long.BYTES]; + System.arraycopy(value.bytes(), 0, b, 0, b.length); + Assertions.assertEquals(uuid.getMostSignificantBits(), new BigInteger(b).longValue()); + System.arraycopy(value.bytes(), Long.BYTES, b, 0, b.length); + Assertions.assertEquals(uuid.getLeastSignificantBits(), new BigInteger(b).longValue()); + + UUID uuid1 = uuidConversion.fromFixed(value, fixedUuid, LogicalTypes.uuid()); Assertions.assertEquals(uuid, uuid1); } @ParameterizedTest @MethodSource("uuidData") - void uuidFixedReverse(UUID uuid) { - Conversions.UUIDConversion bigEndianConversion = new Conversions.UUIDConversion(true); - Conversions.UUIDConversion littleEndianConversion = new Conversions.UUIDConversion(false); + void uuidCharSequence(UUID uuid) { + CharSequence value = uuidConversion.toCharSequence(uuid, stringUuid, LogicalTypes.uuid()); - // simulate uuid from other endian source, assume it's big endian (nevermind if - // current jvm is big endian, as we simulate). - UUID reverserUUID = new UUID(Long.reverseBytes(uuid.getMostSignificantBits()), - Long.reverseBytes(uuid.getLeastSignificantBits())); - GenericFixed value = bigEndianConversion.toFixed(reverserUUID, fixedUUid, LogicalTypes.uuid()); + Assertions.assertEquals(uuid.toString(), value.toString()); - UUID uuid1 = littleEndianConversion.fromFixed(value, fixedUUid, LogicalTypes.uuid()); + UUID uuid1 = uuidConversion.fromCharSequence(value, stringUuid, LogicalTypes.uuid()); Assertions.assertEquals(uuid, uuid1); }