From eb13d6189543d5ffa708e3ca723dcacff86b4ede Mon Sep 17 00:00:00 2001 From: David Noble Date: Tue, 3 Sep 2019 02:38:24 -0700 Subject: [PATCH] Progressed on port --- .../com/azure/data/cosmos/core/Codecs.java | 7 - .../azure/data/cosmos/core/Utf8String.java | 97 +-- .../cosmos/core/codecs/DateTimeCodec.java | 113 ++++ .../data/cosmos/core/codecs/DecimalCodec.java | 187 ++++++ .../cosmos/core/codecs/Float128Codec.java | 72 +++ .../data/cosmos/core/codecs/GuidCodec.java | 93 +++ .../serialization/hybridrow/Float128.java | 15 +- .../serialization/hybridrow/RowBuffer.java | 611 ++++++++++-------- .../serialization/hybridrow/io/RowReader.java | 6 +- .../hybridrow/layouts/LayoutBinary.java | 4 +- .../hybridrow/layouts/LayoutDateTime.java | 4 +- .../hybridrow/layouts/LayoutGuid.java | 2 +- .../hybridrow/layouts/LayoutUtf8.java | 2 +- .../hybridrow/unit/NullableUnitTests.java | 12 +- 14 files changed, 840 insertions(+), 385 deletions(-) delete mode 100644 java/src/main/java/com/azure/data/cosmos/core/Codecs.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/codecs/DateTimeCodec.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/codecs/DecimalCodec.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/codecs/Float128Codec.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/codecs/GuidCodec.java diff --git a/java/src/main/java/com/azure/data/cosmos/core/Codecs.java b/java/src/main/java/com/azure/data/cosmos/core/Codecs.java deleted file mode 100644 index a1a1c8b..0000000 --- a/java/src/main/java/com/azure/data/cosmos/core/Codecs.java +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.data.cosmos.core; - -public class Codecs { -} diff --git a/java/src/main/java/com/azure/data/cosmos/core/Utf8String.java b/java/src/main/java/com/azure/data/cosmos/core/Utf8String.java index 115a56b..1c397b7 100644 --- a/java/src/main/java/com/azure/data/cosmos/core/Utf8String.java +++ b/java/src/main/java/com/azure/data/cosmos/core/Utf8String.java @@ -18,6 +18,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; import java.util.Iterator; import java.util.NoSuchElementException; @@ -202,68 +203,6 @@ public final class Utf8String implements CharSequence, Comparable { return this.length; } - public static boolean opEquals(Utf8String left, Utf8String right) { - if (null == left) { - return null == right; - } - return left.equals(right); - } - - public static boolean opGreaterThan(Utf8String left, Utf8String right) { - return left != null && left.compareTo(right) > 0; - } - - public static boolean opGreaterThan(Utf8String left, String right) { - return left != null && left.compareTo(right) > 0; - } - - public static boolean opGreaterThan(String left, Utf8String right) { - return right == null || right.compareTo(left) <= 0; - } - - public static boolean opGreaterThanOrEquals(Utf8String left, Utf8String right) { - return left == null ? right == null : left.compareTo(right) >= 0; - } - - public static boolean opGreaterThanOrEquals(Utf8String left, String right) { - return left == null ? right == null : left.compareTo(right) >= 0; - } - - public static boolean opGreaterThanOrEquals(String left, Utf8String right) { - return right == null ? left != null : right.compareTo(left) < 0; - } - - public static boolean opLessThan(Utf8String left, Utf8String right) { - return left == null ? right != null : left.compareTo(right) < 0; - } - - public static boolean opLessThan(Utf8String left, String right) { - return left == null ? right != null : left.compareTo(right) < 0; - } - - public static boolean opLessThan(String left, Utf8String right) { - return right == null ? left == null : right.compareTo(left) >= 0; - } - - public static boolean opLessThanOrEquals(Utf8String left, Utf8String right) { - return left == null || left.compareTo(right) <= 0; - } - - public static boolean opLessThanOrEquals(Utf8String left, String right) { - return left == null || left.compareTo(right) <= 0; - } - - public static boolean opLessThanOrEquals(String left, Utf8String right) { - return right != null && right.compareTo(left) > 0; - } - - public static boolean opNotEquals(Utf8String left, Utf8String right) { - if (null == left) { - return null != right; - } - return !left.equals(right); - } - @Override public CharSequence subSequence(int start, int end) { checkArgument(start < 0 || end < 0 || start > end || end > this.length, "start: %s, end: %s", start, end); @@ -281,14 +220,15 @@ public final class Utf8String implements CharSequence, Comparable { } /** - * Creates a {@link Utf8String} from a UTF16 encoding string. - * - * @param string The UTF16 encoding string. - * @return A new {@link Utf8String}. + * Creates a {@link Utf8String} from a UTF16 encoding string *

* This method must transcode the UTF-16 into UTF-8 which both requires allocation and is a size of data operation. + * + * @param string A UTF-16 encoding string or {@code null} + * @return A new {@link Utf8String} or {@code null}, if {@code string} is {@code null} */ - public static Utf8String transcodeUtf16(final String string) { + @Nullable + public static Utf8String transcodeUtf16(@Nullable final String string) { if (string == null) { return null; @@ -308,17 +248,34 @@ public final class Utf8String implements CharSequence, Comparable { } /** - * Parses the contents of a byte buffer to prove it contains a valid UTF-8 character sequence + * Creates a new {@link Utf8String} from a {@link ByteBuf} with UTF-8 character validation + *

+ * The {@link Utf8String} created retains the {@link ByteBuf}. (No data is transferred.) * - * @param buffer The byte buffer to validate + * @param buffer The {@link ByteBuf} to validate and assign to the {@link Utf8String} created. * @return A {@link Utf8String} instance, if the @{code buffer} validates or a value of @{link Optional#empty} * otherwise. */ - public static Optional tryParseUtf8Bytes(@Nonnull final ByteBuf buffer) { + @Nonnull + public static Optional from(@Nonnull final ByteBuf buffer) { checkNotNull(buffer); return Utf8.isWellFormed(buffer.array()) ? Optional.of(new Utf8String(buffer)) : Optional.empty(); } + /** + * Creates a new {@link Utf8String} from a {@link ByteBuf} without UTF-8 character validation + *

+ * The {@link Utf8String} created retains the {@link ByteBuf}. (No data is transferred.) + * + * @param buffer The {@link ByteBuf} to assign to the {@link Utf8String} created. + * @return a new {@link Utf8String} + */ + @Nonnull + public static Utf8String fromUnsafe(@Nonnull ByteBuf buffer) { + checkNotNull(buffer); + return new Utf8String(buffer); + } + private static int decodedLength(final ByteBuf buffer) { final CodePointIterable iterable = new CodePointIterable(buffer, -1); diff --git a/java/src/main/java/com/azure/data/cosmos/core/codecs/DateTimeCodec.java b/java/src/main/java/com/azure/data/cosmos/core/codecs/DateTimeCodec.java new file mode 100644 index 0000000..aad2dd5 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/codecs/DateTimeCodec.java @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core.codecs; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class DateTimeCodec { + + private static final int BYTES = Long.BYTES; + + private static final long FLAGS_MASK = 0xC000000000000000L; + private static final long KIND_AMBIGUOUS = 0xC000000000000000L; + private static final long KIND_LOCAL = 0x8000000000000000L; + private static final long KIND_UTC = 0x4000000000000000L; + private static final long TICKS_MASK = 0x3FFFFFFFFFFFFFFFL; + + private static final ZoneOffset ZONE_OFFSET_LOCAL = OffsetDateTime.now().getOffset(); + private static final int ZONE_OFFSET_LOCAL_TOTAL_SECONDS = ZONE_OFFSET_LOCAL.getTotalSeconds(); + private static final int ZONE_OFFSET_UTC_TOTAL_SECONDS = ZoneOffset.UTC.getTotalSeconds(); + + private DateTimeCodec() { + } + + /** + * Decode an {@link OffsetDateTime} from a {@code System.DateTimeCodec} as serialized by {@code MemoryMarshal.Write} + * + * @param bytes a {@link byte} array containing the serialized value to be decoded + * @return a new {@link OffsetDateTime} + * @see + * struct DateTimeCodec source + */ + public static OffsetDateTime decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode an {@link OffsetDateTime} from a {@code System.DateTimeCodec} as serialized by {@code MemoryMarshal.Write} + * + * @param in a {@link ByteBuf} containing the serialized value to be decoded + * @return a new {@link OffsetDateTime} + * @see + * struct DateTimeCodec source + */ + public static OffsetDateTime decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s", + BYTES, + in.readableBytes()); + + final long data = in.readLongLE(); + final long epochSecond = data & TICKS_MASK; + final ZoneOffset zoneOffset = (data & FLAGS_MASK) == KIND_UTC ? ZoneOffset.UTC : ZONE_OFFSET_LOCAL; + + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), zoneOffset); + } + + /** + * Encode an {@link OffsetDateTime} as a {@code System.DateTimeCodec} serialized by {@code MemoryMarshal.Write} + * + * @param offsetDateTime an {@link OffsetDateTime} to be encoded + * @return a new byte array containing the encoded {@code offsetDateTime} + * @see + * struct DateTimeCodec source + */ + public static byte[] encode(final OffsetDateTime offsetDateTime) { + final byte[] bytes = new byte[BYTES]; + encode(offsetDateTime, Unpooled.wrappedBuffer(bytes)); + return bytes; + } + + /** + * Encode an {@link OffsetDateTime} as a {@code System.DateTimeCodec} serialized by {@code MemoryMarshal.Write} + * + * @param offsetDateTime an {@link OffsetDateTime} to be encoded + * @param out an output {@link ByteBuf} + * @see + * struct DateTimeCodec source + */ + public static void encode(final OffsetDateTime offsetDateTime, final ByteBuf out) { + + final long epochSecond = offsetDateTime.toEpochSecond(); + + checkArgument(epochSecond <= TICKS_MASK, "expected offsetDateTime epoch second in range [0, %s], not %s", + TICKS_MASK, + epochSecond); + + final int zoneOffsetTotalSeconds = offsetDateTime.getOffset().getTotalSeconds(); + final long value; + + if (zoneOffsetTotalSeconds == ZONE_OFFSET_UTC_TOTAL_SECONDS) { + value = epochSecond | KIND_UTC; + } else if (zoneOffsetTotalSeconds == ZONE_OFFSET_LOCAL_TOTAL_SECONDS) { + value = epochSecond | KIND_LOCAL; + } else { + value = epochSecond | KIND_AMBIGUOUS; + } + + out.writeLongLE(value); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/core/codecs/DecimalCodec.java b/java/src/main/java/com/azure/data/cosmos/core/codecs/DecimalCodec.java new file mode 100644 index 0000000..297ef58 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/codecs/DecimalCodec.java @@ -0,0 +1,187 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core.codecs; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static java.lang.Math.max; +import static java.lang.Math.min; + +public final class DecimalCodec { + + public static final int BYTES = 4 * Integer.BYTES; + + private static final int FLAGS_MASK_INVALID = 0b01111111000000001111111111111111; + private static final int FLAGS_MASK_POWER = 0b00000000111111110000000000000000; + private static final int FLAGS_MASK_SIGN = 0b10000000000000000000000000000000; + + private static final BigInteger MAGNITUDE_MAX = new BigInteger(new byte[] { (byte)0x00, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF }); + + private static final BigInteger MAGNITUDE_MIN = new BigInteger(new byte[] { (byte)0xFF, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 }); + + private static final MathContext REDUCED_PRECISION = new MathContext(28, RoundingMode.HALF_EVEN); + private static final int SCALE_MAX = 28; + private static final int SCALE_MIN = 0; + private static final int SCALE_SHIFT = 16; + private static final int VALUE_LENGTH = 3 * Integer.BYTES; + + private DecimalCodec() { + } + + /** + * Decode a {@link BigDecimal} from a {@code System.DecimalCodec} as serialized by {@code MemoryMarshal.Write} + * + * @param bytes a {@link byte} array containing the serialized {@code System.DecimalCodec} to be decoded + * @return a new {@link BigDecimal} + * @see + * struct DecimalCodec source + */ + public static BigDecimal decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode a {@link BigDecimal} from a {@code System.DecimalCodec} value serialized by {@code MemoryMarshal.Write} + * + * @param in a {@link ByteBuf} containing the serialized {@code System.DecimalCodec} to be decoded + * @return a new {@link BigDecimal} + * @see + * struct DecimalCodec source + */ + public static BigDecimal decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s", + BYTES, + in.readableBytes()); + + // The flags field is--and must be--interpreted as follows + // + // Bits Interpretation + // ----- -------------------------------------------------------------------------------------------- + // 0-15 unused and must be zero + // 16-23 a value between 0 and 28 specifying the number of digits to the right of the decimal point + // 24-30 unused and must be zero + // 31 specifies the sign of the value, 1 meaning negative and 0 meaning non-negative + + final int flags = in.readIntLE(); + checkState((flags & FLAGS_MASK_INVALID) == 0, "invalid flags field: %s", flags); + + final int scale = (flags | FLAGS_MASK_POWER) >>> SCALE_SHIFT; + checkState(scale <= SCALE_MAX); + + final int signum = (flags & FLAGS_MASK_SIGN) == 0 ? 1 : -1; + final byte[] buffer = new byte[VALUE_LENGTH]; + in.readBytes(buffer); + + int i = VALUE_LENGTH; + int j = 0; + + while (i > j) { + final byte b = buffer[--i]; + buffer[i] = buffer[j]; + buffer[j++] = b; + } + + return new BigDecimal(new BigInteger(signum, buffer), scale); + } + + /** + * Encode a {@link BigDecimal} as a {@code System.DecimalCodec} serialized by {@code MemoryMarshal.Write} + * + * @param bigDecimal a {@link BigDecimal} to be encoded + * @return a new byte array containing the encoded {@code bigDecimal} + * @see + * struct DecimalCodec source + */ + public static byte[] encode(final BigDecimal bigDecimal) { + final byte[] bytes = new byte[BYTES]; + encode(bigDecimal, Unpooled.wrappedBuffer(bytes)); + return bytes; + } + + /** + * Encode a {@link BigDecimal} as a {@code System.DecimalCodec} serialized by {@code MemoryMarshal.Write} + * + * @param value a {@link BigDecimal} to be encoded + * @param out an output {@link ByteBuf} + * @see + * struct DecimalCodec source + */ + public static void encode(@Nonnull BigDecimal value, @Nonnull final ByteBuf out) { + + checkNotNull(value, "expected non-null value"); + checkNotNull(value, "expected non-null out"); + + final int signum = value.signum(); + + if (signum == 0) { + out.writeZero(BYTES); + return; + } + + BigInteger unscaledValue = value.unscaledValue(); + + if (unscaledValue.compareTo(MAGNITUDE_MIN) < 0 || unscaledValue.compareTo(MAGNITUDE_MAX) > 0) { + value = value.stripTrailingZeros(); + unscaledValue = value.unscaledValue(); + if (unscaledValue.compareTo(MAGNITUDE_MIN) < 0 || unscaledValue.compareTo(MAGNITUDE_MAX) > 0) { + value = new BigDecimal(unscaledValue, min(max(value.scale(), SCALE_MIN), SCALE_MAX), REDUCED_PRECISION); + unscaledValue = value.unscaledValue(); + } + } + + if (value.scale() < SCALE_MIN) { + value = value.setScale(SCALE_MIN, RoundingMode.HALF_EVEN); + unscaledValue = value.unscaledValue(); + } else if (value.scale() > SCALE_MAX) { + value = value.setScale(SCALE_MAX, RoundingMode.HALF_EVEN); + unscaledValue = value.unscaledValue(); + } + + final byte[] bytes = unscaledValue.toByteArray(); + final byte[] buffer = new byte[VALUE_LENGTH]; + final int flags; + + if (signum == -1) { + flags = FLAGS_MASK_SIGN | value.scale() << SCALE_SHIFT; + int carry = 1; + for (int i = buffer.length, j = 0; i-- > 0; j++) { + final int n = ((bytes[i] ^ 0b1111_1111) & 0b1111_1111) + carry; + if ((n & 0b1_0000_0000) == 0) { + carry = 0; + } + buffer[j] = bytes[i]; + } + } else { + flags = value.scale() << SCALE_SHIFT; + for (int i = buffer.length, j = 0; i-- > 0; j++) { + buffer[j] = bytes[i]; + } + } + + out.writeIntLE(flags); + out.writeBytes(buffer, 0, 4); + out.writeBytes(buffer, 8, 4); + out.writeBytes(buffer, 4, 4); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/core/codecs/Float128Codec.java b/java/src/main/java/com/azure/data/cosmos/core/codecs/Float128Codec.java new file mode 100644 index 0000000..5f232bc --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/codecs/Float128Codec.java @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core.codecs; + +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class Float128Codec { + + public static final int BYTES = 2 * Long.BYTES; + + private Float128Codec() { + } + + /** + * Decode a {@link Float128} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param bytes a {@link byte} array containing the serialized {@link Float128} to be decoded + * @return a new {@link Float128} + */ + public static Float128 decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode a {@link Float128} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param in a {@link ByteBuf} containing the serialized {@link Float128} to be decoded + * @return a new {@link Float128} + */ + public static Float128 decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s", + BYTES, + in.readableBytes()); + + return new Float128(in.readLongLE(), in.readLongLE()); + } + + /** + * Encodes a {@link Float128} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param value a {@link Float128} to be encoded + * @return a new byte array containing the encoded + */ + public static byte[] encode(final Float128 value) { + final byte[] bytes = new byte[BYTES]; + encode(value, Unpooled.wrappedBuffer(bytes)); + return bytes; + } + + /** + * Encodes a {@link Float128} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param value a {@link Float128} to be encoded + * @param out an output {@link ByteBuf} + */ + public static void encode(final Float128 value, final ByteBuf out) { + out.writeLongLE(value.high()); + out.writeLongLE(value.low()); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/core/codecs/GuidCodec.java b/java/src/main/java/com/azure/data/cosmos/core/codecs/GuidCodec.java new file mode 100644 index 0000000..0d84344 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/codecs/GuidCodec.java @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core.codecs; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import java.util.UUID; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class GuidCodec { + + public static final int BYTES = 2 * Long.BYTES; + + private GuidCodec() { + } + + /** + * Decode a {@link UUID} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param bytes a {@link byte} array containing the serialized {@link UUID} to be decoded + * @return a new {@link UUID} + */ + public static UUID decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode a {@link UUID} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param in a {@link ByteBuf} containing the serialized {@link UUID} to be decoded + * @return a new {@link UUID} + */ + public static UUID decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s", + BYTES, + in.readableBytes()); + + long mostSignificantBits = in.readUnsignedIntLE() << 32; + + mostSignificantBits |= (0x000000000000FFFFL & in.readShortLE()) << 16; + mostSignificantBits |= (0x000000000000FFFFL & in.readShortLE()); + + long leastSignificantBits = (0x000000000000FFFFL & in.readShortLE()) << (32 + 16); + + for (int shift = 32 + 8; shift >= 0; shift -= 8) { + leastSignificantBits |= (0x00000000000000FFL & in.readByte()) << shift; + } + + return new UUID(mostSignificantBits, leastSignificantBits); + } + + /** + * Encodes a {@link UUID} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param uuid a {@link UUID} to be encoded + * @return a new byte array containing the encoded + */ + public static byte[] encode(final UUID uuid) { + final byte[] bytes = new byte[BYTES]; + encode(uuid, Unpooled.wrappedBuffer(bytes)); + return bytes; + } + + /** + * Encodes a {@link UUID} as serialized by Microsoft APIs like {@code System.GuidCodec.ToByteArray} + * + * @param uuid a {@link UUID} to be encoded + * @param out an output {@link ByteBuf} + */ + public static void encode(final UUID uuid, final ByteBuf out) { + + final long mostSignificantBits = uuid.getMostSignificantBits(); + + out.writeIntLE((int) ((mostSignificantBits & 0xFFFFFFFF00000000L) >>> 32)); + out.writeShortLE((short) ((mostSignificantBits & 0x00000000FFFF0000L) >>> 16)); + out.writeShortLE((short) (mostSignificantBits & 0x000000000000FFFFL)); + + final long leastSignificantBits = uuid.getLeastSignificantBits(); + + out.writeShortLE((short) ((leastSignificantBits & 0xFFFF000000000000L) >>> (32 + 16))); + out.writeShort((short) ((leastSignificantBits & 0x0000FFFF00000000L) >>> 32)); + out.writeInt((int) (leastSignificantBits & 0x00000000FFFFFFFFL)); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java index b3d973c..50ba734 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java @@ -3,10 +3,6 @@ package com.azure.data.cosmos.serialization.hybridrow; -// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: -///#pragma warning disable CA1051 // Do not declare visible instance fields - - /** * An IEEE 128-bit floating point value. *

@@ -25,19 +21,12 @@ package com.azure.data.cosmos.serialization.hybridrow; * * */ -// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: -//ORIGINAL LINE: [DebuggerDisplay("{" + nameof(Float128.Low) + "," + nameof(Float128.High) + "}")][StructLayout -// (LayoutKind.Sequential, Pack = 1)] public readonly struct Float128 -//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ -// from the original: -//ORIGINAL LINE: [DebuggerDisplay("{" + nameof(Float128.Low) + "," + nameof(Float128.High) + "}")][StructLayout -// (LayoutKind.Sequential, Pack = 1)] public readonly struct Float128 -//C# TO JAVA CONVERTER WARNING: Java has no equivalent to the C# readonly struct: + public final class Float128 { /** * The size (in bytes) of a {@link Float128}. */ - public static final int Size = (Long.SIZE / Byte.SIZE) + (Long.SIZE / Byte.SIZE); + public static final int SIZE = (Long.SIZE / Byte.SIZE) + (Long.SIZE / Byte.SIZE); private final long high; private final long low; diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java index 0de10ce..aafaa31 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java @@ -6,6 +6,10 @@ package com.azure.data.cosmos.serialization.hybridrow; import com.azure.data.cosmos.core.Out; import com.azure.data.cosmos.core.Reference; import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.core.codecs.DateTimeCodec; +import com.azure.data.cosmos.core.codecs.DecimalCodec; +import com.azure.data.cosmos.core.codecs.Float128Codec; +import com.azure.data.cosmos.core.codecs.GuidCodec; import com.azure.data.cosmos.serialization.hybridrow.io.RowWriter; import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutArray; @@ -62,6 +66,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.util.Iterator; import java.util.Optional; import java.util.UUID; @@ -136,35 +141,43 @@ public final class RowBuffer { checkState(HybridRowHeader.SIZE + layout.size() <= this.length()); } - public UUID readGuid(int offset) { - - return MemoryMarshal.Read(this.buffer.Slice(offset)); + public ByteBuf readSparseBinary(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.BINARY); + ByteBuf value = this.readBinary(edit.valueOffset()); + edit.endOffset(this.buffer.readerIndex()); + return value; } - public short ReadInt16(int offset) { - return MemoryMarshal.Read(this.buffer.Slice(offset)); + public boolean readSparseBoolean(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.BOOLEAN); + edit.endOffset(edit.valueOffset()); + return edit.cellType() == LayoutTypes.BOOLEAN; } - public LocalDateTime ReadDateTime(int offset) { - return MemoryMarshal.Read(this.buffer.Slice(offset)); + public OffsetDateTime readSparseDateTime(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.DATE_TIME); + edit.endOffset(edit.valueOffset() + Long.SIZE); + return this.readDateTime(edit.valueOffset()); } - public BigDecimal ReadDecimal(int offset) { - return MemoryMarshal.Read(this.buffer.Slice(offset)); + public BigDecimal readDecimal(int offset) { + Item item = this.read(() -> DecimalCodec.decode(this.buffer), offset); + return item.value(); } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: internal ReadOnlySpan ReadFixedBinary(int offset, int len) - public ReadOnlySpan ReadFixedBinary(int offset, int len) { - return this.buffer.Slice(offset, len); + public ByteBuf readFixedBinary(int offset, int length) { + Item item = this.read(() -> this.buffer.readSlice(length), offset); + return item.value(); } - public Utf8Span ReadFixedString(int offset, int len) { - return Utf8Span.UnsafeFromUtf8BytesNoValidation(this.buffer.Slice(offset, len)); + public Utf8String readFixedString(int offset, int length) { + Item item = this.read(() -> Utf8String.fromUnsafe(this.buffer.readSlice(length)), offset); + return item.value(); } public Float128 ReadFloat128(int offset) { - return MemoryMarshal.Read(this.buffer.Slice(offset)); + Item item = this.read(() -> Float128Codec.decode(this.buffer), offset); + return item.value(); } public float ReadFloat32(int offset) { @@ -187,30 +200,23 @@ public final class RowBuffer { return new SchemaId(this.ReadInt32(offset)); } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: internal ReadOnlySpan ReadSparseBinary(ref RowCursor edit) - public ReadOnlySpan ReadSparseBinary(Reference edit) { - this.readSparsePrimitiveTypeCode(edit, LayoutType.Binary); - int sizeLenInBytes; - Out tempOut_sizeLenInBytes = new Out(); - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: ReadOnlySpan span = this.ReadBinary(edit.valueOffset, out int sizeLenInBytes); - ReadOnlySpan span = this.ReadBinary(edit.get().valueOffset(), tempOut_sizeLenInBytes); - sizeLenInBytes = tempOut_sizeLenInBytes.get(); - edit.get().endOffset = edit.get().valueOffset() + sizeLenInBytes + span.Length; - return span; + public BigDecimal ReadSparseDecimal(Reference edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutType.Decimal); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'sizeof': + edit.get().endOffset = edit.get().valueOffset() + sizeof(BigDecimal); + return this.readDecimal(edit.get().valueOffset()); } - public boolean ReadSparseBool(Reference edit) { - this.readSparsePrimitiveTypeCode(edit, LayoutType.Boolean); - edit.get().endOffset = edit.get().valueOffset(); - return edit.get().cellType() == LayoutType.Boolean; + public Float128 ReadSparseFloat128(Reference edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutType.Float128); + edit.get().endOffset = edit.get().valueOffset() + Float128.SIZE; + return this.ReadFloat128(edit.get().valueOffset()).clone(); } - public LocalDateTime ReadSparseDateTime(Reference edit) { - this.readSparsePrimitiveTypeCode(edit, LayoutType.DateTime); - edit.get().endOffset = edit.get().valueOffset() + 8; - return this.ReadDateTime(edit.get().valueOffset()); + public float ReadSparseFloat32(Reference edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutType.Float32); + edit.get().endOffset = edit.get().valueOffset() + (Float.SIZE / Byte.SIZE); + return this.ReadFloat32(edit.get().valueOffset()); } public MongoDbObjectId ReadSparseMongoDbObjectId(Reference edit) { @@ -229,23 +235,30 @@ public final class RowBuffer { return span; } - public BigDecimal ReadSparseDecimal(Reference edit) { - this.readSparsePrimitiveTypeCode(edit, LayoutType.Decimal); - // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'sizeof': - edit.get().endOffset = edit.get().valueOffset() + sizeof(BigDecimal); - return this.ReadDecimal(edit.get().valueOffset()); + public long ReadSparseVarInt(Reference edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutType.VarInt); + int sizeLenInBytes; + Out tempOut_sizeLenInBytes = new Out(); + long value = this.read7BitEncodedInt(edit.get().valueOffset(), tempOut_sizeLenInBytes); + sizeLenInBytes = tempOut_sizeLenInBytes.get(); + edit.get().endOffset = edit.get().valueOffset() + sizeLenInBytes; + return value; } - public Float128 ReadSparseFloat128(Reference edit) { - this.readSparsePrimitiveTypeCode(edit, LayoutType.Float128); - edit.get().endOffset = edit.get().valueOffset() + Float128.Size; - return this.ReadFloat128(edit.get().valueOffset()).clone(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: internal ushort ReadUInt16(int offset) + public short ReadUInt16(int offset) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: return MemoryMarshal.Read(this.buffer.Slice(offset)); + return MemoryMarshal.Read(this.buffer.Slice(offset)); } - public float ReadSparseFloat32(Reference edit) { - this.readSparsePrimitiveTypeCode(edit, LayoutType.Float32); - edit.get().endOffset = edit.get().valueOffset() + (Float.SIZE / Byte.SIZE); - return this.ReadFloat32(edit.get().valueOffset()); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: internal uint ReadUInt32(int offset) + public int ReadUInt32(int offset) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: return MemoryMarshal.Read(this.buffer.Slice(offset)); + return MemoryMarshal.Read(this.buffer.Slice(offset)); } //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: @@ -286,32 +299,6 @@ public final class RowBuffer { return this.ReadUnixDateTime(edit.get().valueOffset()).clone(); } - public long ReadSparseVarInt(Reference edit) { - this.readSparsePrimitiveTypeCode(edit, LayoutType.VarInt); - int sizeLenInBytes; - Out tempOut_sizeLenInBytes = new Out(); - long value = this.read7BitEncodedInt(edit.get().valueOffset(), tempOut_sizeLenInBytes); - sizeLenInBytes = tempOut_sizeLenInBytes.get(); - edit.get().endOffset = edit.get().valueOffset() + sizeLenInBytes; - return value; - } - - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: internal ushort ReadUInt16(int offset) - public short ReadUInt16(int offset) { - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: return MemoryMarshal.Read(this.buffer.Slice(offset)); - return MemoryMarshal.Read(this.buffer.Slice(offset)); - } - - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: internal uint ReadUInt32(int offset) - public int ReadUInt32(int offset) { - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: return MemoryMarshal.Read(this.buffer.Slice(offset)); - return MemoryMarshal.Read(this.buffer.Slice(offset)); - } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: //ORIGINAL LINE: internal ulong ReadUInt64(int offset) public long ReadUInt64(int offset) { @@ -339,7 +326,7 @@ public final class RowBuffer { Out tempOut__ = new Out(); //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: //ORIGINAL LINE: return this.ReadBinary(offset, out int _); - ReadOnlySpan tempVar = this.ReadBinary(offset, tempOut__); + ReadOnlySpan tempVar = this.readBinary(offset); _ = tempOut__.get(); return tempVar; } @@ -434,6 +421,26 @@ public final class RowBuffer { this.length(this.length() + shiftDelete); } + public void UnsetBit(int offset, LayoutBit bit) { + checkState(LayoutBit.opNotEquals(bit.clone(), LayoutBit.INVALID)); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.buffer[bit.GetOffset(offset)] &= unchecked((byte)~(1 << bit.GetBit())); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + this.buffer[bit.offset(offset)] &= (byte) ~(1 << bit.bit()); + } + + public void WriteDateTime(int offset, LocalDateTime value) { + Reference tempReference_value = new Reference(value); + MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); + value = tempReference_value.get(); + } + + public void WriteDecimal(int offset, BigDecimal value) { + Reference tempReference_value = new Reference(value); + MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); + value = tempReference_value.get(); + } + /** * Rebuild the unique index for a set/map scope. * @@ -547,26 +554,6 @@ public final class RowBuffer { return Result.Success; } - public void UnsetBit(int offset, LayoutBit bit) { - checkState(LayoutBit.opNotEquals(bit.clone(), LayoutBit.INVALID)); - // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: - //ORIGINAL LINE: this.buffer[bit.GetOffset(offset)] &= unchecked((byte)~(1 << bit.GetBit())); - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - this.buffer[bit.offset(offset)] &= (byte) ~(1 << bit.bit()); - } - - public void WriteDateTime(int offset, LocalDateTime value) { - Reference tempReference_value = new Reference(value); - MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); - value = tempReference_value.get(); - } - - public void WriteDecimal(int offset, BigDecimal value) { - Reference tempReference_value = new Reference(value); - MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); - value = tempReference_value.get(); - } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: //ORIGINAL LINE: internal void WriteFixedBinary(int offset, ReadOnlySpan value, int len) public void WriteFixedBinary(int offset, ReadOnlySpan value, int len) { @@ -767,7 +754,7 @@ public final class RowBuffer { } public void WriteSparseFloat128(Reference edit, Float128 value, UpdateOptions options) { - int numBytes = Float128.Size; + int numBytes = Float128.SIZE; int metaBytes; Out tempOut_metaBytes = new Out(); int spaceNeeded; @@ -781,7 +768,7 @@ public final class RowBuffer { metaBytes = tempOut_metaBytes.get(); this.writeSparseMetadata(edit, LayoutType.Float128, TypeArgumentList.EMPTY, metaBytes); this.writeFloat128(edit.get().valueOffset(), value); - checkState(spaceNeeded == metaBytes + Float128.Size); + checkState(spaceNeeded == metaBytes + Float128.SIZE); edit.get().endOffset = edit.get().metaOffset() + spaceNeeded; this.length(this.length() + shift); } @@ -806,14 +793,6 @@ public final class RowBuffer { this.length(this.length() + shift); } - // TODO: DANOBLE: Support MongoDbObjectId values - // public void WriteMongoDbObjectId(int offset, MongoDbObjectId value) { - // Reference tempReference_value = - // new Reference(value); - // MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); - // value = tempReference_value.get(); - // } - public void WriteSparseGuid(Reference edit, UUID value, UpdateOptions options) { int numBytes = 16; int metaBytes; @@ -874,6 +853,14 @@ public final class RowBuffer { this.length(this.length() + shift); } + // TODO: DANOBLE: Support MongoDbObjectId values + // public void WriteMongoDbObjectId(int offset, MongoDbObjectId value) { + // Reference tempReference_value = + // new Reference(value); + // MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); + // value = tempReference_value.get(); + // } + public void WriteSparseInt64(Reference edit, long value, UpdateOptions options) { int numBytes = (Long.SIZE / Byte.SIZE); int metaBytes; @@ -1422,44 +1409,6 @@ public final class RowBuffer { this.length(this.length() + shift.get()); } - public void WriteUnixDateTime(int offset, UnixDateTime value) { - Reference tempReference_value = - new Reference(value); - MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); - value = tempReference_value.get(); - } - - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: internal void WriteVariableBinary(int offset, ReadOnlySpan value, bool exists, out int shift) - public void WriteVariableBinary(int offset, ReadOnlySpan value, boolean exists, - Out shift) { - int numBytes = value.Length; - int spaceNeeded; - Out tempOut_spaceNeeded = new Out(); - this.EnsureVariable(offset, false, numBytes, exists, tempOut_spaceNeeded, shift); - spaceNeeded = tempOut_spaceNeeded.get(); - - int sizeLenInBytes = this.WriteBinary(offset, value); - checkState(spaceNeeded == numBytes + sizeLenInBytes); - this.length(this.length() + shift.get()); - } - - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: internal void WriteVariableBinary(int offset, ReadOnlySequence value, bool exists, out int - // shift) - public void WriteVariableBinary(int offset, ReadOnlySequence value, boolean exists, - Out shift) { - int numBytes = (int)value.Length; - int spaceNeeded; - Out tempOut_spaceNeeded = new Out(); - this.EnsureVariable(offset, false, numBytes, exists, tempOut_spaceNeeded, shift); - spaceNeeded = tempOut_spaceNeeded.get(); - - int sizeLenInBytes = this.WriteBinary(offset, value); - checkState(spaceNeeded == numBytes + sizeLenInBytes); - this.length(this.length() + shift.get()); - } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: //ORIGINAL LINE: internal void WriteVariableUInt(int offset, ulong value, bool exists, out int shift) public void WriteVariableUInt(int offset, long value, boolean exists, Out shift) { @@ -1497,42 +1446,42 @@ public final class RowBuffer { this.buffer.setIntLE(offset, (int) (value - decrement)); } - /** - * Compute the byte offset from the beginning of the row for a given variable column's value. - * - * @param layout The (optional) layout of the current scope. - * @param scopeOffset The 0-based offset to the beginning of the scope's value. - * @param varIndex The 0-based index of the variable column within the variable segment. - * @return The byte offset from the beginning of the row where the variable column's value should be - * located. - */ - public int computeVariableValueOffset(Layout layout, int scopeOffset, int varIndex) { - if (layout == null) { - return scopeOffset; - } + public void WriteUnixDateTime(int offset, UnixDateTime value) { + Reference tempReference_value = + new Reference(value); + MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); + value = tempReference_value.get(); + } - int index = layout.numFixed() + varIndex; - ReadOnlySpan columns = layout.columns(); - checkState(index <= columns.Length); - int offset = scopeOffset + layout.size(); - for (int i = layout.numFixed(); i < index; i++) { - LayoutColumn col = columns[i]; - if (this.readBit(scopeOffset, col.getNullBit().clone())) { - int lengthSizeInBytes; - Out tempOut_lengthSizeInBytes = new Out(); - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: ulong valueSizeInBytes = this.Read7BitEncodedUInt(offset, out int lengthSizeInBytes); - long valueSizeInBytes = this.read7BitEncodedUInt(offset, tempOut_lengthSizeInBytes); - lengthSizeInBytes = tempOut_lengthSizeInBytes.get(); - if (col.type().getIsVarint()) { - offset += lengthSizeInBytes; - } else { - offset += (int) valueSizeInBytes + lengthSizeInBytes; - } - } - } + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: internal void WriteVariableBinary(int offset, ReadOnlySpan value, bool exists, out int shift) + public void WriteVariableBinary(int offset, ReadOnlySpan value, boolean exists, + Out shift) { + int numBytes = value.Length; + int spaceNeeded; + Out tempOut_spaceNeeded = new Out(); + this.EnsureVariable(offset, false, numBytes, exists, tempOut_spaceNeeded, shift); + spaceNeeded = tempOut_spaceNeeded.get(); - return offset; + int sizeLenInBytes = this.WriteBinary(offset, value); + checkState(spaceNeeded == numBytes + sizeLenInBytes); + this.length(this.length() + shift.get()); + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: internal void WriteVariableBinary(int offset, ReadOnlySequence value, bool exists, out int + // shift) + public void WriteVariableBinary(int offset, ReadOnlySequence value, boolean exists, + Out shift) { + int numBytes = (int)value.Length; + int spaceNeeded; + Out tempOut_spaceNeeded = new Out(); + this.EnsureVariable(offset, false, numBytes, exists, tempOut_spaceNeeded, shift); + spaceNeeded = tempOut_spaceNeeded.get(); + + int sizeLenInBytes = this.WriteBinary(offset, value); + checkState(spaceNeeded == numBytes + sizeLenInBytes); + this.length(this.length() + shift.get()); } /** @@ -1579,6 +1528,44 @@ public final class RowBuffer { return this.readHeader(); } + /** + * Compute the byte offset from the beginning of the row for a given variable column's value. + * + * @param layout The (optional) layout of the current scope. + * @param scopeOffset The 0-based offset to the beginning of the scope's value. + * @param varIndex The 0-based index of the variable column within the variable segment. + * @return The byte offset from the beginning of the row where the variable column's value should be + * located. + */ + public int computeVariableValueOffset(Layout layout, int scopeOffset, int varIndex) { + if (layout == null) { + return scopeOffset; + } + + int index = layout.numFixed() + varIndex; + ReadOnlySpan columns = layout.columns(); + checkState(index <= columns.Length); + int offset = scopeOffset + layout.size(); + for (int i = layout.numFixed(); i < index; i++) { + LayoutColumn col = columns[i]; + if (this.readBit(scopeOffset, col.getNullBit().clone())) { + int lengthSizeInBytes; + Out tempOut_lengthSizeInBytes = new Out(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ulong valueSizeInBytes = this.Read7BitEncodedUInt(offset, out int lengthSizeInBytes); + long valueSizeInBytes = this.read7BitEncodedUInt(offset, tempOut_lengthSizeInBytes); + lengthSizeInBytes = tempOut_lengthSizeInBytes.get(); + if (col.type().getIsVarint()) { + offset += lengthSizeInBytes; + } else { + offset += (int) valueSizeInBytes + lengthSizeInBytes; + } + } + } + + return offset; + } + public void incrementUInt32(final int offset, final long increment) { final long value = this.buffer.getUnsignedIntLE(offset); this.buffer.setIntLE(offset, (int) (value + increment)); @@ -1671,19 +1658,26 @@ public final class RowBuffer { } public long read7BitEncodedUInt(int offset, Out lengthInBytes) { - return this.read(this::read7BitEncodedUInt, offset, lengthInBytes); + Item item = this.read(this::read7BitEncodedUInt, offset); + lengthInBytes.set(item.length()); + return item.value(); } - public boolean readBit(int offset, LayoutBit bit) { + public boolean readBit(final int offset, @Nonnull final LayoutBit bit) { + + checkNotNull(bit, "expected non-null bit"); if (bit.isInvalid()) { return true; } - // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: - //ORIGINAL LINE: return (this.buffer[bit.GetOffset(offset)] & unchecked((byte)(1 << bit.GetBit()))) != 0; - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - return (this.buffer[bit.offset(offset)] & (byte) (1 << bit.bit())) != 0; + Item item = this.read(() -> (this.buffer.readByte() & (byte) (1 << bit.bit())) != 0, bit.offset(offset)); + return item.value(); + } + + public OffsetDateTime readDateTime(int offset) { + Item item = this.read(() -> DateTimeCodec.decode(this.buffer), offset); + return item.value(); } /** @@ -1752,17 +1746,23 @@ public final class RowBuffer { return this.validateHeader(version); } - public HybridRowHeader readHeader() { - HybridRowVersion version = HybridRowVersion.from(this.buffer.readByte()); - SchemaId schemaId = SchemaId.from(this.buffer.readIntLE()); - return new HybridRowHeader(version, schemaId); + public UUID readGuid(int offset) { + return this.read(() -> GuidCodec.decode(this.buffer), offset).value(); + } + + public HybridRowHeader readHeader(int offset) { + return this.read(this::readHeader, offset).value(); + } + + public short readInt16(int offset) { + return this.read(this.buffer::readShortLE, offset).value(); } public long readInt64(int offset) { - return MemoryMarshal.Read(this.buffer.Slice(offset)); + return this.read(this.buffer::readLongLE, offset).value(); } - public byte readInt8(int offset, Out lengthInBytes) { + public byte readInt8(int offset, @Nonnull Out lengthInBytes) { return this.read(this.buffer::readByte, offset, lengthInBytes); } @@ -1781,7 +1781,7 @@ public final class RowBuffer { public short readSparseInt16(RowCursor edit) { this.readSparsePrimitiveTypeCode(edit, LayoutTypes.INT_16); edit.endOffset(edit.valueOffset() + (Short.SIZE / Byte.SIZE)); - return this.ReadInt16(edit.valueOffset()); + return this.readInt16(edit.valueOffset()); } public int readSparseInt32(RowCursor edit) { @@ -1813,6 +1813,29 @@ public final class RowBuffer { return NullValue.Default; } + public int readSparsePathLen( + @Nonnull final Layout layout, final int offset, @Nonnull final Out pathLenInBytes, + @Nonnull final Out pathOffset) { + + checkNotNull(layout); + checkNotNull(pathOffset); + checkNotNull(pathLenInBytes); + + final Item item = this.read(this::read7BitEncodedUInt, offset); + final int token = item.value().intValue(); + + if (token < layout.tokenizer().count()) { + pathLenInBytes.set(item.length()); + pathOffset.set(offset); + return token; + } + + final int numBytes = token - layout.tokenizer().count(); + pathLenInBytes.set(numBytes + item.length()); + pathOffset.set(offset + item.length()); + return token; + } + public Utf8String readSparsePath(RowCursor edit) { final Optional path = edit.layout().tokenizer().tryFindString(edit.longValue().pathToken); @@ -1825,26 +1848,6 @@ public final class RowBuffer { return Utf8String.unsafeFromUtf8BytesNoValidation(this.buffer.Slice(edit.pathOffset(), numBytes)); } - public int readSparsePathLen( - @Nonnull final Layout layout, final int offset, @Nonnull final Out pathLenInBytes, - @Nonnull final Out pathOffset) { - - final int start = this.buffer.readerIndex(); - final int token = (int) this.read7BitEncodedUInt(); - final int end = this.buffer.readerIndex(); - - if (token < layout.tokenizer().count()) { - pathLenInBytes.set(end - start); - pathOffset.set(start); - return token; - } - - final int numBytes = token - layout.tokenizer().count(); - pathLenInBytes.set(numBytes + (end - start)); - pathOffset.set(end); - return token; - } - // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: //ORIGINAL LINE: [MethodImpl(MethodImplOptions.AggressiveInlining)] internal LayoutType ReadSparseTypeCode(int // offset) @@ -2181,7 +2184,7 @@ public final class RowBuffer { int shift; Out tempOut_shift = new Out(); this.ensureSparse(edit, LayoutTypes.FLOAT_32, TypeArgumentList.EMPTY, numBytes, options, tempOut_metaBytes, - tempOut_spaceNeeded, tempOut_shift); + tempOut_spaceNeeded, tempOut_shift); shift = tempOut_shift.get(); spaceNeeded = tempOut_spaceNeeded.get(); metaBytes = tempOut_metaBytes.get(); @@ -2198,7 +2201,7 @@ public final class RowBuffer { public void writeSparseTypeCode(int offset, LayoutCode code) { //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: //ORIGINAL LINE: this.WriteUInt8(offset, (byte)code); - this.WriteUInt8(offset, (byte) code.value()); + this.WriteUInt8(offset, code.value()); } /** @@ -2240,6 +2243,16 @@ public final class RowBuffer { return 1; } + /** + * Compute the number of bytes necessary to store the signed integer using the varint encoding. + * + * @param value The value to be encoded + * @return The number of bytes needed to store the varint encoding of {@code value} + */ + private static int Count7BitEncodedInt(long value) { + return RowBuffer.count7BitEncodedUInt(RowBuffer.rotateSignToLsb(value)); + } + /** * Compares the values of two encoded key-value pair fields using the hybrid row binary * collation. @@ -2306,14 +2319,14 @@ public final class RowBuffer { return this.CompareFieldValue(leftKey.clone(), leftKeyLen, rightKey.clone(), rightKeyLen); } - /** - * Compute the number of bytes necessary to store the signed integer using the varint encoding. - * - * @param value The value to be encoded - * @return The number of bytes needed to store the varint encoding of {@code value} - */ - private static int Count7BitEncodedInt(long value) { - return RowBuffer.count7BitEncodedUInt(RowBuffer.rotateSignToLsb(value)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private int WriteBinary(int offset, ReadOnlySpan value) + private int WriteBinary(int offset, ReadOnlySpan value) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: int sizeLenInBytes = this.Write7BitEncodedUInt(offset, (ulong)value.Length); + int sizeLenInBytes = this.write7BitEncodedUInt(offset, (long) value.Length); + value.CopyTo(this.buffer.Slice(offset + sizeLenInBytes)); + return sizeLenInBytes; } private void EnsureVariable(int offset, boolean isVarint, int numBytes, boolean exists, @@ -2420,11 +2433,9 @@ public final class RowBuffer { return true; } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: private ReadOnlySpan ReadBinary(int offset, out int sizeLenInBytes) - private ReadOnlySpan ReadBinary(int offset, Out sizeLenInBytes) { - int numBytes = (int) this.read7BitEncodedUInt(offset, sizeLenInBytes); - return this.buffer.Slice(offset + sizeLenInBytes.get(), numBytes); + private ByteBuf readBinary(int offset) { + Item item = this.read(this::read7BitEncodedUInt, offset); + return this.buffer.readSlice(item.length); } private Utf8Span ReadString(int offset, Out sizeLenInBytes) { @@ -2432,16 +2443,6 @@ public final class RowBuffer { return Utf8Span.UnsafeFromUtf8BytesNoValidation(this.buffer.Slice(offset + sizeLenInBytes.get(), numBytes)); } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: private int WriteBinary(int offset, ReadOnlySpan value) - private int WriteBinary(int offset, ReadOnlySpan value) { - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: int sizeLenInBytes = this.Write7BitEncodedUInt(offset, (ulong)value.Length); - int sizeLenInBytes = this.write7BitEncodedUInt(offset, (long) value.Length); - value.CopyTo(this.buffer.Slice(offset + sizeLenInBytes)); - return sizeLenInBytes; - } - //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: //ORIGINAL LINE: private int WriteBinary(int offset, ReadOnlySequence value) private int WriteBinary(int offset, ReadOnlySequence value) { @@ -2452,6 +2453,32 @@ public final class RowBuffer { return sizeLenInBytes; } + private static int countSparsePath(@Nonnull final RowCursor edit) { + + if (!edit.writePathToken().isNull()) { + StringToken token = edit.writePathToken(); + ByteBuf varint = token.varint(); + return varint.readerIndex() + varint.readableBytes(); + } + + Optional optional = edit.layout().tokenizer().findToken(edit.writePath()); + + if (optional.isPresent()) { + StringToken token = optional.get(); + edit.writePathToken(token); + ByteBuf varint = token.varint(); + return varint.readerIndex() + varint.readableBytes(); + } + + Utf8String path = edit.writePath().toUtf8(); + assert path != null; + + int numBytes = path.length(); + int sizeLenInBytes = RowBuffer.count7BitEncodedUInt(edit.layout().tokenizer().count() + numBytes); + + return sizeLenInBytes + numBytes; + } + /** * Return the size (in bytes) of the default sparse value for the type. * @@ -2550,32 +2577,6 @@ public final class RowBuffer { throw new IllegalStateException(lenientFormat("Not Implemented: %s", code)); } - private static int countSparsePath(@Nonnull final RowCursor edit) { - - if (!edit.writePathToken().isNull()) { - StringToken token = edit.writePathToken(); - ByteBuf varint = token.varint(); - return varint.readerIndex() + varint.readableBytes(); - } - - Optional optional = edit.layout().tokenizer().findToken(edit.writePath()); - - if (optional.isPresent()) { - StringToken token = optional.get(); - edit.writePathToken(token); - ByteBuf varint = token.varint(); - return varint.readerIndex() + varint.readableBytes(); - } - - Utf8String path = edit.writePath().toUtf8(); - assert path != null; - - int numBytes = path.length(); - int sizeLenInBytes = RowBuffer.count7BitEncodedUInt((long) (edit.layout().tokenizer().count() + numBytes)); - - return sizeLenInBytes + numBytes; - } - private void ensure(int size) { this.buffer.ensureWritable(size); } @@ -2685,11 +2686,25 @@ public final class RowBuffer { this.ensureSparse(edit, cellType, typeArgs, numBytes, rowOptions, metaBytes, spaceNeeded, shift); } - private T read(Supplier supplier, int offset, Out lengthInBytes) { + private Item read(@Nonnull final Supplier supplier, int offset) { + + checkNotNull(supplier); + this.buffer.readerIndex(offset); T value = supplier.get(); - lengthInBytes.set(this.buffer.readerIndex() - offset); - return value; + + return Item.of(value, offset, this.buffer.readerIndex() - offset); + } + + private T read(@Nonnull final Supplier supplier, int offset, @Nonnull Out lengthInBytes) { + + checkNotNull(supplier); + checkNotNull(lengthInBytes); + + Item item = this.read(supplier, offset); + lengthInBytes.set(item.length()); + + return item.value(); } private long read7BitEncodedUInt() { @@ -2713,6 +2728,12 @@ public final class RowBuffer { return result; } + private HybridRowHeader readHeader() { + HybridRowVersion version = HybridRowVersion.from(this.buffer.readByte()); + SchemaId schemaId = SchemaId.from(this.buffer.readIntLE()); + return new HybridRowHeader(version, schemaId); + } + /** * Read the metadata of an encoded sparse field. * @@ -2766,10 +2787,11 @@ public final class RowBuffer { edit.scopeType().readSparsePath(this, edit); } - private void readSparsePrimitiveTypeCode(@Nonnull RowCursor edit, LayoutType code) { + private void readSparsePrimitiveTypeCode(@Nonnull final RowCursor edit, @Nonnull final LayoutType code) { - checkNotNull(edit); - checkArgument(edit.exists()); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(code, "expected non-null code"); + checkArgument(edit.exists(), "expected edit.exists value of true, not false"); if (edit.scopeType().hasImplicitTypeCode(edit)) { if (edit.scopeType() instanceof LayoutNullable) { @@ -2788,8 +2810,8 @@ public final class RowBuffer { } } else { if (code == LayoutTypes.BOOLEAN) { - code = this.readSparseTypeCode(edit.metaOffset()); - checkState(code == LayoutTypes.BOOLEAN || code == LayoutTypes.BooleanFalse); + final LayoutType layoutType = this.readSparseTypeCode(edit.metaOffset()); + checkState(layoutType == LayoutTypes.BOOLEAN || layoutType == LayoutTypes.BooleanFalse); } else { checkState(this.readSparseTypeCode(edit.metaOffset()) == code); } @@ -2799,10 +2821,10 @@ public final class RowBuffer { checkState(edit.pathOffset() == 0); checkState(edit.pathToken() == 0); } else { + int offset = edit.metaOffset() + LayoutCode.SIZE; Out pathLenInBytes = new Out<>(); Out pathOffset = new Out<>(); - int token = this.readSparsePathLen(edit.layout(), edit.metaOffset() + (LayoutCode.SIZE / Byte.SIZE), - pathLenInBytes, pathOffset); + int token = this.readSparsePathLen(edit.layout(), offset, pathLenInBytes, pathOffset); checkState(edit.pathOffset() == pathOffset.get()); checkState(edit.pathToken() == token); } @@ -3165,6 +3187,35 @@ public final class RowBuffer { return sizeLenInBytes; } + private static class Item { + + private int length; + private int offset; + private T value; + + private Item(T value, int offset, int length) { + this.value = value; + this.offset = offset; + this.length = length; + } + + public int length() { + return this.length; + } + + public static Item of(T value, int offset, int length) { + return new Item<>(value, offset, length); + } + + public int offset() { + return this.offset; + } + + public T value() { + return this.value; + } + } + /** * Represents a single item within a set/map scope that needs to be indexed *

@@ -3182,11 +3233,11 @@ public final class RowBuffer { * The layout code of the value. */ public LayoutCode code() { - return Code; + return this.Code; } public UniqueIndexItem code(LayoutCode code) { - Code = code; + this.Code = code; return this; } @@ -3194,11 +3245,11 @@ public final class RowBuffer { * If existing, the offset to the metadata of the existing field, otherwise the location to insert a new field */ public int metaOffset() { - return MetaOffset; + return this.MetaOffset; } public UniqueIndexItem metaOffset(int metaOffset) { - MetaOffset = metaOffset; + this.MetaOffset = metaOffset; return this; } @@ -3206,11 +3257,11 @@ public final class RowBuffer { * Size of the target element */ public int size() { - return Size; + return this.Size; } public UniqueIndexItem size(int size) { - Size = size; + this.Size = size; return this; } @@ -3218,11 +3269,11 @@ public final class RowBuffer { * If existing, the offset to the value of the existing field, otherwise undefined */ public int valueOffset() { - return ValueOffset; + return this.ValueOffset; } public UniqueIndexItem valueOffset(int valueOffset) { - ValueOffset = valueOffset; + this.ValueOffset = valueOffset; return this; } } diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java index 5a33ce6..636f33b 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java @@ -372,7 +372,7 @@ public final class RowReader { Reference tempReference_cursor = new Reference(this.cursor); - value.setAndGet(this.row.ReadSparseBinary(tempReference_cursor)); + value.setAndGet(this.row.readSparseBinary(tempReference_cursor)); this.cursor = tempReference_cursor.get(); return Result.Success; default: @@ -399,7 +399,7 @@ public final class RowReader { Reference tempReference_cursor = new Reference(this.cursor); - value.setAndGet(this.row.ReadSparseBool(tempReference_cursor)); + value.setAndGet(this.row.readSparseBoolean(tempReference_cursor)); this.cursor = tempReference_cursor.get(); return Result.Success; default: @@ -426,7 +426,7 @@ public final class RowReader { Reference tempReference_cursor = new Reference(this.cursor); - value.setAndGet(this.row.ReadSparseDateTime(tempReference_cursor)); + value.setAndGet(this.row.readSparseDateTime(tempReference_cursor)); this.cursor = tempReference_cursor.get(); return Result.Success; default: diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java index 4c332ae..d52239b 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java @@ -57,7 +57,7 @@ public final class LayoutBinary extends LayoutType implements ILayoutSpa return Result.NotFound; } - value.setAndGet(b.get().ReadFixedBinary(scope.get().start() + col.getOffset(), col.getSize())); + value.setAndGet(b.get().readFixedBinary(scope.get().start() + col.getOffset(), col.getSize())); return Result.Success; } @@ -85,7 +85,7 @@ public final class LayoutBinary extends LayoutType implements ILayoutSpa return result; } - value.setAndGet(b.get().ReadSparseBinary(edit)); + value.setAndGet(b.get().readSparseBinary(edit)); return Result.Success; } diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java index 84957dc..c40a12e 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java @@ -35,7 +35,7 @@ public final class LayoutDateTime extends LayoutType { return Result.NotFound; } - value.setAndGet(b.get().ReadDateTime(scope.get().start() + col.getOffset())); + value.setAndGet(b.get().readDateTime(scope.get().start() + col.getOffset())); return Result.Success; } @@ -48,7 +48,7 @@ public final class LayoutDateTime extends LayoutType { return result; } - value.setAndGet(b.get().ReadSparseDateTime(edit)); + value.setAndGet(b.get().readSparseDateTime(edit)); return Result.Success; } diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java index 6e14fa6..e0c272a 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java @@ -65,7 +65,7 @@ public final class LayoutGuid extends LayoutType { } //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: - //ORIGINAL LINE: public override Result WriteSparse(ref RowBuffer b, ref RowCursor edit, Guid value, + //ORIGINAL LINE: public override Result WriteSparse(ref RowBuffer b, ref RowCursor edit, GuidCodec value, // UpdateOptions options = UpdateOptions.Upsert) @Override public Result writeSparse(RowBuffer b, RowCursor edit, UUID value, diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java index 25455d7..8e1a321 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java @@ -45,7 +45,7 @@ public final class LayoutUtf8 extends LayoutType implements ILayoutUtf8S return Result.NotFound; } - value.setAndGet(b.get().ReadFixedString(scope.get().start() + col.getOffset(), col.getSize())); + value.setAndGet(b.get().readFixedString(scope.get().start() + col.getOffset(), col.getSize())); return Result.Success; } diff --git a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java index 4eb831b..cb2b7be 100644 --- a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java +++ b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java @@ -44,9 +44,9 @@ public final class NullableUnitTests { t1.NullSet = new ArrayList(Arrays.asList(null, "abc", "def")); t1.NullTuple = new ArrayList<(Integer, Long) > (Arrays.asList((1, 2), (null, 3),(4, null),(null, null))) //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: t1.NullMap = new Dictionary> { { System.Guid.Parse - // ("{00000000-0000-0000-0000-000000000000}"), 1 }, { System.Guid.Parse - // ("{4674962B-CE11-4916-81C5-0421EE36F168}"), 20 }, { System.Guid.Parse + //ORIGINAL LINE: t1.NullMap = new Dictionary> { { System.GuidCodec.Parse + // ("{00000000-0000-0000-0000-000000000000}"), 1 }, { System.GuidCodec.Parse + // ("{4674962B-CE11-4916-81C5-0421EE36F168}"), 20 }, { System.GuidCodec.Parse // ("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), null }}; t1.NullMap = new HashMap(Map.ofEntries(Map.entry(UUID.fromString("{00000000-0000-0000-0000" + "-000000000000}"), 1), Map.entry(UUID.fromString("{4674962B-CE11-4916-81C5-0421EE36F168}"), 20), @@ -318,7 +318,7 @@ public final class NullableUnitTests { // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: if (c.typeAs().ReadScope(row, ref scope, out scope) == Result.Success) { //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: value.NullMap = new Dictionary>(); + //ORIGINAL LINE: value.NullMap = new Dictionary>(); value.NullMap = new HashMap(); RowCursor tupleScope = null; // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these @@ -621,7 +621,7 @@ public final class NullableUnitTests { ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref outerScope, c.typeArgs().clone(), out outerScope)); //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: foreach ((Guid key, Nullable itemValue) in value.NullMap) + //ORIGINAL LINE: foreach ((GuidCodec key, Nullable itemValue) in value.NullMap) for ((UUID key,Byte itemValue) :value.NullMap) { Reference tempReference_outerScope8 = @@ -690,7 +690,7 @@ public final class NullableUnitTests { public ArrayList NullArray; public ArrayList NullBool; //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: - //ORIGINAL LINE: public Dictionary> NullMap; + //ORIGINAL LINE: public Dictionary> NullMap; public HashMap NullMap; public ArrayList<(Integer,Long)>NullTuple public ArrayList NullSet;