Skip to content

Commit 0edf619

Browse files
authored
Added error logic to the cast as String conversion.
Added more detailed error handling in the casting of string values to type of T. If decoding fails, instead of providing a generic message. Provides the user with clearer type error messages. More explicit failure state for casting from string to bool. If the user does not provide exactly values which are valid. Alert them to this issue.
1 parent 70e1871 commit 0edf619

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

Sources/SQLClientSwift/SQLRowDecoder.swift

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,13 @@ private struct SQLRowKeyedContainer<Key: CodingKey>: KeyedDecodingContainerProto
149149
}
150150

151151
private func cast<T>(_ key: Key) throws -> T {
152+
// Validate key is in columns
152153
let value = try requireValue(for: key)
154+
155+
// Direct cast as type
153156
if let v = value as? T { return v }
157+
158+
// If type is NSNumber supported
154159
if let n = value as? NSNumber {
155160
switch T.self {
156161
case is Bool.Type: return (n.boolValue) as! T
@@ -169,14 +174,40 @@ private struct SQLRowKeyedContainer<Key: CodingKey>: KeyedDecodingContainerProto
169174
default: break
170175
}
171176
}
177+
// String → primitive conversions.
172178
if let s = value as? String {
173179
switch T.self {
174-
case is Int.Type: if let i = Int(s) { return i as! T }
175-
case is Double.Type: if let d = Double(s) { return d as! T }
176-
case is Bool.Type: return (["true","1","yes"].contains(s.lowercased())) as! T
180+
case is Int.Type:
181+
guard let i = Int(s) else {
182+
throw DecodingError.typeMismatch(T.self, .init(
183+
codingPath: codingPath + [key],
184+
debugDescription: "Cannot convert '\(s)' to Int for column '\(key.stringValue)'."))
185+
}
186+
return i as! T
187+
188+
case is Double.Type:
189+
guard let d = Double(s) else {
190+
throw DecodingError.typeMismatch(T.self, .init(
191+
codingPath: codingPath + [key],
192+
debugDescription: "Cannot convert '\(s)' to Double for column '\(key.stringValue)'."))
193+
}
194+
return d as! T
195+
196+
case is Bool.Type:
197+
switch s.lowercased() {
198+
case "true", "1", "yes": return true as! T
199+
case "false", "0", "no": return false as! T
200+
default:
201+
throw DecodingError.typeMismatch(T.self, .init(
202+
codingPath: codingPath + [key],
203+
debugDescription: "Cannot convert '\(s)' to Bool for column '\(key.stringValue)'. "
204+
+ "Expected one of: true, false, 1, 0, yes, no."))
205+
}
206+
177207
default: break
178208
}
179209
}
210+
// No Conversion path succeeded
180211
throw DecodingError.typeMismatch(T.self, .init(
181212
codingPath: codingPath + [key],
182213
debugDescription: "Expected \(T.self), got \(type(of: value)) for column '\(key.stringValue)'"))

0 commit comments

Comments
 (0)