Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Sources/ContainerizationExtras/CIDRv4.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/// Describes an IPv4 CIDR address block.
@frozen
public struct CIDRv4: CustomStringConvertible, Equatable, Sendable, Hashable, Codable {
public struct CIDRv4: CustomStringConvertible, Equatable, Sendable, Hashable {
/// The IP component of this CIDR address.
public let address: IPv4Address

Expand Down Expand Up @@ -99,3 +99,16 @@ public struct CIDRv4: CustomStringConvertible, Equatable, Sendable, Hashable, Co
"\(address)/\(prefix)"
}
}

extension CIDRv4: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
try self.init(string)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(description)
}
}
15 changes: 14 additions & 1 deletion Sources/ContainerizationExtras/CIDRv6.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/// Describes an IPv4 or IPv6 CIDR address block.
@frozen
public struct CIDRv6: CustomStringConvertible, Equatable, Sendable, Hashable, Codable {
public struct CIDRv6: CustomStringConvertible, Equatable, Sendable, Hashable {

/// The IP component of this CIDR address.
public let address: IPv6Address
Expand Down Expand Up @@ -100,3 +100,16 @@ public struct CIDRv6: CustomStringConvertible, Equatable, Sendable, Hashable, Co
"\(address)/\(prefix)"
}
}

extension CIDRv6: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
try self.init(string)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(description)
}
}
15 changes: 14 additions & 1 deletion Sources/ContainerizationExtras/IPv4Address.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//

@frozen
public struct IPv4Address: Sendable, Hashable, CustomStringConvertible, Equatable, Comparable, Codable {
public struct IPv4Address: Sendable, Hashable, CustomStringConvertible, Equatable, Comparable {
public let value: UInt32

@inlinable
Expand Down Expand Up @@ -215,3 +215,16 @@ public struct IPv4Address: Sendable, Hashable, CustomStringConvertible, Equatabl
lhs.value < rhs.value
}
}

extension IPv4Address: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
try self.init(string)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(description)
}
}
15 changes: 14 additions & 1 deletion Sources/ContainerizationExtras/IPv6Address.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//

/// Represents an IPv6 network address conforming to RFC 5952 and RFC 4291.
public struct IPv6Address: Sendable, Hashable, CustomStringConvertible, Equatable, Comparable, Codable {
public struct IPv6Address: Sendable, Hashable, CustomStringConvertible, Equatable, Comparable {
public let value: UInt128

public let zone: String?
Expand Down Expand Up @@ -252,3 +252,16 @@ public struct IPv6Address: Sendable, Hashable, CustomStringConvertible, Equatabl
return (lhs.zone ?? "") < (rhs.zone ?? "")
}
}

extension IPv6Address: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
try self.init(string)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(description)
}
}
63 changes: 63 additions & 0 deletions Tests/ContainerizationExtrasTests/TestCIDR.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//

import Foundation
import Testing

@testable import ContainerizationExtras
Expand Down Expand Up @@ -308,4 +309,66 @@ struct TestCIDR {
let cidr = try CIDR("192.168.1.100/24")
#expect(cidr.description == "192.168.1.100/24")
}

@Test(
"CIDRv4 Codable encodes to string representation",
arguments: [
"192.168.1.0/24",
"10.0.0.0/8",
"172.16.0.0/12",
]
)
func testCIDRv4CodableEncode(cidr: String) throws {
let original = try CIDRv4(cidr)
let encoded = try JSONEncoder().encode(original)
let jsonString = String(data: encoded, encoding: .utf8)!
#expect(jsonString.contains(original.address.description))
#expect(jsonString.contains("\(original.prefix.length)"))
}

@Test(
"CIDRv4 Codable decodes from string representation",
arguments: [
"192.168.1.0/24",
"10.0.0.0/8",
"172.16.0.0/12",
]
)
func testCIDRv4CodableDecode(cidr: String) throws {
let json = Data("\"\(cidr)\"".utf8)
let decoded = try JSONDecoder().decode(CIDRv4.self, from: json)
let expected = try CIDRv4(cidr)
#expect(decoded == expected)
}

@Test(
"CIDRv6 Codable encodes to string representation",
arguments: [
("2001:db8::/32", "2001:db8::", 32),
("fe80::/10", "fe80::", 10),
("::1/128", "::1", 128),
]
)
func testCIDRv6CodableEncode(cidr: String, expectedAddr: String, expectedPrefix: UInt8) throws {
let original = try CIDRv6(cidr)
let encoded = try JSONEncoder().encode(original)
let jsonString = String(data: encoded, encoding: .utf8)!
#expect(jsonString.contains(expectedAddr))
#expect(jsonString.contains("\(expectedPrefix)"))
}

@Test(
"CIDRv6 Codable decodes from string representation",
arguments: [
"2001:db8::/32",
"fe80::/10",
"::1/128",
]
)
func testCIDRv6CodableDecode(cidr: String) throws {
let json = Data("\"\(cidr)\"".utf8)
let decoded = try JSONDecoder().decode(CIDRv6.self, from: json)
let expected = try CIDRv6(cidr)
#expect(decoded == expected)
}
}
31 changes: 31 additions & 0 deletions Tests/ContainerizationExtrasTests/TestIPv4Address.swift
Original file line number Diff line number Diff line change
Expand Up @@ -427,5 +427,36 @@ struct IPv4AddressTests {
#expect(Bool(false), "Should have thrown IPAddressError, got: \(error)")
}
}

@Test(
"Codable encodes to string representation",
arguments: [
"127.0.0.1",
"192.168.1.1",
"0.0.0.0",
"255.255.255.255",
]
)
func testCodableEncode(address: String) throws {
let original = try IPv4Address(address)
let encoded = try JSONEncoder().encode(original)
#expect(String(data: encoded, encoding: .utf8) == "\"\(address)\"")
}

@Test(
"Codable decodes from string representation",
arguments: [
"127.0.0.1",
"192.168.1.1",
"0.0.0.0",
"255.255.255.255",
]
)
func testCodableDecode(address: String) throws {
let json = Data("\"\(address)\"".utf8)
let decoded = try JSONDecoder().decode(IPv4Address.self, from: json)
let expected = try IPv4Address(address)
#expect(decoded == expected)
}
}
}
31 changes: 31 additions & 0 deletions Tests/ContainerizationExtrasTests/TestIPv6Address.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,35 @@ struct IPv6AddressTests {
"Address \(addressString) (\(description)) should\(expected ? "" : " not") be documentation"
)
}

@Test(
"Codable encodes to string representation",
arguments: [
("::1", "::1"),
("2001:db8::1", "2001:db8::1"),
("::", "::"),
("fe80::1", "fe80::1"),
]
)
func testCodableEncode(input: String, expected: String) throws {
let original = try IPv6Address(input)
let encoded = try JSONEncoder().encode(original)
#expect(String(data: encoded, encoding: .utf8) == "\"\(expected)\"")
}

@Test(
"Codable decodes from string representation",
arguments: [
"::1",
"2001:db8::1",
"::",
"fe80::1",
]
)
func testCodableDecode(address: String) throws {
let json = Data("\"\(address)\"".utf8)
let decoded = try JSONDecoder().decode(IPv6Address.self, from: json)
let expected = try IPv6Address(address)
#expect(decoded == expected)
}
}