I think the following is a viable implementation:
public extension LosslessStringConvertible where Self: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode("\(self)")
}
}
public extension LosslessStringConvertible where Self: Decodable {
init(from decoder: Decoder) throws {
let stringRep = try decoder.singleValueContainer().decode(String.self)
self.init(stringRep)!
}
}
// Opt in.
extension Float80: Codable {}
// Test.
import Foundation
let f80 = Float80(3.142)
let encodedData = try JSONEncoder().encode(f80)
print(String(data: encodedData, encoding: .utf8)!)
let decodedF80 = try JSONDecoder().decode(Float80.self, from: encodedData)
print(decodedF80 == f80)
The difference is that you have to opt in. Therefore concerns about all LosslessStringConvertible
s suddenly becoming Codable
are mitigated and you can still do your own implementation if you wish.
Unfortunately I think there is a Codable
bug, see Problem with Encoder.singleValueContainer, and so the above currently doesn't work :(.