InlineArray conformance to common protocols

Are there plans to make InlineArray conforming to standard protocols?

'[3 of Int]' does not conform to protocol 'Equatable'
'[3 of Int]' does not conform to 'Encodable'
'[3 of Int]' does not conform to 'Decodable'
4 Likes

See the relevant proposal text:

7 Likes

Thank you, good to know.

Until it is properly implemented I guess I could roll my own conformances, like these:

import Foundation

extension InlineArray: @retroactive Equatable where Element: Equatable {
    public static func == (lhs: Self, rhs: Self) -> Bool {
        !(0 ..< Self.count).contains { lhs[$0] != rhs[$0] }
    }
}

extension InlineArray: @retroactive Hashable where Element: Hashable {
    public func hash(into hasher: inout Hasher) {
        (0 ..< Self.count).forEach {
            hasher.combine(self[$0])
        }
    }
}

extension InlineArray: @retroactive Encodable where Element: Encodable {
    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        let array = (0 ..< Self.count).map { self[$0] }
        try container.encode(array)
    }
}

extension InlineArray: @retroactive Decodable where Element: Decodable {
    enum InlineArrayError: Error { case sizeMismatch(required: Int, provided: Int) }

    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let array = try container.decode([Element].self)
        if array.count != Self.count { throw InlineArrayError.sizeMismatch(required: Self.count, provided: array.count) }
        self = .init { array[$0] }
    }
}

extension InlineArray: @retroactive CustomStringConvertible {
    public var description: String {
        "\((0 ..< Self.count).map { self[$0] })"
    }
}

struct Test: Hashable, Codable {
    let x: [3 of Int]
}

func main() {
    let test = Test(x: [1, 2, 3])
    let data = try! JSONEncoder().encode(test)
    let s = String(data: data, encoding: .utf8)!
    print(s)              // {"x":[1,2,3]}
    let test2 = try! JSONDecoder().decode(Test.self, from: data)
    print(test == test2)  // true
    print(test)           // Test(x: [1, 2, 3])
    print(test.hashValue) // -754052155688762463
    let s2 = #"{"x":[1,2,3, 4]}"#
    let data2 = s2.data(using: .utf8)!
    do {
        let test3 = try JSONDecoder().decode(Test.self, from: data2)
        print(test3)
    } catch {
        print(error) // sizeMismatch(required: 3, provided: 4)
    }

}
main()
2 Likes