diff --git a/Sources/MessagePack/Box.swift b/Sources/MessagePack/Box.swift index fb222ab..afbb4ce 100644 --- a/Sources/MessagePack/Box.swift +++ b/Sources/MessagePack/Box.swift @@ -42,3 +42,15 @@ extension Box where Value == Date { try container.encode(self.value) } } + +extension Box where Value == URL { + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + self.init(try container.decode(Value.self)) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(self.value) + } +} diff --git a/Sources/MessagePack/Decoder/MessagePackDecoder.swift b/Sources/MessagePack/Decoder/MessagePackDecoder.swift index 46e4b05..fabd259 100644 --- a/Sources/MessagePack/Decoder/MessagePackDecoder.swift +++ b/Sources/MessagePack/Decoder/MessagePackDecoder.swift @@ -35,6 +35,9 @@ final public class MessagePackDecoder { case is Date.Type: let box = try Box(from: decoder) return box.value as! T + case is URL.Type: + let box = try Box(from: decoder) + return box.value as! T default: return try T(from: decoder) } diff --git a/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift b/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift index 833c339..6347204 100644 --- a/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift +++ b/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift @@ -203,13 +203,23 @@ extension _MessagePackDecoder.SingleValueContainer: SingleValueDecodingContainer return self.data.subdata(in: self.index.. URL { + let urlStr = try decode(String.self) + guard let url = URL(string: urlStr) else { + throw DecodingError.dataCorruptedError(in: self, debugDescription: "Invalid URL: \(urlStr)") + } + return url + } + func decode(_ type: T.Type) throws -> T where T : Decodable { switch type { case is Data.Type: return try decode(Data.self) as! T case is Date.Type: return try decode(Date.self) as! T + case is URL.Type: + return try decode(URL.self) as! T default: let decoder = _MessagePackDecoder(data: self.data) let value = try T(from: decoder) diff --git a/Sources/MessagePack/Encoder/MessagePackEncoder.swift b/Sources/MessagePack/Encoder/MessagePackEncoder.swift index d2b6a08..0ffeed4 100644 --- a/Sources/MessagePack/Encoder/MessagePackEncoder.swift +++ b/Sources/MessagePack/Encoder/MessagePackEncoder.swift @@ -29,6 +29,8 @@ final public class MessagePackEncoder { try Box(data).encode(to: encoder) case let date as Date: try Box(date).encode(to: encoder) + case let url as URL: + try Box(url).encode(to: encoder) default: try value.encode(to: encoder) } diff --git a/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift b/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift index 9006b3e..989e64e 100644 --- a/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift +++ b/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift @@ -239,7 +239,11 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer throw EncodingError.invalidValue(value, context) } } - + + func encode(_ value: URL) throws { + try encode(value.absoluteString) + } + func encode(_ value: T) throws where T : Encodable { try checkCanEncode(value: value) defer { self.canEncodeNewValue = false } @@ -249,6 +253,8 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer try self.encode(data) case let date as Date: try self.encode(date) + case let url as URL: + try self.encode(url) default: let encoder = _MessagePackEncoder() try value.encode(to: encoder) diff --git a/Tests/MessagePackTests/Airport.swift b/Tests/MessagePackTests/Airport.swift index b39bf95..8b81832 100644 --- a/Tests/MessagePackTests/Airport.swift +++ b/Tests/MessagePackTests/Airport.swift @@ -1,8 +1,11 @@ +import Foundation + struct Airport: Codable, Equatable { let name: String let iata: String let icao: String let coordinates: [Double] + let website: URL struct Runway: Codable, Equatable { enum Surface: String, Codable, Equatable { @@ -25,6 +28,7 @@ struct Airport: Codable, Equatable { icao: "KPDX", coordinates: [-122.5975, 45.5886111111111], + website: URL(string: "https://www.flypdx.com")!, runways: [ Airport.Runway( direction: "3/21", diff --git a/Tests/MessagePackTests/MessagePackRoundTripTests.swift b/Tests/MessagePackTests/MessagePackRoundTripTests.swift index a0304c7..a80c4ae 100644 --- a/Tests/MessagePackTests/MessagePackRoundTripTests.swift +++ b/Tests/MessagePackTests/MessagePackRoundTripTests.swift @@ -20,6 +20,7 @@ class MessagePackRoundTripTests: XCTestCase { XCTAssertEqual(value.icao, decoded.icao) XCTAssertEqual(value.coordinates[0], decoded.coordinates[0], accuracy: 0.01) XCTAssertEqual(value.coordinates[1], decoded.coordinates[1], accuracy: 0.01) + XCTAssertEqual(value.website, decoded.website) XCTAssertEqual(value.runways[0].direction, decoded.runways[0].direction) XCTAssertEqual(value.runways[0].distance, decoded.runways[0].distance) XCTAssertEqual(value.runways[0].surface, decoded.runways[0].surface)