Skip to content

Compare Feature property values in equality - #235

Merged
trasch merged 6 commits into
mainfrom
feature_deep_equality
Sep 10, 2026
Merged

trasch merged 6 commits into
mainfrom
feature_deep_equality

Conversation

@trasch

@trasch trasch commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Closes #232. Completes #231. Stacked on #234.

What

Feature.== now compares property values, not just keys (resolving the keys-only TODO in Feature.swift):

  • Values are compared after JSONValue normalization, so a property stored as 3.0 equals one stored as 3, and nested objects/arrays compare deeply.
  • Values that are not JSON-compatible (e.g. Data) are regarded as equal when present on both sides — keeping == reflexive, documented on the API.
  • Feature.hash(into:) hashes the normalized values (non-JSON-compatible values hash to a fixed bucket, consistent with the == fallback).

Behavior change

Features with the same property keys but different values were previously regarded as equal (documented keys-only behavior); they are now unequal. Code relying on that (e.g. Set/Dictionary semantics) would observe different results — see #232 for the compatibility discussion; a semver bump is appropriate for the release containing this.

Verification

  • Full suite passes (2410 tests), including the existing JSON round-trip equality tests — parsed/encoded features compare equal under the deep semantics thanks to value normalization.
  • New tests: value differences → unequal, normalized numeric equality (3 vs 3.0), deep nested comparison, non-JSON fallback + reflexivity, Set<Feature> deduplication.

The hash is based on a rotation-canonical, quantized representation of
the ring vertices, consistent with the shift-insensitive equality of
these types (compareShifted). Purely additive, no behavior changes.
- JSONValue: a Hashable/Sendable/Codable JSON value enum with numeric
  normalization (3.0 == 3), created from property-style Sendable values
- properties(as:)/foreignMembers(as:): decode into any Decodable type,
  with JSONDecoder strategy support and real DecodingErrors
- jsonValue(for:)/jsonForeignMember(for:): pattern matching accessors
- intValue/doubleValue/boolValue/stringValue(for:) and foreign member
  equivalents: coercing scalar accessors
- Feature(encodedProperties:): create a Feature from Encodable
  properties (distinct label to keep dictionary-literal call sites
  resolving to the [String: Sendable] initializer)
- Hashable conformances for Point, MultiPoint, LineString,
  MultiLineString, GeometryCollection, Feature, and FeatureCollection,
  consistent with their Equatable implementations
- Existing accessors and Equatable behavior are unchanged
Two features are now equal when their property values match, compared
after JSONValue normalization (a property stored as 3.0 equals one
stored as 3). Values that are not JSON-compatible (e.g. Data) are
regarded as equal when present on both sides, keeping == reflexive.
The Feature hash is updated accordingly.

Note: this is a behavior change — features with the same property keys
but different values were previously regarded as equal.

Resolves the keys-only equality TODO in Feature.
@trasch
trasch marked this pull request as draft September 7, 2026 14:49
@trasch trasch self-assigned this Sep 7, 2026
@trasch trasch added the enhancement New feature or request label Sep 7, 2026
Base automatically changed from typed_properties to main September 10, 2026 11:22
Resolve conflicts: keep the deep property-value equality (== and hash)
from this branch, adopt the JSONValue extensions, bulk jsonProperties()/
jsonForeignMembers() conversions, and tests from main (#234). Also fix
pre-existing redundant #require warnings in PolygonTests.
@trasch
trasch marked this pull request as ready for review September 10, 2026 11:44
@trasch
trasch merged commit 8cdecaa into main Sep 10, 2026
1 check passed
@trasch
trasch deleted the feature_deep_equality branch September 10, 2026 11:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deep Feature equality: compare property values

1 participant