In trying to serialize an array of float3 objects with the basic JSONEncoder, it\'s revealed that float3 does not conform to the Codable protocol, so this cannot be done.
Dávid is correct on how to fix the problem, but it's worth understanding why it's a problem (it's not actually designated vs convenience initializers; that only applies to classes).
If we created our own version of float3
, your code would work fine with an extension:
struct float3 {
var x: Float
var y: Float
var z: Float
}
extension float3: Codable {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
x = try values.decode(Float.self, forKey: .x)
y = try values.decode(Float.self, forKey: .y)
z = try values.decode(Float.self, forKey: .z)
}
// ...
}
So that seems strange. Why doesn't our implementation of the simd
type work the same as the simd
type? Because simd
doesn't have an x
stored property (or y
or z
). Those are all computed properties.
The real interface is defined in simd.swift.gyb. If you study that code, you'll see all the SIMD vector types use a generic _vector
storage:
public var _vector: Builtin.${llvm_vectype}
And then there are computed properties defined for each letter (component
is ['x','y','z','w']
):
% for i in xrange(count):
public var ${component[i]} : ${scalar} {
@_transparent
get {
let elt = Builtin.${extractelement}(_vector,
(${i} as Int32)._value)
return ${scalar}(_bits: elt)
}
@_transparent
set {
_vector = Builtin.${insertelement}(_vector,
newValue._value,
(${i} as Int32)._value)
}
}
% end
So if we were building our own float3
(without fancy builtins), it'd be something like this:
struct float3 {
private var vector: [Float]
var x: Float { get { return vector[0] } set { vector[0] = newValue } }
var y: Float { get { return vector[1] } set { vector[1] = newValue } }
var z: Float { get { return vector[2] } set { vector[2] = newValue } }
init(x: Float, y: Float, z: Float) {
vector = [x, y, z]
}
}
And if you write your extension against that, you'll get the same error.