CIVector Codable

March 4, 2019

For my current side project, I have to export CIFilter parameters to json, and I've been running into issues with various CoreImage types not conforming to Swift's Codable. CIColor is easy enough to encode and decode, but CIVector (which represents an arbitrary length list of CGFloats) is trickier.

Thought I'd share a wrapper type which I use to encode and decode CIVector:

struct CIVectorCodableWrapper {
    let vector: CIVector
}

extension CIVectorCodableWrapper: Codable {
    public init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        var floats: [CGFloat] = []
        while !container.isAtEnd {
            floats.append(try container.decode(CGFloat.self))
        }
        vector = CIVector(floats: floats)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        for i in 0..<vector.count {
            try container.encode(vector.value(at: i))
        }
    }
}

CIVector is semantically an "unkeyed container" type, so the Codable implementation encodes the vector's floats to an unkeyed coding container (with JSONEncoder, for example, this becomes an array).