Нет необходимости создавать свой собственный IPv4AddressDecodingError. Вы можете бросить DecodingError
, используя dataCorruptedError
метод. Кстати, нет необходимости создавать перечисление CodingKeys
для одного значения:
Вы также можете создать протокол, который соответствует RawRepresentable & Codable
и ограничивает RawValue
до Codable
. Таким образом, вы можете создавать обобщенные c методы кодировщика и декодера для обоих IP-адресов:
import Network
public protocol RawRepresentableCodableProtocol: RawRepresentable & Codable
where Self.RawValue: Codable { }
public extension RawRepresentableCodableProtocol {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(RawValue.self)
guard let object = Self(rawValue: rawValue) else {
throw DecodingError
.dataCorruptedError(in: container, debugDescription: "Invalid rawValue data: \(rawValue)")
}
self = object
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValue)
}
}
Теперь мы можем расширить RawRepresentableCodableProtocol
, ограничив Self
до IPAddress
протокол и обеспечение ошибочного инициализатора данных rawValue:
public extension RawRepresentableCodableProtocol where Self: IPAddress {
init?(rawValue: Data) {
guard let object = Self(rawValue, nil) else { return nil }
self = object
}
}
extension IPv4Address: RawRepresentableCodableProtocol { }
extension IPv6Address: RawRepresentableCodableProtocol { }
Тестирование игровой площадки:
let ipv4 = IPv4Address("1.2.33.44")! // 1.2.33.44
let dataIPv4 = try JSONEncoder().encode(ipv4) // 10 bytes
let loadedIPv4 = try JSONDecoder().decode(IPv4Address.self, from: dataIPv4) // 1.2.33.44
let ipv6 = IPv6Address("2001:db8::35:44")! // 2001:db8::35:44
let dataIPv6 = try JSONEncoder().encode(ipv6) // 26 bytes
let loadedIPv6 = try JSONDecoder().decode(IPv6Address.self, from: dataIPv6) // 2001:db8::35:44