Skip to content

Commit 1d3b7cb

Browse files
committed
add support for inet
1 parent 92ee156 commit 1d3b7cb

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import NIOCore
2+
3+
extension SocketAddress: PostgresDecodable {
4+
public init<JSONDecoder: PostgresJSONDecoder>(from byteBuffer: inout NIOCore.ByteBuffer, type: PostgresDataType, format: PostgresFormat, context: PostgresDecodingContext<JSONDecoder>) throws {
5+
// IP family
6+
byteBuffer.moveReaderIndex(forwardBy: MemoryLayout<UInt8>.size)
7+
8+
// netmask length in bits
9+
guard let netmaskLength: UInt8 = byteBuffer.readInteger(as: UInt8.self) else {
10+
throw PostgresDecodingError.Code.failure
11+
}
12+
13+
// ensure it is not a CIDR
14+
guard byteBuffer.readInteger(as: UInt8.self) == 0 else {
15+
throw PostgresDecodingError.Code.failure
16+
}
17+
18+
// address length in bytes
19+
guard let addressLength: UInt8 = byteBuffer.readInteger(as: UInt8.self),
20+
addressLength * 8 == netmaskLength,
21+
let packedIPAddress: ByteBuffer = byteBuffer.readSlice(length: Int(addressLength))
22+
else {
23+
throw PostgresDecodingError.Code.failure
24+
}
25+
26+
try self.init(packedIPAddress: packedIPAddress, port: 0)
27+
}
28+
}
29+
30+
extension SocketAddress: PostgresEncodable & PostgresNonThrowingEncodable {
31+
public static var psqlType: PostgresDataType { return .inet }
32+
public static var psqlFormat: PostgresFormat { .binary }
33+
public func encode<JSONEncoder: PostgresJSONEncoder>(into byteBuffer: inout ByteBuffer, context: PostgresEncodingContext<JSONEncoder>) {
34+
switch self {
35+
case .v4(let address):
36+
// IP family
37+
byteBuffer.writeInteger(UInt8(2))
38+
// netmask length in bits
39+
byteBuffer.writeInteger(UInt8(32))
40+
// indicate it is not a CIDR
41+
byteBuffer.writeInteger(UInt8(0))
42+
// address length in bytes
43+
byteBuffer.writeInteger(UInt8(4))
44+
// address values
45+
let addressBytes = withUnsafeBytes(of: address.address.sin_addr.s_addr) { Array($0) }
46+
byteBuffer.writeBytes(addressBytes)
47+
48+
case .v6(let address):
49+
// IP family
50+
byteBuffer.writeInteger(UInt8(3))
51+
// netmask length in bits
52+
byteBuffer.writeInteger(UInt8(128))
53+
// indicate it is not a CIDR
54+
byteBuffer.writeInteger(UInt8(0))
55+
// address length in bytes
56+
byteBuffer.writeInteger(UInt8(16))
57+
// address values
58+
let addressBytes = withUnsafeBytes(of: address.address.sin6_addr) { Array($0) }
59+
byteBuffer.writeBytes(addressBytes)
60+
61+
case .unixDomainSocket:
62+
fatalError("Cannot encode a UNIX socket address using the Postgres inet type")
63+
}
64+
}
65+
}
66+
67+
extension SocketAddress: PostgresArrayDecodable {}
68+
69+
extension SocketAddress: PostgresArrayEncodable {
70+
public static var psqlArrayType: PostgresDataType { return .inetArray }
71+
}
72+
73+
extension SocketAddress: Decodable {
74+
public init(from decoder: Decoder) throws {
75+
let container = try decoder.singleValueContainer()
76+
let ipAddress = try container.decode(String.self)
77+
try self.init(ipAddress: ipAddress, port: 0)
78+
}
79+
}
80+
81+
extension SocketAddress: Encodable {
82+
public func encode(to encoder: Encoder) throws {
83+
var container = encoder.singleValueContainer()
84+
try container.encode(self.description)
85+
}
86+
}

0 commit comments

Comments
 (0)