Skip to content

Commit b8e5602

Browse files
authored
SWIFT-1004 Support parsing $uuid as extended JSON representation for subtype 4 binary (#50)
1 parent 06f76a9 commit b8e5602

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

Sources/SwiftBSON/BSONBinary.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,32 @@ extension BSONBinary: BSONValue {
158158
* - `DecodingError` if `json` is a partial match or is malformed.
159159
*/
160160
internal init?(fromExtJSON json: JSON, keyPath: [String]) throws {
161+
if let uuidJSON = try json.unwrapObject(withKey: "$uuid", keyPath: keyPath) {
162+
guard let uuidString = uuidJSON.stringValue else {
163+
throw DecodingError._extendedJSONError(
164+
keyPath: keyPath,
165+
debugDescription: "Expected value for key $uuid \"\(uuidJSON)\" to be a string"
166+
+ " but got some other value"
167+
)
168+
}
169+
guard let uuid = UUID(uuidString: uuidString) else {
170+
throw DecodingError._extendedJSONError(
171+
keyPath: keyPath,
172+
debugDescription: "Invalid UUID string: \(uuidString)"
173+
)
174+
}
175+
176+
do {
177+
self = try BSONBinary(from: uuid)
178+
return
179+
} catch {
180+
throw DecodingError._extendedJSONError(
181+
keyPath: keyPath,
182+
debugDescription: error.localizedDescription
183+
)
184+
}
185+
}
186+
161187
// canonical and relaxed extended JSON
162188
guard let binary = try json.unwrapObject(withKey: "$binary", keyPath: keyPath) else {
163189
return nil

Tests/Specs/bson-corpus/binary.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
"canonical_bson": "1D000000057800100000000473FFD26444B34C6990E8E7D1DFC035D400",
4040
"canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"04\"}}}"
4141
},
42+
{
43+
"description": "subtype 0x04 UUID",
44+
"canonical_bson": "1D000000057800100000000473FFD26444B34C6990E8E7D1DFC035D400",
45+
"canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"04\"}}}",
46+
"degenerate_extjson": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4\"}}"
47+
},
4248
{
4349
"description": "subtype 0x05",
4450
"canonical_bson": "1D000000057800100000000573FFD26444B34C6990E8E7D1DFC035D400",
@@ -81,5 +87,15 @@
8187
"description": "subtype 0x02 length negative one",
8288
"bson": "130000000578000600000002FFFFFFFFFFFF00"
8389
}
90+
],
91+
"parseErrors": [
92+
{
93+
"description": "$uuid wrong type",
94+
"string": "{\"x\" : { \"$uuid\" : { \"data\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4\"}}}"
95+
},
96+
{
97+
"description": "$uuid invalid value",
98+
"string": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-90e8-e7d1dfc035d4\"}}"
99+
}
84100
]
85101
}

Tests/SwiftBSONTests/BSONCorpusTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ final class BSONCorpusTests: BSONTestCase {
243243
}
244244
let description = "\(testFile.description)-\(test.description)"
245245
switch BSONType(rawValue: UInt8(testFile.bsonType.dropFirst(2), radix: 16)!)! {
246-
case .invalid: // "top level document" uses 0x00 for the bson type
246+
case .binary, .invalid: // "top level document" uses 0x00 for the bson type
247247
guard let testData = test.string.data(using: .utf8) else {
248248
XCTFail("Unable to interpret canonical_bson as Data")
249249
return

0 commit comments

Comments
 (0)