diff --git a/Sources/ContainerizationOCI/Platform.swift b/Sources/ContainerizationOCI/Platform.swift index a9c17482..b52d385f 100644 --- a/Sources/ContainerizationOCI/Platform.swift +++ b/Sources/ContainerizationOCI/Platform.swift @@ -277,7 +277,14 @@ extension Platform: Hashable { } public func hash(into hasher: inout Swift.Hasher) { - hasher.combine(description) + hasher.combine(os) + hasher.combine(architecture) + // arm64 with no variant is equivalent to arm64/v8 per the == implementation + if architecture == "arm64" { + hasher.combine(variant ?? "v8") + } else { + hasher.combine(variant) + } } } diff --git a/Tests/ContainerizationOCITests/OCIPlatformTests.swift b/Tests/ContainerizationOCITests/OCIPlatformTests.swift index 8977a526..7ffebedc 100644 --- a/Tests/ContainerizationOCITests/OCIPlatformTests.swift +++ b/Tests/ContainerizationOCITests/OCIPlatformTests.swift @@ -66,4 +66,19 @@ struct OCIPlatformTests { let rhs = Platform(arch: "arm64", os: "linux", variant: nil) #expect(lhs == rhs, "Both nil variants => variantEqual is true => overall equal") } + + @Test func arm64_nilAndV8_sameHashValue() { + let withoutVariant = Platform(arch: "arm64", os: "linux", variant: nil) + let withV8 = Platform(arch: "arm64", os: "linux", variant: "v8") + // Equal platforms must produce the same hash — violating this breaks Set/Dictionary lookups + #expect(withoutVariant.hashValue == withV8.hashValue, "arm64 nil variant and v8 must hash identically") + } + + @Test func arm64_nilAndV8_setLookup() { + let withoutVariant = Platform(arch: "arm64", os: "linux", variant: nil) + let withV8 = Platform(arch: "arm64", os: "linux", variant: "v8") + var set = Set() + set.insert(withoutVariant) + #expect(set.contains(withV8), "arm64/v8 must be found in a Set that contains arm64 with nil variant") + } }