@@ -145,10 +145,7 @@ public struct BSONNull: BSONValue, Codable, Equatable {
145145 public init ( ) { }
146146
147147 public init ( from decoder: Decoder ) throws {
148- if decoder is _BSONDecoder {
149- throw bsonDecodingDirectlyError ( type: BSONNull . self, at: decoder. codingPath)
150- }
151- throw bsonDecodingUnsupportedError ( type: BSONNull . self, at: decoder. codingPath)
148+ throw getDecodingError ( type: BSONNull . self, decoder: decoder)
152149 }
153150
154151 public func encode( to: Encoder ) throws {
@@ -250,10 +247,7 @@ public struct Binary: BSONValue, Equatable, Codable {
250247 }
251248
252249 public init ( from decoder: Decoder ) throws {
253- if decoder is _BSONDecoder {
254- throw bsonDecodingDirectlyError ( type: Binary . self, at: decoder. codingPath)
255- }
256- throw bsonDecodingUnsupportedError ( type: Binary . self, at: decoder. codingPath)
250+ throw getDecodingError ( type: Binary . self, decoder: decoder)
257251 }
258252
259253 public func encode( to: Encoder ) throws {
@@ -361,10 +355,7 @@ public struct DBPointer: BSONValue, Codable, Equatable {
361355 }
362356
363357 public init ( from decoder: Decoder ) throws {
364- if decoder is _BSONDecoder {
365- throw bsonDecodingDirectlyError ( type: DBPointer . self, at: decoder. codingPath)
366- }
367- throw bsonDecodingUnsupportedError ( type: DBPointer . self, at: decoder. codingPath)
358+ throw getDecodingError ( type: DBPointer . self, decoder: decoder)
368359 }
369360
370361 public func encode( to: Encoder ) throws {
@@ -439,10 +430,7 @@ public struct Decimal128: BSONValue, Equatable, Codable, CustomStringConvertible
439430 }
440431
441432 public init ( from decoder: Decoder ) throws {
442- if decoder is _BSONDecoder {
443- throw bsonDecodingDirectlyError ( type: Decimal128 . self, at: decoder. codingPath)
444- }
445- throw bsonDecodingUnsupportedError ( type: Decimal128 . self, at: decoder. codingPath)
433+ throw getDecodingError ( type: Decimal128 . self, decoder: decoder)
446434 }
447435
448436 public func encode( to: Encoder ) throws {
@@ -586,10 +574,7 @@ public struct CodeWithScope: BSONValue, Equatable, Codable {
586574 }
587575
588576 public init ( from decoder: Decoder ) throws {
589- if decoder is _BSONDecoder {
590- throw bsonDecodingDirectlyError ( type: CodeWithScope . self, at: decoder. codingPath)
591- }
592- throw bsonDecodingUnsupportedError ( type: CodeWithScope . self, at: decoder. codingPath)
577+ throw getDecodingError ( type: CodeWithScope . self, decoder: decoder)
593578 }
594579
595580 public func encode( to: Encoder ) throws {
@@ -657,10 +642,7 @@ public struct MaxKey: BSONValue, Equatable, Codable {
657642 public init ( ) { }
658643
659644 public init ( from decoder: Decoder ) throws {
660- if decoder is _BSONDecoder {
661- throw bsonDecodingDirectlyError ( type: MaxKey . self, at: decoder. codingPath)
662- }
663- throw bsonDecodingUnsupportedError ( type: MaxKey . self, at: decoder. codingPath)
645+ throw getDecodingError ( type: MaxKey . self, decoder: decoder)
664646 }
665647
666648 public func encode( to: Encoder ) throws {
@@ -693,10 +675,7 @@ public struct MinKey: BSONValue, Equatable, Codable {
693675 public init ( ) { }
694676
695677 public init ( from decoder: Decoder ) throws {
696- if decoder is _BSONDecoder {
697- throw bsonDecodingDirectlyError ( type: MinKey . self, at: decoder. codingPath)
698- }
699- throw bsonDecodingUnsupportedError ( type: MinKey . self, at: decoder. codingPath)
678+ throw getDecodingError ( type: MinKey . self, decoder: decoder)
700679 }
701680
702681 public func encode( to: Encoder ) throws {
@@ -751,10 +730,7 @@ public struct ObjectId: BSONValue, Equatable, CustomStringConvertible, Codable {
751730 }
752731
753732 public init ( from decoder: Decoder ) throws {
754- if decoder is _BSONDecoder {
755- throw bsonDecodingDirectlyError ( type: ObjectId . self, at: decoder. codingPath)
756- }
757- throw bsonDecodingUnsupportedError ( type: ObjectId . self, at: decoder. codingPath)
733+ throw getDecodingError ( type: ObjectId . self, decoder: decoder)
758734 }
759735
760736 public func encode( to: Encoder ) throws {
@@ -896,10 +872,7 @@ public struct RegularExpression: BSONValue, Equatable, Codable {
896872 }
897873
898874 public init ( from decoder: Decoder ) throws {
899- if decoder is _BSONDecoder {
900- throw bsonDecodingDirectlyError ( type: RegularExpression . self, at: decoder. codingPath)
901- }
902- throw bsonDecodingUnsupportedError ( type: RegularExpression . self, at: decoder. codingPath)
875+ throw getDecodingError ( type: RegularExpression . self, decoder: decoder)
903876 }
904877
905878 public func encode( to: Encoder ) throws {
@@ -984,10 +957,7 @@ public struct Symbol: BSONValue, CustomStringConvertible, Codable, Equatable {
984957 public let stringValue : String
985958
986959 public init ( from decoder: Decoder ) throws {
987- if decoder is _BSONDecoder {
988- throw bsonDecodingDirectlyError ( type: Symbol . self, at: decoder. codingPath)
989- }
990- throw bsonDecodingUnsupportedError ( type: Symbol . self, at: decoder. codingPath)
960+ throw getDecodingError ( type: Symbol . self, decoder: decoder)
991961 }
992962
993963 internal init ( _ stringValue: String ) {
@@ -1050,10 +1020,7 @@ public struct Timestamp: BSONValue, Equatable, Codable {
10501020 }
10511021
10521022 public init ( from decoder: Decoder ) throws {
1053- if decoder is _BSONDecoder {
1054- throw bsonDecodingDirectlyError ( type: Timestamp . self, at: decoder. codingPath)
1055- }
1056- throw bsonDecodingUnsupportedError ( type: Timestamp . self, at: decoder. codingPath)
1023+ throw getDecodingError ( type: Timestamp . self, decoder: decoder)
10571024 }
10581025
10591026 public func encode( to: Encoder ) throws {
@@ -1091,10 +1058,7 @@ public struct BSONUndefined: BSONValue, Equatable, Codable {
10911058 internal init ( ) { }
10921059
10931060 public init ( from decoder: Decoder ) throws {
1094- if decoder is _BSONDecoder {
1095- throw bsonDecodingDirectlyError ( type: BSONUndefined . self, at: decoder. codingPath)
1096- }
1097- throw bsonDecodingUnsupportedError ( type: BSONUndefined . self, at: decoder. codingPath)
1061+ throw getDecodingError ( type: BSONUndefined . self, decoder: decoder)
10981062 }
10991063
11001064 public func encode( to: Encoder ) throws {
@@ -1205,21 +1169,45 @@ private func bsonDecodingUnsupportedError<T: BSONValue>(type: T.Type, at codingP
12051169}
12061170
12071171/**
1208- * Error thrown when a `BSONValue` type introduced by the driver (e.g. ObjectId) is decoded via the decoder
1209- * initializer when using `BSONDecoder`. These introduced types are BSON primitives that do not exist in Swift.
1210- * Since they're BSON primitives, they should be read straight from the document via the underlying `bson_t`,
1211- * and `BSONDecoder` should never be calling into init(from:Decoder) to initialize them.
1212- *
1213- * Example error causes:
1214- * - Decoding directly from Document: decoder.decode(ObjectId.self, from: doc)
1215- * - Attempting to decode by field names: decoder.decode(CodeWithScope.self, from: "{\"code": \"code\"}")
1172+ * Error thrown when a `BSONValue` type introduced by the driver (e.g. ObjectId) is decoded directly via the top-level
1173+ * `BSONDecoder`.
12161174 */
12171175private func bsonDecodingDirectlyError< T: BSONValue > ( type: T . Type , at codingPath: [ CodingKey ] ) -> DecodingError {
1218- let description = " Cannot initialize a BSONValue type \( T . self) directly from BSONDecoder. It must be a member of " +
1219- " a struct or a class. "
1176+ let description = " Cannot initialize BSONValue type \( T . self) directly from BSONDecoder. It must be decoded as " +
1177+ " a member of a struct or a class."
12201178
12211179 return DecodingError . typeMismatch (
12221180 T . self,
12231181 DecodingError . Context ( codingPath: codingPath, debugDescription: description)
12241182 )
12251183}
1184+
1185+ /**
1186+ * This function determines which error to throw when a driver-introduced BSON type is decoded via its init(decoder).
1187+ * The types that use this function are all BSON primitives, so they should be decoded directly in `_BSONDecoder`. If
1188+ * execution reaches their decoding initializer, it means something went wrong. This function determines an appropriate
1189+ * error to throw for each possible case.
1190+ *
1191+ * Some example cases:
1192+ * - Decoding directly from the BSONDecoder top-level (e.g. BSONDecoder().decode(ObjectId.self, from: ...))
1193+ * - Encountering the wrong type of BSONValue (e.g. expected "_id" to be an `ObjectId`, got a `Document` instead)
1194+ * - Attempting to decode a driver-introduced BSONValue with a non-BSONDecoder
1195+ */
1196+ internal func getDecodingError< T: BSONValue > ( type: T . Type , decoder: Decoder ) -> DecodingError {
1197+ if let bsonDecoder = decoder as? _BSONDecoder {
1198+ // Cannot decode driver-introduced BSONValues directly
1199+ if decoder. codingPath. isEmpty {
1200+ return bsonDecodingDirectlyError ( type: T . self, at: decoder. codingPath)
1201+ }
1202+
1203+ // Got the wrong BSONValue type
1204+ return DecodingError . _typeMismatch (
1205+ at: decoder. codingPath,
1206+ expectation: T . self,
1207+ reality: bsonDecoder. storage. topContainer
1208+ )
1209+ }
1210+
1211+ // Non-BSONDecoders are currently unsupported
1212+ return bsonDecodingUnsupportedError ( type: T . self, at: decoder. codingPath)
1213+ }
0 commit comments