JetForMe
(Rick M)
1
In my MODBUS library, I have a slew of errors in an enum (MBError).
In a unit test in Xcode, when the test throws an exception, Xcode writes this to the console:
<unknown>:0: error: -[SwiftMODBUSTests.SwiftMODBUSTests testAlicatAsync] : failed: caught error: "The operation couldn’t be completed. (SwiftMODBUS.MBError error 5.)"
If I catch the error and print it, I get the CustomDebugStringConvertible I created for it:
Err: Timeout
I figured the "5" was the fifth case in the enum, but that doesn't match. Here's the enum:
public
enum
MBError : Error
{
case unknown(Int)
case deviceIDNotSet
case unexpectedReturnedRegisterCount(Int)
case timeout
// libmodbus errors
case invalidFunction
case invalidAddress(Int?)
case invalidValue(Int?, String?)
case serverFailure
case ack
case serverBusy
case nack
case memoryParity
case notDefined // ???
case gatewayPathUnavailable
case noResponse
case invalidCRC
case invalidData
case invalidExeceptionCode
case unknownExeceptionCode
case dataOverflow // Too many bytes returned
case badServer // Response not from requested device
…
}
extension
MBError : CustomDebugStringConvertible
{
public
var
debugDescription: String
{
switch self
{
case .unknown(let ec): return "Unknown (\(ec))"
case .deviceIDNotSet: return "Device ID not set"
case .unexpectedReturnedRegisterCount(let c): return "Unexpected returned register count: \(c)"
case .timeout: return "Timeout"
case .invalidFunction: return "Invalid function"
case .invalidAddress(let a): return "Invalid address \(String(describing: a))"
case .invalidValue(let a, let v): return "Invalid value \(String(describing: a)) \(String(describing: v))"
case .serverFailure: return "Server failure"
case .ack: return "Acknowledged"
case .serverBusy: return "Server busy"
case .nack: return "Not acknowledged"
case .memoryParity: return "Memory parity"
case .notDefined: return "Error not defined"
case .gatewayPathUnavailable: return "Gateway path unavailable"
case .noResponse: return "No response"
case .invalidCRC: return "Invalid CRC"
case .invalidData: return "Invalid data"
case .invalidExeceptionCode: return "Invalid exception code"
case .unknownExeceptionCode: return "Unknown exception code"
case .dataOverflow: return "Data overflow"
case .badServer: return "Bad server"
}
}
}
Jon_Shier
(Jon Shier)
2
I believe that's what happens when a Swift Error is printed from Obj-C (which underlies XCTest), as it converts to NSError, which requires a numeric code. I've never found the logic for how the numeric values are generated.
1 Like
Jon_Shier
(Jon Shier)
3
Ah, it's all in swift/ErrorType.swift at 23ba70e7bac709874ae06a4545d287fb27333995 · apple/swift · GitHub
Looks like it's all generated metadata from the runtime. In some brief experiments the _code value generally follow the pattern of cases with associated values first, then cases without associated values.
This:
enum SomeError: Error, CaseIterable {
case one, two, three(String), four, five, six(String), seven
static var allCases: [SomeError] {
[.one, .two, .three("default"), .four, .five, .six("default"), .seven]
}
}
print(SomeError.allCases.map(\._code))
prints [2, 3, 0, 4, 5, 1, 6].
3 Likes
JetForMe
(Rick M)
4
Ah! That explains why the numbering changed when I added those associated values. Nice sleuthing.