- * This is equivalent to evaluating the expression {@code out.get() == null}. - * - * @return {@code true} if there is a value present, otherwise {@code false} - */ - public boolean isPresent() { - return this.value != null; - } - - /** - * Indicates whether some other object is equal to this {@link Out} value. - *
- * The other object is considered equal if: - *
+ * This is equivalent to evaluating the expression {@code out.get() == null}. + * + * @return {@code true} if there is a value present, otherwise {@code false} + */ + public boolean isPresent() { + return this.value != null; + } + + /** + * Indicates whether some other object is equal to this {@link Out} value. + *
+ * The other object is considered equal if: + *
- * The other object is considered equal if: - *
+ * The other object is considered equal if: + *
- * This type supports polymorphic use of {@link String} and {@link Utf8String} when equality, hashing, and comparison
- * are needed against either encoding. An API leveraging {@link UtfAnyString} can avoid separate method overloads
- * while still accepting either encoding without imposing additional allocations.
- */
-public final class UtfAnyString implements CharSequence, Comparable
- * An index ranges from zero to {@link UtfAnyString#length()} minus one. The first {@code char} value of the
- * sequence is at index zero, the next at index one, and so on, as for array indexing. If the {@code char}
- * value specified by the {@code index} is a surrogate, the surrogate (not the surrogate pair) is returned.
- *
- * @param index the index of the {@code char} value to be returned.
- * @return the specified {@code char} value
- * @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than
- * {@link UtfAnyString#length()}
- * @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}.
- */
- @Override
- public char charAt(final int index) {
- if (this.buffer == null) {
- throw new UnsupportedOperationException("String is null");
- }
- return this.buffer.charAt(index);
- }
-
- public int compareTo(@Nonnull final String other) {
-
- checkNotNull(other, "expected non-null other");
-
- if (other == this.buffer) {
- return 0;
- }
-
- if (this.buffer == null) {
- return -1;
- }
-
- return this.buffer instanceof String
- ? ((String) this.buffer).compareTo(other)
- : ((Utf8String) this.buffer).compareTo(other);
- }
-
- public int compareTo(@Nonnull final Utf8String other) {
-
- checkNotNull(other, "expected non-null other");
-
- if (other == this.buffer) {
- return 0;
- }
-
- if (this.buffer == null) {
- return -1;
- }
-
- return this.buffer instanceof String
- ? -other.compareTo((String) this.buffer)
- : ((Utf8String) this.buffer).compareTo(other);
- }
-
- @Override
- public int compareTo(@Nonnull final UtfAnyString other) {
-
- checkNotNull(other, "expected non-null other");
-
- if (other.buffer == this.buffer) {
- return 0;
- }
-
- if (other.buffer == null) {
- return 1;
- }
-
- if (this.buffer == null) {
- return -1;
- }
-
- if (this.buffer instanceof String) {
- return other.buffer instanceof String
- ? ((String) this.buffer).compareTo((String) other.buffer)
- : -((Utf8String) other.buffer).compareTo((String) this.buffer);
- }
-
- return ((Utf8String) this.buffer).compareTo((Utf8String) other.buffer);
- }
-
- public static UtfAnyString empty() {
- return EMPTY;
- }
-
- @Override
- public boolean equals(final Object other) {
-
- if (other == null) {
- return false;
- }
-
- if (other instanceof String) {
- return this.equals((String) other);
- }
-
- if (other instanceof Utf8String) {
- return this.equals((Utf8String) other);
- }
-
- if (other instanceof UtfAnyString) {
- return this.equals((UtfAnyString) other);
- }
-
- return false;
- }
-
- public boolean equals(final String other) {
-
- if (null == this.buffer) {
- return null == other;
- }
-
- if (this.buffer instanceof String) {
- return other.contentEquals(this.buffer); // skips the type check that String.equals performs
- }
-
- return ((Utf8String) this.buffer).equals(other);
- }
-
- public boolean equals(final Utf8String other) {
-
- if (null == other) {
- return null == this.buffer;
- }
-
- return other.equals(this.buffer);
- }
-
- public boolean equals(final UtfAnyString other) {
-
- if (null == other) {
- return false;
- }
-
- if (null == this.buffer) {
- return null == other.buffer;
- }
-
- return this.buffer instanceof String ? other.buffer.equals(this.buffer) : this.buffer.equals(other.buffer);
- }
-
- @Override
- public int hashCode() {
-
- final long[] hash = { 5_381, 5_381 };
-
- if (this.buffer == null) {
- return NULL_HASHCODE;
- }
-
- if (this.buffer instanceof String) {
-
- final int ignored = ((String) this.buffer).codePoints().reduce(0, (index, codePoint) -> {
- if (index % 2 == 0) {
- hash[0] = ((hash[0] << 5) + hash[0]) ^ codePoint;
- } else {
- hash[1] = ((hash[1] << 5) + hash[1]) ^ codePoint;
- }
- return index;
- });
-
- return reduceHashCode(hash[0], hash[1]);
- }
-
- return this.buffer.hashCode();
- }
-
- /**
- * Returns the length of this character sequence.
- *
- * The length is the number of 16-bit {@code char}s in the sequence.
- *
- * @return the number of {@code char}s in this sequence.
- * @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}.
- */
- @Override
- public int length() {
- if (this.buffer == null) {
- throw new UnsupportedOperationException("String is null");
- }
- return this.buffer.length();
- }
-
- /**
- * Returns a {@code CharSequence} that is a subsequence of this sequence.
- *
- * The subsequence starts with the {@code char} value at the specified index and ends with the{@code char} value at
- * index {@code end - 1}. The length (in {@code char}s) of the returned sequence is {@code end - start}, so if
- * {@code start == end}, an empty sequence is returned.
- *
- * @param start the start index, inclusive
- * @param end the end index, exclusive
- * @return the specified subsequence
- * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, {@code end} is greater than
- * {@link UtfAnyString#length()}, or {@code start} is greater than {@code
- * end}.
- * @throws UnsupportedOperationException if string is {@code null}
- */
- @Override
- @Nonnull
- public CharSequence subSequence(final int start, final int end) {
- if (this.buffer == null) {
- throw new UnsupportedOperationException("String is null");
- }
- return this.buffer.subSequence(start, end);
- }
-
- @Override
- @Nonnull
- public String toString() {
- return String.valueOf(this.buffer);
- }
-
- public String toUtf16() {
- if (null == this.buffer) {
- return null;
- }
- return this.buffer instanceof String ? (String) this.buffer : this.buffer.toString();
- }
-
- public Utf8String toUtf8() {
- if (null == this.buffer) {
- return null;
- }
- return this.buffer instanceof String ? transcodeUtf16((String) this.buffer) : (Utf8String) this.buffer;
- }
-
- private static int reduceHashCode(final long h1, final long h2) {
- return Long.valueOf(h1 + (h2 * 1_566_083_941L)).intValue();
- }
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.data.cosmos.core;
+
+import javax.annotation.Nonnull;
+
+import static com.azure.data.cosmos.core.Utf8String.transcodeUtf16;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A string whose memory representation may be either UTF-8 or UTF-16.
+ *
+ * This type supports polymorphic use of {@link String} and {@link Utf8String} when equality, hashing, and comparison
+ * are needed against either encoding. An API leveraging {@link UtfAnyString} can avoid separate method overloads
+ * while still accepting either encoding without imposing additional allocations.
+ */
+public final class UtfAnyString implements CharSequence, Comparable
+ * An index ranges from zero to {@link UtfAnyString#length()} minus one. The first {@code char} value of the
+ * sequence is at index zero, the next at index one, and so on, as for array indexing. If the {@code char}
+ * value specified by the {@code index} is a surrogate, the surrogate (not the surrogate pair) is returned.
+ *
+ * @param index the index of the {@code char} value to be returned.
+ * @return the specified {@code char} value
+ * @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than
+ * {@link UtfAnyString#length()}
+ * @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}.
+ */
+ @Override
+ public char charAt(final int index) {
+ if (this.buffer == null) {
+ throw new UnsupportedOperationException("String is null");
+ }
+ return this.buffer.charAt(index);
+ }
+
+ public int compareTo(@Nonnull final String other) {
+
+ checkNotNull(other, "expected non-null other");
+
+ if (other == this.buffer) {
+ return 0;
+ }
+
+ if (this.buffer == null) {
+ return -1;
+ }
+
+ return this.buffer instanceof String
+ ? ((String) this.buffer).compareTo(other)
+ : ((Utf8String) this.buffer).compareTo(other);
+ }
+
+ public int compareTo(@Nonnull final Utf8String other) {
+
+ checkNotNull(other, "expected non-null other");
+
+ if (other == this.buffer) {
+ return 0;
+ }
+
+ if (this.buffer == null) {
+ return -1;
+ }
+
+ return this.buffer instanceof String
+ ? -other.compareTo((String) this.buffer)
+ : ((Utf8String) this.buffer).compareTo(other);
+ }
+
+ @Override
+ public int compareTo(@Nonnull final UtfAnyString other) {
+
+ checkNotNull(other, "expected non-null other");
+
+ if (other.buffer == this.buffer) {
+ return 0;
+ }
+
+ if (other.buffer == null) {
+ return 1;
+ }
+
+ if (this.buffer == null) {
+ return -1;
+ }
+
+ if (this.buffer instanceof String) {
+ return other.buffer instanceof String
+ ? ((String) this.buffer).compareTo((String) other.buffer)
+ : -((Utf8String) other.buffer).compareTo((String) this.buffer);
+ }
+
+ return ((Utf8String) this.buffer).compareTo((Utf8String) other.buffer);
+ }
+
+ public static UtfAnyString empty() {
+ return EMPTY;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+
+ if (other == null) {
+ return false;
+ }
+
+ if (other instanceof String) {
+ return this.equals((String) other);
+ }
+
+ if (other instanceof Utf8String) {
+ return this.equals((Utf8String) other);
+ }
+
+ if (other instanceof UtfAnyString) {
+ return this.equals((UtfAnyString) other);
+ }
+
+ return false;
+ }
+
+ public boolean equals(final String other) {
+
+ if (null == this.buffer) {
+ return null == other;
+ }
+
+ if (this.buffer instanceof String) {
+ return other.contentEquals(this.buffer); // skips the type check that String.equals performs
+ }
+
+ return ((Utf8String) this.buffer).equals(other);
+ }
+
+ public boolean equals(final Utf8String other) {
+
+ if (null == other) {
+ return null == this.buffer;
+ }
+
+ return other.equals(this.buffer);
+ }
+
+ public boolean equals(final UtfAnyString other) {
+
+ if (null == other) {
+ return false;
+ }
+
+ if (null == this.buffer) {
+ return null == other.buffer;
+ }
+
+ return this.buffer instanceof String ? other.buffer.equals(this.buffer) : this.buffer.equals(other.buffer);
+ }
+
+ @Override
+ public int hashCode() {
+
+ final long[] hash = { 5_381, 5_381 };
+
+ if (this.buffer == null) {
+ return NULL_HASHCODE;
+ }
+
+ if (this.buffer instanceof String) {
+
+ final int ignored = ((String) this.buffer).codePoints().reduce(0, (index, codePoint) -> {
+ if (index % 2 == 0) {
+ hash[0] = ((hash[0] << 5) + hash[0]) ^ codePoint;
+ } else {
+ hash[1] = ((hash[1] << 5) + hash[1]) ^ codePoint;
+ }
+ return index;
+ });
+
+ return reduceHashCode(hash[0], hash[1]);
+ }
+
+ return this.buffer.hashCode();
+ }
+
+ /**
+ * Returns the length of this character sequence.
+ *
+ * The length is the number of 16-bit {@code char}s in the sequence.
+ *
+ * @return the number of {@code char}s in this sequence.
+ * @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}.
+ */
+ @Override
+ public int length() {
+ if (this.buffer == null) {
+ throw new UnsupportedOperationException("String is null");
+ }
+ return this.buffer.length();
+ }
+
+ /**
+ * Returns a {@code CharSequence} that is a subsequence of this sequence.
+ *
+ * The subsequence starts with the {@code char} value at the specified index and ends with the{@code char} value at
+ * index {@code end - 1}. The length (in {@code char}s) of the returned sequence is {@code end - start}, so if
+ * {@code start == end}, an empty sequence is returned.
+ *
+ * @param start the start index, inclusive
+ * @param end the end index, exclusive
+ * @return the specified subsequence
+ * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, {@code end} is greater than
+ * {@link UtfAnyString#length()}, or {@code start} is greater than {@code
+ * end}.
+ * @throws UnsupportedOperationException if string is {@code null}
+ */
+ @Override
+ @Nonnull
+ public CharSequence subSequence(final int start, final int end) {
+ if (this.buffer == null) {
+ throw new UnsupportedOperationException("String is null");
+ }
+ return this.buffer.subSequence(start, end);
+ }
+
+ @Override
+ @Nonnull
+ public String toString() {
+ return String.valueOf(this.buffer);
+ }
+
+ public String toUtf16() {
+ if (null == this.buffer) {
+ return null;
+ }
+ return this.buffer instanceof String ? (String) this.buffer : this.buffer.toString();
+ }
+
+ public Utf8String toUtf8() {
+ if (null == this.buffer) {
+ return null;
+ }
+ return this.buffer instanceof String ? transcodeUtf16((String) this.buffer) : (Utf8String) this.buffer;
+ }
+
+ private static int reduceHashCode(final long h1, final long h2) {
+ return Long.valueOf(h1 + (h2 * 1_566_083_941L)).intValue();
+ }
}
\ No newline at end of file
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java
similarity index 97%
rename from java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java
rename to experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java
index aeb75d4..5e694cb 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java
+++ b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java
@@ -1,55 +1,55 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.data.cosmos.serialization.hybridrow;
-
-/**
- * Represents an IEEE 754-2008 128-bit decimal floating point number.
- *
- * The {@link Float128} represents an IEEE 754-2008 floating point number as a pair of {@code long} values:
- * {@link #high()} and {@link #low()}.
- *
- * @see decimal128 floating-point format
- * @see 754-2008: IEEE Standard for Floating-Point Arithmetic
- * @see Decimal Arithmetic Encodings Version 1.01 – 7 Apr 2009
- */
-public final class Float128 {
-
- /**
- * The size (in bytes) of a {@link Float128}.
- */
- public static final int BYTES = 2 * Long.BYTES;
- public static final Float128 ZERO = new Float128(0L, 0L);
-
- private final long high;
- private final long low;
-
- /**
- * Initializes a new instance of the {@link Float128} struct.
- *
- * @param high the high-order 64 bits.
- * @param low the low-order 64 bits.
- */
- public Float128(long high, long low) {
- this.high = high;
- this.low = low;
- }
-
- /**
- * The high-order 64 bits of the IEEE 754-2008 128-bit decimal floating point, using the BID encoding scheme.
- *
- * @return the high-order 64 bits of the IEEE 754-2008 128-bit floating point number represented by this object.
- */
- public long high() {
- return this.high;
- }
-
- /**
- * The low-order 64 bits of the IEEE 754-2008 128-bit decimal floating point, using the BID encoding scheme.
- *
- * @return the low-order 64 bits of the IEEE 754-2008 128-bit floating point number represented by this object.
- */
- public long low() {
- return this.low;
- }
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.data.cosmos.serialization.hybridrow;
+
+/**
+ * Represents an IEEE 754-2008 128-bit decimal floating point number.
+ *
+ * The {@link Float128} represents an IEEE 754-2008 floating point number as a pair of {@code long} values:
+ * {@link #high()} and {@link #low()}.
+ *
+ * @see decimal128 floating-point format
+ * @see 754-2008: IEEE Standard for Floating-Point Arithmetic
+ * @see Decimal Arithmetic Encodings Version 1.01 – 7 Apr 2009
+ */
+public final class Float128 {
+
+ /**
+ * The size (in bytes) of a {@link Float128}.
+ */
+ public static final int BYTES = 2 * Long.BYTES;
+ public static final Float128 ZERO = new Float128(0L, 0L);
+
+ private final long high;
+ private final long low;
+
+ /**
+ * Initializes a new instance of the {@link Float128} struct.
+ *
+ * @param high the high-order 64 bits.
+ * @param low the low-order 64 bits.
+ */
+ public Float128(long high, long low) {
+ this.high = high;
+ this.low = low;
+ }
+
+ /**
+ * The high-order 64 bits of the IEEE 754-2008 128-bit decimal floating point, using the BID encoding scheme.
+ *
+ * @return the high-order 64 bits of the IEEE 754-2008 128-bit floating point number represented by this object.
+ */
+ public long high() {
+ return this.high;
+ }
+
+ /**
+ * The low-order 64 bits of the IEEE 754-2008 128-bit decimal floating point, using the BID encoding scheme.
+ *
+ * @return the low-order 64 bits of the IEEE 754-2008 128-bit floating point number represented by this object.
+ */
+ public long low() {
+ return this.low;
+ }
}
\ No newline at end of file
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java
similarity index 100%
rename from java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java
rename to experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java
similarity index 97%
rename from java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java
rename to experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java
index df3b078..be10a88 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java
+++ b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java
@@ -1,56 +1,56 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.data.cosmos.serialization.hybridrow;
-
-import javax.annotation.Nonnull;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Describes the header that precedes all valid Hybrid Rows.
- */
-public final class HybridRowHeader {
- /**
- * Size (in bytes) of a serialized header.
- */
- public static final int BYTES = HybridRowVersion.BYTES + SchemaId.BYTES;
-
- private final SchemaId schemaId;
- private final HybridRowVersion version;
-
- /**
- * Initializes a new instance of a {@link HybridRowHeader}.
- *
- * @param version The version of the HybridRow library used to write this row.
- * @param schemaId The unique identifier of the schema whose layout was used to write this row.
- */
- public HybridRowHeader(@Nonnull final HybridRowVersion version, @Nonnull SchemaId schemaId) {
-
- checkNotNull(version, "expected non-null version");
- checkNotNull(schemaId, "expected non-null schemaId");
-
- this.version = version;
- this.schemaId = schemaId;
- }
-
- /**
- * The unique identifier of the schema whose layout was used to write this {@link HybridRowHeader}.
- *
- * @return unique identifier of the schema whose layout was used to write this {@link HybridRowHeader}.
- */
- @Nonnull
- public SchemaId schemaId() {
- return this.schemaId;
- }
-
- /**
- * The version of the HybridRow serialization library used to write this {@link HybridRowHeader}.
- *
- * @return version of the HybridRow serialization library used to write this {@link HybridRowHeader}.
- */
- @Nonnull
- public HybridRowVersion version() {
- return this.version;
- }
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.data.cosmos.serialization.hybridrow;
+
+import javax.annotation.Nonnull;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Describes the header that precedes all valid Hybrid Rows.
+ */
+public final class HybridRowHeader {
+ /**
+ * Size (in bytes) of a serialized header.
+ */
+ public static final int BYTES = HybridRowVersion.BYTES + SchemaId.BYTES;
+
+ private final SchemaId schemaId;
+ private final HybridRowVersion version;
+
+ /**
+ * Initializes a new instance of a {@link HybridRowHeader}.
+ *
+ * @param version The version of the HybridRow library used to write this row.
+ * @param schemaId The unique identifier of the schema whose layout was used to write this row.
+ */
+ public HybridRowHeader(@Nonnull final HybridRowVersion version, @Nonnull SchemaId schemaId) {
+
+ checkNotNull(version, "expected non-null version");
+ checkNotNull(schemaId, "expected non-null schemaId");
+
+ this.version = version;
+ this.schemaId = schemaId;
+ }
+
+ /**
+ * The unique identifier of the schema whose layout was used to write this {@link HybridRowHeader}.
+ *
+ * @return unique identifier of the schema whose layout was used to write this {@link HybridRowHeader}.
+ */
+ @Nonnull
+ public SchemaId schemaId() {
+ return this.schemaId;
+ }
+
+ /**
+ * The version of the HybridRow serialization library used to write this {@link HybridRowHeader}.
+ *
+ * @return version of the HybridRow serialization library used to write this {@link HybridRowHeader}.
+ */
+ @Nonnull
+ public HybridRowVersion version() {
+ return this.version;
+ }
}
\ No newline at end of file
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java
similarity index 96%
rename from java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java
rename to experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java
index f60b370..8c038e5 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java
+++ b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java
@@ -1,50 +1,50 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.data.cosmos.serialization.hybridrow;
-
-import com.google.common.base.Suppliers;
-import it.unimi.dsi.fastutil.bytes.Byte2ReferenceMap;
-import it.unimi.dsi.fastutil.bytes.Byte2ReferenceOpenHashMap;
-
-import java.util.function.Supplier;
-
-/**
- * Versions of HybridRow.
- *
- * A version from this list MUST be inserted in the version BOM at the beginning of all rows.
- */
-public enum HybridRowVersion {
-
- INVALID((byte)0),
-
- /**
- * Initial version of the HybridRow format.
- */
- V1((byte)0x81);
-
- public static final int BYTES = Byte.BYTES;
-
- private static final Supplier
+ * A version from this list MUST be inserted in the version BOM at the beginning of all rows.
+ */
+public enum HybridRowVersion {
+
+ INVALID((byte)0),
+
+ /**
+ * Initial version of the HybridRow format.
+ */
+ V1((byte)0x81);
+
+ public static final int BYTES = Byte.BYTES;
+
+ private static final Supplier
- * May be stored hybrid row to indicate the literal null value. Typically this value should not be used and the
- * corresponding column should be absent from the row.
- */
-public final class NullValue {
- /**
- * The default null literal.
- * This is the same value as default({@link NullValue}).
- */
- public static final NullValue DEFAULT = new NullValue();
-
- /**
- * Returns true if this is the same value as {@code other}.
- *
- * @param other The value to compare against.
- * @return True if the two values are the same.
- */
- public boolean equals(NullValue other) {
- return true;
- }
-
- @Override
- public boolean equals(Object other) {
- if (null == other) {
- return false;
- }
- return other instanceof NullValue && this.equals((NullValue)other);
- }
-
- @Override
- public int hashCode() {
- return 42;
- }
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.data.cosmos.serialization.hybridrow;
+
+/**
+ * The literal null value.
+ *
+ * May be stored hybrid row to indicate the literal null value. Typically this value should not be used and the
+ * corresponding column should be absent from the row.
+ */
+public final class NullValue {
+ /**
+ * The default null literal.
+ * This is the same value as default({@link NullValue}).
+ */
+ public static final NullValue DEFAULT = new NullValue();
+
+ /**
+ * Returns true if this is the same value as {@code other}.
+ *
+ * @param other The value to compare against.
+ * @return True if the two values are the same.
+ */
+ public boolean equals(NullValue other) {
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (null == other) {
+ return false;
+ }
+ return other instanceof NullValue && this.equals((NullValue)other);
+ }
+
+ @Override
+ public int hashCode() {
+ return 42;
+ }
}
\ No newline at end of file
diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java
similarity index 96%
rename from java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java
rename to experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java
index 50843a2..19323d0 100644
--- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java
+++ b/experimental/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java
@@ -1,74 +1,74 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.data.cosmos.serialization.hybridrow;
-
-import com.google.common.base.Suppliers;
-import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
-import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
-import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
-
-import java.util.Arrays;
-import java.util.function.Supplier;
-
-public enum Result {
-
- SUCCESS(0),
- FAILURE(1),
- NOT_FOUND(2),
- EXISTS(3),
- TOO_BIG(4),
-
- /**
- * The type of an existing field does not match the expected type for this operation.
- */
- TYPE_MISMATCH(5),
-
- /**
- * An attempt to write in a read-only scope.
- */
- INSUFFICIENT_PERMISSIONS(6),
-
- /**
- * An attempt to write a field that did not match its (optional) type constraints.
- */
- TYPE_CONSTRAINT(7),
-
- /**
- * The byte sequence could not be parsed as a valid row.
- */
- INVALID_ROW(8),
-
- /**
- * The byte sequence was too short for the requested action.
- */
- INSUFFICIENT_BUFFER(9),
-
- /**
- * The operation was cancelled.
- */
- CANCELED(10);
-
- public static final int BYTES = Integer.BYTES;
-
- private static final Supplier
- * A Hybrid Row begins in the 0-th byte of the {@link RowBuffer}. The sequence of bytes is defined by the Hybrid Row
- * grammar.
- */
-public final class RowBuffer {
-
- private final ByteBuf buffer;
- private LayoutResolver resolver;
-
- /**
- * Initializes a new instance of a {@link RowBuffer}.
- *
- * @param capacity Initial buffer capacity.
- */
- public RowBuffer(int capacity) {
- this(capacity, ByteBufAllocator.DEFAULT);
- }
-
- /**
- * Initializes a new instance of a {@link RowBuffer}.
- *
- * @param capacity Initial buffer capacity
- * @param allocator A buffer allocator
- */
- public RowBuffer(final int capacity, @Nonnull final ByteBufAllocator allocator) {
- checkArgument(capacity > 0, "capacity: %s", capacity);
- checkNotNull(allocator, "expected non-null allocator");
- this.buffer = allocator.buffer(capacity);
- this.resolver = null;
- }
-
- /**
- * Initializes a new instance of a {@link RowBuffer} from an existing buffer.
- *
- * @param buffer An existing {@link ByteBuf} containing a Hybrid Row. This instance takes ownership of the buffer.
- * Hence, the caller should not maintain a reference to the buffer or mutate the buffer after this
- * call returns.
- * @param version The version of the Hybrid Row format to use for encoding the buffer.
- * @param resolver The resolver for UDTs.
- */
- public RowBuffer(
- @Nonnull final ByteBuf buffer,
- @Nonnull final HybridRowVersion version,
- @Nonnull final LayoutResolver resolver) {
-
- checkNotNull(buffer, "expected non-null buffer");
- checkNotNull(version, "expected non-null version");
- checkNotNull(resolver, "expected non-null resolver");
-
- final int length = buffer.writerIndex();
-
- checkArgument(length >= HybridRowHeader.BYTES,
- "expected buffer with at least %s, not %s bytes", HybridRowHeader.BYTES, length);
-
- this.buffer = buffer;
- this.resolver = resolver;
-
- final Item
- * The field is interpreted as either a variable-length integer or a variable-length sequence of bytes as indicated
- * by the value of {@code isVarint}.
- *
- * @param offset index of the field in this {@link RowBuffer}
- * @param isVarint {@code true}, if the field should be interpreted as a variable-length integer value;
- * {@code false}, if the field should be interpreted as a variable-length sequence of bytes.
- */
- public void deleteVariable(final int offset, final boolean isVarint) {
-
- final Item
- * The row is initialized to default row for the given layout. All fixed columns have their
- * default values. All variable columns are null. No sparse columns are present. The row is
- * valid.
- */
- public void initLayout(HybridRowVersion version, Layout layout, LayoutResolver resolver) {
-
- checkNotNull(version, "expected non-null version");
- checkNotNull(layout, "expected non-null layout");
- checkNotNull(resolver, "expected non-null resolver");
-
- this.writeHeader(new HybridRowHeader(version, layout.schemaId()));
- this.buffer.writeZero(layout.size());
- this.resolver = resolver;
- }
-
- /**
- * The length of this {@link RowBuffer} in bytes.
- *
- * @return The length of this {@link RowBuffer} in bytes.
- */
- public int length() {
- return this.buffer.writerIndex();
- }
-
- /**
- * Compute the byte offsets from the beginning of the row for a given sparse field insertion.
- * into a set/map.
- *
- * @param scope The sparse scope to insert into.
- * @param srcEdit The field to move into the set/map.
- * @return The prepared edit context.
- */
- @Nonnull
- public RowCursor prepareSparseMove(@Nonnull final RowCursor scope, @Nonnull final RowCursor srcEdit) {
-
- checkNotNull(srcEdit, "expected non-null srcEdit");
- checkNotNull(scope, "expected non-null scope");
- checkArgument(scope.index() == 0);
- checkArgument(scope.scopeType().isUniqueScope());
-
- RowCursor dstEdit = scope.clone().metaOffset(scope.valueOffset());
- int srcSize = this.sparseComputeSize(srcEdit);
- int srcBytes = srcSize - (srcEdit.valueOffset() - srcEdit.metaOffset());
-
- while (dstEdit.index() < dstEdit.count()) {
-
- this.readSparseMetadata(dstEdit);
- checkState(dstEdit.pathOffset() == 0);
-
- int elmSize = -1; // defer calculating the full size until needed
- int cmp;
-
- if (scope.scopeType() instanceof LayoutTypedMap) {
- cmp = this.compareKeyValueFieldValue(srcEdit, dstEdit);
- } else {
- elmSize = this.sparseComputeSize(dstEdit);
- int elmBytes = elmSize - (dstEdit.valueOffset() - dstEdit.metaOffset());
- cmp = this.compareFieldValue(srcEdit, srcBytes, dstEdit, elmBytes);
- }
-
- if (cmp <= 0) {
- dstEdit.exists(cmp == 0);
- return dstEdit;
- }
-
- elmSize = elmSize == -1 ? this.sparseComputeSize(dstEdit) : elmSize;
- dstEdit.index(dstEdit.index() + 1);
- dstEdit.metaOffset(dstEdit.metaOffset() + elmSize);
- }
-
- dstEdit.exists(false);
- dstEdit.cellType(LayoutTypes.END_SCOPE);
- dstEdit.valueOffset(dstEdit.metaOffset());
-
- return dstEdit;
- }
-
- /**
- * Read the value of a bit within the bit field at the given {@code offset} within this {@link RowBuffer}.
- *
- * @param offset offset of a bit field within this {@link RowBuffer}.
- * @param bit the bit to read.
- * @return {@code true} if the {@code bit} is set, otherwise {@code false}.
- */
- public boolean readBit(final int offset, @Nonnull final LayoutBit bit) {
-
- checkNotNull(bit, "expected non-null bit");
-
- if (bit.isInvalid()) {
- return true;
- }
-
- Item
- * The {@link RowBuffer} is initialized with the associated layout and row {@code version}.
- *
- * @param inputStream the stream from which the contents of the current {@link RowBuffer} should be read
- * @param byteCount the number of bytes to be read from the {@code inputStream}
- * @param version the {@link HybridRowVersion} to be assigned to the current {@link RowBuffer}
- * @param resolver the layout resolver to be used in parsing the {@code inputStream}
- * @return {@code true} if the read succeeded; otherwise, if the {@link InputStream} was corrupted, {@code false}
- */
- public boolean readFrom(
- @Nonnull final InputStream inputStream, final int byteCount, @Nonnull final HybridRowVersion version,
- @Nonnull final LayoutResolver resolver) {
-
- checkNotNull(inputStream, "expected non-null inputStream");
- checkNotNull(resolver, "expected non-null resolver");
- checkNotNull(version, "expected non-null version");
- checkState(byteCount >= HybridRowHeader.BYTES, "expected byteCount >= %s, not %s", HybridRowHeader.BYTES,
- byteCount);
-
- this.reset();
- this.ensure(byteCount);
- this.resolver = resolver;
-
- final int bytesRead;
-
- try {
- bytesRead = this.buffer.writeBytes(inputStream, byteCount);
- } catch (IOException error) {
- return false;
- }
-
- if (bytesRead != byteCount) {
- return false;
- }
-
- return this.validateHeader(version);
- }
-
- /**
- * Reads the contents of the current {@link RowBuffer} from a {@link ByteBuf}.
- *
- * The {@link RowBuffer} is initialized with a copy of the specified input {@link ByteBuf} and the associated layout
- * and row {@code version}.
- *
- * @param input the buffer from which the contents of the current {@link RowBuffer} should be read
- * @param version the {@link HybridRowVersion} to be assigned to the current {@link RowBuffer}
- * @param resolver the layout resolver to be used in parsing the {@code inputStream}
- * @return {@code true} if the read succeeded; otherwise, if the {@link InputStream} was corrupted, {@code false}
- */
- public boolean readFrom(
- @Nonnull final ByteBuf input, @Nonnull final HybridRowVersion version, @Nonnull final LayoutResolver resolver) {
-
- checkNotNull(input, "expected non-null input");
- checkNotNull(version, "expected non-null version");
- checkNotNull(resolver, "expected non-null resolver");
- checkState(input.readableBytes() >= HybridRowHeader.BYTES);
-
- this.reset();
- this.resolver = resolver;
- this.buffer.writeBytes(this.buffer);
-
- return this.validateHeader(version);
- }
-
- /**
- * Read the value of a {@code Guid} field at the given {@code offset} within this {@link RowBuffer}.
- *
- * @param offset offset of a {@code Guid} field within this {@link RowBuffer}.
- * @return the {@code Guid} value read.
- */
- public UUID readGuid(int offset) {
- return this.read(() -> GuidCodec.decode(this.buffer), offset).value();
- }
-
- /**
- * Read the value of a {@code Header} field at the given {@code offset} within this {@link RowBuffer}.
- *
- * @param offset offset of a {@code Header} field within this {@link RowBuffer}.
- * @return the {@code Header} value read.
- */
- public HybridRowHeader readHeader(int offset) {
- return this.read(this::readHeader, offset).value();
- }
-
- /**
- * Read the value of a {@code Int16} field at the given {@code offset} within this {@link RowBuffer}.
- *
- * @param offset offset of a {@code Int16} field within this {@link RowBuffer}.
- * @return the {@code Int16} value read.
- */
- public short readInt16(int offset) {
- return this.read(this.buffer::readShortLE, offset).value();
- }
-
- /**
- * Read the value of a {@code Int32} field at the given {@code offset} within this {@link RowBuffer}.
- *
- * @param offset offset of a {@code Int32} field within this {@link RowBuffer}.
- * @return the {@code Int32} value read.
- */
- public int readInt32(int offset) {
- Item
- * Moves the signed bit of a two's complement value to the least significant bit (LSB) by:
- *
- * The {@code scope} MUST be a set or map scope.
- *
- * The scope may have been built (e.g. via RowWriter) with relaxed uniqueness constraint checking.
- * This operation rebuilds an index to support verification of uniqueness constraints during
- * subsequent partial updates. If the appropriate uniqueness constraints cannot be established (i.e.
- * a duplicate exists), this operation fails. Before continuing, the resulting scope should either:
- *
- * The target {@code scope} may or may not have already been indexed. This operation is idempotent.
- */
- @Nonnull
- public Result typedCollectionUniqueIndexRebuild(@Nonnull final RowCursor scope) {
-
- checkNotNull(scope, "expected non-null scope");
- checkArgument(scope.scopeType().isUniqueScope(), "expected unique scope type");
- checkArgument(scope.index() == 0, "expected scope index of zero");
-
- RowCursor edit = scope.clone();
-
- if (edit.count() <= 1) {
- return Result.SUCCESS;
- }
-
- // Compute index elements
-
- UniqueIndexItem[] uniqueIndex = new UniqueIndexItem[edit.count()];
- edit.metaOffset(scope.valueOffset());
-
- for (; edit.index() < edit.count(); edit.index(edit.index() + 1)) {
-
- final RowCursor dstEdit = new RowCursor();
- this.readSparseMetadata(dstEdit);
-
- checkState(edit.pathOffset() == 0);
-
- final int elementSize = this.sparseComputeSize(edit);
-
- uniqueIndex[edit.index()] = new UniqueIndexItem()
- .code(edit.cellType().layoutCode())
- .metaOffset(edit.metaOffset())
- .valueOffset(edit.valueOffset())
- .size(elementSize);
-
- edit.metaOffset(edit.metaOffset() + elementSize);
- }
-
- // Create scratch space equal to the sum of the sizes of the scope's values.
- // Implementation Note: theoretically this scratch space could be eliminated by
- // performing the item move operations directly during the Insertion Sort, however,
- // doing so might result in moving the same item multiple times. Under the assumption
- // that items are relatively large, using scratch space requires each item to be moved
- // AT MOST once. Given that row buffer memory is likely reused, scratch space is
- // relatively memory efficient.
-
- int shift = edit.metaOffset() - scope.valueOffset();
-
- // Sort and check for duplicates
-
- if (!this.insertionSort(scope, edit, Arrays.asList(uniqueIndex))) {
- return Result.EXISTS;
- }
-
- // Move elements
-
- int metaOffset = scope.valueOffset();
- this.ensure(this.length() + shift);
- this.writeFixedBinary(metaOffset + shift, this.buffer, metaOffset, this.length() - metaOffset);
-
- for (UniqueIndexItem item : uniqueIndex) {
- this.writeFixedBinary(metaOffset, this.buffer, item.metaOffset() + shift, item.size());
- metaOffset += item.size();
- }
-
- // Delete the scratch space (if necessary - if it doesn't just fall off the end of the row)
-
- if (metaOffset != this.length()) {
- this.writeFixedBinary(metaOffset, this.buffer, metaOffset + shift, this.length() - metaOffset);
- }
-
- return Result.SUCCESS;
- }
-
- public void unsetBit(final int offset, @Nonnull final LayoutBit bit) {
- checkNotNull(bit, "expected non-null bit");
- checkArgument(!bit.isInvalid());
- final int index = bit.offset(offset);
- this.buffer.setByte(index, this.buffer.getByte(index) & (byte) ~(1 << bit.bit()));
- }
-
- public int write7BitEncodedInt(final long value) {
- return this.write7BitEncodedUInt(RowBuffer.rotateSignToLsb(value));
- }
-
- /**
- * Sets the specified 64-bit integer at the current {@link RowBuffer position} as a 7-bit encoded 32-bit value.
- *
- * The 64-bit integer value is written 7-bits at a time. The high bit of the byte, when set, indicates there are
- * more bytes. An {@link IllegalArgumentException} is thrown, if the specified 64-bit integer value is outside
- * the range of an unsigned 32-bit integer, [0, 0x00000000FFFFFFFFL].
- *
- * @param value a 64-bit integer constrained to the range of an unsigned 32-bit integer, [0, 0x00000000FFFFFFFFL]
- * @return The number of bytes written
- */
- public int write7BitEncodedUInt(final long value) {
- checkArgument(0 <= value && value <= 0x00000000FFFFFFFFL, "expected value in range [0, %s], not %s", 0x00000000FFFFFFFFL, value);
- long n = value;
- int i = 0;
- while (n >= 0x80L) {
- this.buffer.writeByte((byte) (n | 0x80L));
- n >>>= 7;
- }
- this.buffer.writeByte((byte) n);
- return i;
- }
-
- public void writeDateTime(int offset, OffsetDateTime value) {
- Item
- *
- */
- public static long rotateSignToLsb(long value) {
- boolean isNegative = value < 0;
- long unsignedValue = value;
- unsignedValue = isNegative ? ((~unsignedValue + 1) << 1) + 1 : unsignedValue << 1;
- return unsignedValue;
- }
-
- /**
- * Undoes the rotation introduced by {@link #rotateSignToLsb}.
- *
- * @param unsignedValue An unsigned value with the sign bit in the LSB.
- * @return A signed two's complement value encoding the same value.
- */
- public static long rotateSignToMsb(long unsignedValue) {
- boolean isNegative = unsignedValue % 2 != 0;
- return isNegative ? (~(unsignedValue >>> 1) + 1) | 0x8000000000000000L : unsignedValue >>> 1;
- }
-
- // TODO: DANOBLE: Support MongoDbObjectId values
- // public void WriteMongoDbObjectId(int offset, MongoDbObjectId value) {
- // Reference
- *
- * Failure to perform one of these actions will leave the row is potentially in a corrupted state where partial
- * updates may subsequent fail.
- *