Skip to content

Commit 4d83a2c

Browse files
authored
Split error message from code (#24)
Motivation: Users can't check the code of an `AsyncDNSResolver.Error` because it's backed by an internal enum carrying a message as its associated data. Modifications: - Rework `AsyncDNSResolver.Error` so that the code is separate from the message. Result: Users can programattically take action based on the code of an error
1 parent 96a18c6 commit 4d83a2c

File tree

5 files changed

+173
-219
lines changed

5 files changed

+173
-219
lines changed

Sources/AsyncDNSResolver/Errors.swift

Lines changed: 118 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -15,198 +15,155 @@
1515
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
1616
extension AsyncDNSResolver {
1717
/// Possible ``AsyncDNSResolver/AsyncDNSResolver`` errors.
18-
public struct Error: Swift.Error, CustomStringConvertible {
19-
enum Code: Equatable, CustomStringConvertible {
20-
case noData(String?)
21-
case invalidQuery(String?)
22-
case serverFailure(String?)
23-
case notFound(String?)
24-
case notImplemented(String?)
25-
case serverRefused(String?)
26-
case badQuery(String?)
27-
case badName(String?)
28-
case badFamily(String?)
29-
case badResponse(String?)
30-
case connectionRefused(String?)
31-
case timeout(String?)
32-
case eof(String?)
33-
case fileIO(String?)
34-
case noMemory(String?)
35-
case destruction(String?)
36-
case badString(String?)
37-
case badFlags(String?)
38-
case noName(String?)
39-
case badHints(String?)
40-
case notInitialized(String?)
41-
case initError(String?)
42-
case cancelled(String?)
43-
case service(String?)
44-
case other(code: Int, String?)
45-
46-
var description: String {
47-
switch self {
48-
case .noData(let description):
49-
return "no data: \(description ?? "")"
50-
case .invalidQuery(let description):
51-
return "invalid query: \(description ?? "")"
52-
case .serverFailure(let description):
53-
return "server failure: \(description ?? "")"
54-
case .notFound(let description):
55-
return "not found: \(description ?? "")"
56-
case .notImplemented(let description):
57-
return "not implemented: \(description ?? "")"
58-
case .serverRefused(let description):
59-
return "server refused: \(description ?? "")"
60-
case .badQuery(let description):
61-
return "bad query: \(description ?? "")"
62-
case .badName(let description):
63-
return "bad name: \(description ?? "")"
64-
case .badFamily(let description):
65-
return "bad family: \(description ?? "")"
66-
case .badResponse(let description):
67-
return "bad response: \(description ?? "")"
68-
case .connectionRefused(let description):
69-
return "connection refused: \(description ?? "")"
70-
case .timeout(let description):
71-
return "timeout: \(description ?? "")"
72-
case .eof(let description):
73-
return "EOF: \(description ?? "")"
74-
case .fileIO(let description):
75-
return "file IO: \(description ?? "")"
76-
case .noMemory(let description):
77-
return "no memory: \(description ?? "")"
78-
case .destruction(let description):
79-
return "destruction: \(description ?? "")"
80-
case .badString(let description):
81-
return "bad string: \(description ?? "")"
82-
case .badFlags(let description):
83-
return "bad flags: \(description ?? "")"
84-
case .noName(let description):
85-
return "no name: \(description ?? "")"
86-
case .badHints(let description):
87-
return "bad hints: \(description ?? "")"
88-
case .notInitialized(let description):
89-
return "not initialized: \(description ?? "")"
90-
case .initError(let description):
91-
return "initialization error: \(description ?? "")"
92-
case .cancelled(let description):
93-
return "cancelled: \(description ?? "")"
94-
case .service(let description):
95-
return "service: \(description ?? "")"
96-
case .other(let code, let description):
97-
return "other [\(code)]: \(description ?? "")"
98-
}
18+
public struct Error: Swift.Error, Hashable, CustomStringConvertible {
19+
public struct Code: Hashable, Sendable {
20+
fileprivate enum Value: Hashable, Sendable {
21+
case noData
22+
case invalidQuery
23+
case serverFailure
24+
case notFound
25+
case notImplemented
26+
case serverRefused
27+
case badQuery
28+
case badName
29+
case badFamily
30+
case badResponse
31+
case connectionRefused
32+
case timeout
33+
case eof
34+
case fileIO
35+
case noMemory
36+
case destruction
37+
case badString
38+
case badFlags
39+
case noName
40+
case badHints
41+
case notInitialized
42+
case initError
43+
case cancelled
44+
case service
45+
case other(Int)
9946
}
100-
}
10147

102-
let code: Code
48+
fileprivate var value: Value
49+
private init(_ value: Value) {
50+
self.value = value
51+
}
10352

104-
private init(code: Code) {
105-
self.code = code
106-
}
53+
public static var noData: Self { Self(.noData) }
10754

108-
public var description: String {
109-
"\(self.code)"
110-
}
55+
public static var invalidQuery: Self { Self(.invalidQuery) }
11156

112-
public static func noData(_ description: String? = nil) -> Error {
113-
.init(code: .noData(description))
114-
}
57+
public static var serverFailure: Self { Self(.serverFailure) }
11558

116-
public static func invalidQuery(_ description: String? = nil) -> Error {
117-
.init(code: .invalidQuery(description))
118-
}
59+
public static var notFound: Self { Self(.notFound) }
11960

120-
public static func serverFailure(_ description: String? = nil) -> Error {
121-
.init(code: .serverFailure(description))
122-
}
61+
public static var notImplemented: Self { Self(.notImplemented) }
12362

124-
public static func notFound(_ description: String? = nil) -> Error {
125-
.init(code: .notFound(description))
126-
}
63+
public static var serverRefused: Self { Self(.serverRefused) }
12764

128-
public static func notImplemented(_ description: String? = nil) -> Error {
129-
.init(code: .notImplemented(description))
130-
}
65+
public static var badQuery: Self { Self(.badQuery) }
13166

132-
public static func serverRefused(_ description: String? = nil) -> Error {
133-
.init(code: .serverRefused(description))
134-
}
67+
public static var badName: Self { Self(.badName) }
13568

136-
public static func badQuery(_ description: String? = nil) -> Error {
137-
.init(code: .badQuery(description))
138-
}
69+
public static var badFamily: Self { Self(.badFamily) }
13970

140-
public static func badName(_ description: String? = nil) -> Error {
141-
.init(code: .badName(description))
142-
}
71+
public static var badResponse: Self { Self(.badResponse) }
14372

144-
public static func badFamily(_ description: String? = nil) -> Error {
145-
.init(code: .badFamily(description))
146-
}
73+
public static var connectionRefused: Self { Self(.connectionRefused) }
14774

148-
public static func badResponse(_ description: String? = nil) -> Error {
149-
.init(code: .badResponse(description))
150-
}
75+
public static var timeout: Self { Self(.timeout) }
15176

152-
public static func connectionRefused(_ description: String? = nil) -> Error {
153-
.init(code: .connectionRefused(description))
154-
}
77+
public static var eof: Self { Self(.eof) }
15578

156-
public static func timeout(_ description: String? = nil) -> Error {
157-
.init(code: .timeout(description))
158-
}
79+
public static var fileIO: Self { Self(.fileIO) }
15980

160-
public static func eof(_ description: String? = nil) -> Error {
161-
.init(code: .eof(description))
162-
}
81+
public static var noMemory: Self { Self(.noMemory) }
16382

164-
public static func fileIO(_ description: String? = nil) -> Error {
165-
.init(code: .fileIO(description))
166-
}
83+
public static var destruction: Self { Self(.destruction) }
16784

168-
public static func noMemory(_ description: String? = nil) -> Error {
169-
.init(code: .noMemory(description))
170-
}
85+
public static var badString: Self { Self(.badString) }
17186

172-
public static func destruction(_ description: String? = nil) -> Error {
173-
.init(code: .destruction(description))
174-
}
87+
public static var badFlags: Self { Self(.badFlags) }
17588

176-
public static func badString(_ description: String? = nil) -> Error {
177-
.init(code: .badString(description))
178-
}
89+
public static var noName: Self { Self(.noName) }
17990

180-
public static func badFlags(_ description: String? = nil) -> Error {
181-
.init(code: .badFlags(description))
182-
}
91+
public static var badHints: Self { Self(.badHints) }
18392

184-
public static func noName(_ description: String? = nil) -> Error {
185-
.init(code: .noName(description))
186-
}
93+
public static var notInitialized: Self { Self(.notInitialized) }
18794

188-
public static func badHints(_ description: String? = nil) -> Error {
189-
.init(code: .badHints(description))
190-
}
95+
public static var initError: Self { Self(.initError) }
19196

192-
public static func notInitialized(_ description: String? = nil) -> Error {
193-
.init(code: .notInitialized(description))
194-
}
97+
public static var cancelled: Self { Self(.cancelled) }
19598

196-
public static func initError(_ description: String? = nil) -> Error {
197-
.init(code: .initError(description))
198-
}
99+
public static var service: Self { Self(.service) }
199100

200-
public static func cancelled(_ description: String? = nil) -> Error {
201-
.init(code: .cancelled(description))
101+
public static func other(_ code: Int) -> Self {
102+
Self(.other(code))
103+
}
202104
}
203105

204-
public static func service(_ description: String? = nil) -> Error {
205-
.init(code: .service(description))
106+
public var code: Code
107+
public var message: String
108+
109+
public init(code: Code, message: String = "") {
110+
self.code = code
111+
self.message = message
206112
}
207113

208-
public static func other(code: Int, _ description: String? = nil) -> Error {
209-
.init(code: .other(code: code, description))
114+
public var description: String {
115+
switch self.code.value {
116+
case .noData:
117+
return "no data: \(self.message)"
118+
case .invalidQuery:
119+
return "invalid query: \(self.message)"
120+
case .serverFailure:
121+
return "server failure: \(self.message)"
122+
case .notFound:
123+
return "not found: \(self.message)"
124+
case .notImplemented:
125+
return "not implemented: \(self.message)"
126+
case .serverRefused:
127+
return "server refused: \(self.message)"
128+
case .badQuery:
129+
return "bad query: \(self.message)"
130+
case .badName:
131+
return "bad name: \(self.message)"
132+
case .badFamily:
133+
return "bad family: \(self.message)"
134+
case .badResponse:
135+
return "bad response: \(self.message)"
136+
case .connectionRefused:
137+
return "connection refused: \(self.message)"
138+
case .timeout:
139+
return "timeout: \(self.message)"
140+
case .eof:
141+
return "EOF: \(self.message)"
142+
case .fileIO:
143+
return "file IO: \(self.message)"
144+
case .noMemory:
145+
return "no memory: \(self.message)"
146+
case .destruction:
147+
return "destruction: \(self.message)"
148+
case .badString:
149+
return "bad string: \(self.message)"
150+
case .badFlags:
151+
return "bad flags: \(self.message)"
152+
case .noName:
153+
return "no name: \(self.message)"
154+
case .badHints:
155+
return "bad hints: \(self.message)"
156+
case .notInitialized:
157+
return "not initialized: \(self.message)"
158+
case .initError:
159+
return "initialization error: \(self.message)"
160+
case .cancelled:
161+
return "cancelled: \(self.message)"
162+
case .service:
163+
return "service: \(self.message)"
164+
case .other(let code):
165+
return "other [\(code)]: \(self.message)"
166+
}
210167
}
211168
}
212169
}

Sources/AsyncDNSResolver/c-ares/DNSResolver_c-ares.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ extension Ares {
370370
}
371371

372372
guard let hostent = hostentPtrPtr.pointee?.pointee else {
373-
throw AsyncDNSResolver.Error.noData("no NS records found")
373+
throw AsyncDNSResolver.Error(code: .noData, message: "no NS records found")
374374
}
375375

376376
let nameServers = toStringArray(hostent.h_aliases)
@@ -391,7 +391,7 @@ extension Ares {
391391
}
392392

393393
guard let hostent = hostentPtrPtr.pointee?.pointee else {
394-
throw AsyncDNSResolver.Error.noData("no CNAME record found")
394+
throw AsyncDNSResolver.Error(code: .noData, message: "no CNAME record found")
395395
}
396396

397397
return String(cString: hostent.h_name)
@@ -411,7 +411,7 @@ extension Ares {
411411
}
412412

413413
guard let soaReply = soaReplyPtrPtr.pointee?.pointee else {
414-
throw AsyncDNSResolver.Error.noData("no SOA record found")
414+
throw AsyncDNSResolver.Error(code: .noData, message: "no SOA record found")
415415
}
416416

417417
return SOARecord(
@@ -441,7 +441,7 @@ extension Ares {
441441
}
442442

443443
guard let hostent = hostentPtrPtr.pointee?.pointee else {
444-
throw AsyncDNSResolver.Error.noData("no PTR record found")
444+
throw AsyncDNSResolver.Error(code: .noData, message: "no PTR record found")
445445
}
446446

447447
let hostnames = toStringArray(hostent.h_aliases)

0 commit comments

Comments
 (0)