Slide 48
Slide 48 text
@propertyWrapper
public struct LosslessValue: Codable {
private let type: LosslessStringCodable.Type
public var wrappedValue: T
public init(from decoder: Decoder) throws {
do {
self.wrappedValue = try T.init(from: decoder)
self.type = T.self
} catch let error {
func decode(_: T.Type) -> (Decoder) -> LosslessStringCodable? {
return { try? T.init(from: $0) }
}
let types: [(Decoder) -> LosslessStringCodable?] = [
decode(String.self),decode(Bool.self),decode(Int.self),
decode(Int8.self),decode(Int16.self),decode(Int64.self),
decode(UInt.self),decode(UInt8.self),decode(UInt16.self),
decode(UInt64.self),decode(Double.self),decode(Float.self),
]
guard
let rawValue = types.lazy.compactMap({ $0(decoder) }).first,
let value = T.init("\(rawValue)")
else { throw error }
self.wrappedValue = value
self.type = Swift.type(of: rawValue)
}
}
public func encode(to encoder: Encoder) throws {
let string = String(describing: wrappedValue)
guard let original = type.init(string) else {
let description = "Unable to encode '\(wrappedValue)' back to source type '\(type)'"
throw EncodingError.invalidValue(string, .init(codingPath: [], debugDescription: description))
}
try original.encode(to: encoder)
}
}