Skip to content

feat: add deep-array value-equality helpers in sdk-core#149

Merged
OmarAlJarrah merged 3 commits into
mainfrom
feat/deep-array-value-equality
Jun 21, 2026
Merged

feat: add deep-array value-equality helpers in sdk-core#149
OmarAlJarrah merged 3 commits into
mainfrom
feat/deep-array-value-equality

Conversation

@OmarAlJarrah

Copy link
Copy Markdown
Member

Summary

Adds ValueEquality to org.dexpace.sdk.core.util — content-deep contentEquals / contentHashCode helpers for value types that hold array-typed fields.

java.util.Objects.equals/hashCode compare arrays by identity, so two structurally-equal ByteArray fields (or any array-typed field) are reported unequal and hash differently. A value type with array fields therefore cannot rely on Objects.equals for a correct equals/hashCode. These helpers compare by content instead.

Behavior

  • contentEquals(a, b) / contentHashCode(value), both @JvmStatic and null-safe (two nulls equal; null hashes to 0).
  • Primitive arrays (ByteArray, IntArray, DoubleArray, …) compared by element value.
  • Object arrays compared with Arrays.deepEquals / deepHashCode, so nested and arbitrarily-deep multi-dimensional arrays compare structurally, and object-array elements use their own equals.
  • Distinct array kinds (object vs primitive, IntArray vs LongArray) are not equal even with matching values, mirroring the JVM's distinct array types.
  • Non-array values fall back to ordinary equals/hashCode.
  • The two methods are mutually consistent: whenever contentEquals(a, b) is true, contentHashCode(a) == contentHashCode(b).

No core type needs it today; it is the hand-usable runtime primitive a DTO generator (or a hand-written value type) targets for array fields. No code generation is introduced.

Tests

ValueEqualityTest covers nulls, identity shortcut, scalars, every primitive-array kind, object arrays (including null elements), nested object arrays, nested primitive arrays, deeply-nested multi-dimensional arrays, custom value-type elements, cross-kind mismatches, and equals/hashCode consistency.

Gated build (module-scoped)

./gradlew :sdk-core:test :sdk-core:ktlintCheck :sdk-core:detekt :sdk-core:apiDump --no-daemon
./gradlew :sdk-core:apiCheck --no-daemon

Both BUILD SUCCESSFUL. The regenerated sdk-core/api/sdk-core.api snapshot is committed.

Closes #49

Add ValueEquality.contentEquals / contentHashCode to org.dexpace.sdk.core.util
for value types that hold array-typed fields. java.util.Objects.equals compares
arrays by identity, so structurally-equal ByteArray (or any array) fields are
wrongly reported unequal; these helpers compare by content instead.

Both helpers handle primitive arrays, object arrays, nulls, and arbitrarily-deep
nested / multi-dimensional arrays (via Arrays.deepEquals / deepHashCode), while
falling back to ordinary equals/hashCode for non-array values. The two methods
are mutually consistent: content-equal values always share a content hash.
…semantics

contentEquals reimplemented java.util.Objects.deepEquals branch for branch, so delegate to it directly instead. Document that array comparison follows Arrays.equals/Double.equals semantics rather than ==: NaN compares equal and 0.0 != -0.0, for both primitive and boxed arrays. Note that contentHashCode mirrors Arrays.deepHashCode by hand and is kept in lockstep with contentEquals.

Add tests for NaN and signed zero across primitive and boxed float/double arrays, plus nested arrays, mixed elements, and non-canonical NaN bit patterns.
… ValueEquality

Expand the ValueEquality KDoc to answer the three questions a reader is most
likely to have about it:

- Why it is public with no in-tree caller: it is a deliberate, forward-looking
  primitive that hand-written (or later generated) value types target for their
  array-typed fields.
- Why contentEquals is a thin wrapper over Objects.deepEquals: to pair
  symmetrically with contentHashCode, for which the JDK offers no
  Objects.deepHashCode counterpart, giving callers one contract-paired API.
- That Kotlin unsigned arrays (UByteArray, etc.) are not recognized as arrays
  and fall through to identity-based equals/hashCode, with the asXxxArray()
  workaround for content semantics.

Doc-only; no signature or behavior change (apiCheck unchanged).
@OmarAlJarrah OmarAlJarrah merged commit 901ee7f into main Jun 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a deep-array contentEquals/contentHashCode value-equality utility

1 participant