@@ -16,21 +16,6 @@ public struct BSONDocument {
16
16
17
17
private var storage : BSONDocumentStorage
18
18
19
- internal var byteLength : Int {
20
- get {
21
- guard let byteLength = self . storage. buffer. getInteger ( at: 0 , endianness: . little, as: Int32 . self) else {
22
- fatalError ( " Cannot read byteLength of BSON from buffer " )
23
- }
24
- return Int ( byteLength)
25
- }
26
- set {
27
- guard newValue <= Int32 . max else {
28
- fatalError ( " Cannot cast \( newValue) down to Int32 " )
29
- }
30
- self . storage. buffer. setInteger ( Int32 ( newValue) , at: 0 , endianness: . little, as: Int32 . self)
31
- }
32
- }
33
-
34
19
/// An unordered set containing the keys in this document.
35
20
internal private( set) var keySet : Set < String >
36
21
@@ -66,8 +51,8 @@ public struct BSONDocument {
66
51
fatalError ( " Data is \( self . storage. buffer. writerIndex - start) bytes, "
67
52
+ " but maximum allowed BSON document size is \( Int32 . max) bytes " )
68
53
}
69
- // Set byteLength in reserved space
70
- self . storage. buffer . setInteger ( byteLength , at : 0 , endianness : . little , as : Int32 . self )
54
+ // Set encodedLength in reserved space
55
+ self . storage. encodedLength = Int ( byteLength )
71
56
}
72
57
73
58
/// Initializes a new, empty `BSONDocument`.
@@ -103,16 +88,13 @@ public struct BSONDocument {
103
88
*/
104
89
public init ( fromBSON bson: ByteBuffer ) throws {
105
90
let storage = BSONDocumentStorage ( bson)
106
- try storage. validate ( )
107
- self = BSONDocument ( fromUnsafeBSON: storage)
91
+ let keys = try storage. validateAndRetrieveKeys ( )
92
+ self = BSONDocument ( fromUnsafeBSON: storage, keys : keys )
108
93
}
109
94
110
- private init ( fromUnsafeBSON storage: BSONDocumentStorage ) {
111
- self . keySet = Set ( )
95
+ private init ( fromUnsafeBSON storage: BSONDocumentStorage , keys: Set < String > ) {
112
96
self . storage = storage
113
- for (key, _) in self {
114
- self . keySet. insert ( key)
115
- }
97
+ self . keySet = keys
116
98
}
117
99
118
100
/**
@@ -240,6 +222,44 @@ public struct BSONDocument {
240
222
set { self [ member] = newValue }
241
223
}
242
224
225
+ /**
226
+ * Returns a copy of this document with an `_id` element prepended. If the document already contains an `_id`,
227
+ * returns the document as-is.
228
+ * - Throws: `BSONError.DocumentTooLargeError` if adding the `_id` would make the document exceed the maximum
229
+ * allowed size for a document.
230
+ * - SeeAlso: https://docs.mongodb.com/manual/core/document/#the-id-field
231
+ */
232
+ public func withID( ) throws -> BSONDocument {
233
+ guard !self . keySet. contains ( " _id " ) else {
234
+ return self
235
+ }
236
+
237
+ var newStorage = BSONDocumentStorage ( )
238
+ // placeholder for length
239
+ newStorage. buffer. writeInteger ( 0 , endianness: . little, as: Int32 . self)
240
+ var newSize = self . storage. encodedLength
241
+
242
+ let _id = BSON . objectID ( )
243
+ newSize += newStorage. append ( key: " _id " , value: _id)
244
+
245
+ guard newSize <= BSON_MAX_SIZE else {
246
+ throw BSONError . DocumentTooLargeError ( value: _id. bsonValue, forKey: " _id " )
247
+ }
248
+
249
+ guard let suffix = self . storage. buffer. getBytes ( at: 4 , length: self . storage. encodedLength - 4 ) else {
250
+ throw BSONError . InternalError (
251
+ message: " Failed to slice buffer from 4 to \( self . storage. encodedLength) : \( self . storage. buffer) "
252
+ )
253
+ }
254
+ newStorage. buffer. writeBytes ( suffix)
255
+
256
+ var newKeys = self . keySet
257
+ newKeys. insert ( " _id " )
258
+ var document = BSONDocument ( fromUnsafeBSON: newStorage, keys: newKeys)
259
+ document. storage. encodedLength = newSize
260
+ return document
261
+ }
262
+
243
263
/**
244
264
* Sets a BSON element with the corresponding key
245
265
* if element.value is nil the element is deleted from the BSON
@@ -252,10 +272,11 @@ public struct BSONDocument {
252
272
}
253
273
// appending new key
254
274
self . keySet. insert ( key)
255
- self . storage. buffer. moveWriterIndex ( to: self . byteLength - 1 ) // setup to overwrite null terminator
275
+ // setup to overwrite null terminator
276
+ self . storage. buffer. moveWriterIndex ( to: self . storage. encodedLength - 1 )
256
277
let size = self . storage. append ( key: key, value: value)
257
278
self . storage. buffer. writeInteger ( 0 , endianness: . little, as: UInt8 . self) // add back in our null terminator
258
- self . byteLength += size
279
+ self . storage . encodedLength += size
259
280
return
260
281
}
261
282
@@ -265,21 +286,24 @@ public struct BSONDocument {
265
286
throw BSONError . InternalError ( message: " Cannot find \( key) to delete " )
266
287
}
267
288
289
+ let prefixLength = range. startIndex
290
+ let suffixLength = self . storage. encodedLength - range. endIndex
291
+
268
292
guard
269
- let prefix = self . storage. buffer. getBytes ( at: 0 , length: range . startIndex ) ,
270
- let suffix = self . storage. buffer. getBytes ( at: range. endIndex, length: self . byteLength - range . endIndex )
293
+ let prefix = self . storage. buffer. getBytes ( at: 0 , length: prefixLength ) ,
294
+ let suffix = self . storage. buffer. getBytes ( at: range. endIndex, length: suffixLength )
271
295
else {
272
296
throw BSONError . InternalError (
273
297
message: " Cannot slice buffer from " +
274
298
" 0 to len \( range. startIndex) and from \( range. endIndex) " +
275
- " to len \( self . byteLength - range . endIndex ) : \( self . storage. buffer) "
299
+ " to len \( suffixLength ) : \( self . storage. buffer) "
276
300
)
277
301
}
278
302
279
303
var newStorage = BSONDocumentStorage ( )
280
304
newStorage. buffer. writeBytes ( prefix)
281
305
282
- var newSize = self . byteLength - ( range. endIndex - range. startIndex)
306
+ var newSize = self . storage . encodedLength - ( range. endIndex - range. startIndex)
283
307
if let value = value {
284
308
// Overwriting
285
309
let size = newStorage. append ( key: key, value: value)
@@ -296,9 +320,9 @@ public struct BSONDocument {
296
320
newStorage. buffer. writeBytes ( suffix)
297
321
298
322
self . storage = newStorage
299
- self . byteLength = newSize
300
- guard self . byteLength == self . storage. buffer. readableBytes else {
301
- fatalError ( " BSONDocument's encoded byte length is \( self . byteLength ) , however the " +
323
+ self . storage . encodedLength = newSize
324
+ guard self . storage . encodedLength == self . storage. buffer. readableBytes else {
325
+ fatalError ( " BSONDocument's encoded byte length is \( self . storage . encodedLength ) , however the " +
302
326
" buffer has \( self . storage. buffer. readableBytes) readable bytes " )
303
327
}
304
328
}
@@ -314,6 +338,21 @@ public struct BSONDocument {
314
338
/// Create BSONDocumentStorage with a 0 capacity buffer.
315
339
internal init ( ) { self . buffer = BSON_ALLOCATOR . buffer ( capacity: 0 ) }
316
340
341
+ internal var encodedLength : Int {
342
+ get {
343
+ guard let encodedLength = self . buffer. getInteger ( at: 0 , endianness: . little, as: Int32 . self) else {
344
+ fatalError ( " Cannot read encoded Length of BSON from buffer " )
345
+ }
346
+ return Int ( encodedLength)
347
+ }
348
+ set {
349
+ guard newValue <= Int32 . max else {
350
+ fatalError ( " Cannot cast \( newValue) down to Int32 " )
351
+ }
352
+ self . buffer. setInteger ( Int32 ( newValue) , at: 0 , endianness: . little, as: Int32 . self)
353
+ }
354
+ }
355
+
317
356
/// Appends element to underlying BSON bytes, returns the size of the element appended: type + key + value
318
357
@discardableResult internal mutating func append( key: String , value: BSON ) -> Int {
319
358
let writer = self . buffer. writerIndex
@@ -323,36 +362,44 @@ public struct BSONDocument {
323
362
return self . buffer. writerIndex - writer
324
363
}
325
364
326
- internal func validate( ) throws {
365
+ @discardableResult
366
+ internal func validateAndRetrieveKeys( ) throws -> Set < String > {
327
367
// Pull apart the underlying binary into [KeyValuePair], should reveal issues
328
- guard let byteLength = self . buffer. getInteger ( at: 0 , endianness: . little, as: Int32 . self) else {
329
- throw BSONError . InvalidArgumentError ( message: " Validation Failed: Cannot read byteLength " )
368
+ guard let encodedLength = self . buffer. getInteger ( at: 0 , endianness: . little, as: Int32 . self) else {
369
+ throw BSONError . InvalidArgumentError ( message: " Validation Failed: Cannot read encoded length " )
330
370
}
331
371
332
- guard byteLength >= BSON_MIN_SIZE && byteLength <= BSON_MAX_SIZE else {
372
+ guard encodedLength >= BSON_MIN_SIZE && encodedLength <= BSON_MAX_SIZE else {
333
373
throw BSONError . InvalidArgumentError (
334
- message: " Validation Failed: BSON cannot be \( byteLength ) bytes long "
374
+ message: " Validation Failed: BSON cannot be \( encodedLength ) bytes long "
335
375
)
336
376
}
337
377
338
- guard byteLength == self . buffer. readableBytes else {
378
+ guard encodedLength == self . buffer. readableBytes else {
339
379
throw BSONError . InvalidArgumentError (
340
- message: " BSONDocument's encoded byte length is \( byteLength ) , however the " +
380
+ message: " BSONDocument's encoded byte length is \( encodedLength ) , however the " +
341
381
" buffer has \( self . buffer. readableBytes) readable bytes "
342
382
)
343
383
}
344
384
385
+ var keySet = Set < String > ( )
345
386
let iter = BSONDocumentIterator ( over: self . buffer)
346
387
// Implicitly validate with iterator
347
388
do {
348
- while let ( _, value) = try iter. nextThrowing ( ) {
389
+ while let ( key, value) = try iter. nextThrowing ( ) {
390
+ let ( inserted, _) = keySet. insert ( key)
391
+ guard inserted else {
392
+ throw BSONError . InvalidArgumentError (
393
+ message: " Validation Failed: BSON contains multiple values for key \( key) "
394
+ )
395
+ }
349
396
switch value {
350
397
case let . document( doc) :
351
- try doc. storage. validate ( )
398
+ try doc. storage. validateAndRetrieveKeys ( )
352
399
case let . array( array) :
353
400
for item in array {
354
401
if let doc = item. documentValue {
355
- try doc. storage. validate ( )
402
+ try doc. storage. validateAndRetrieveKeys ( )
356
403
}
357
404
}
358
405
default :
@@ -364,6 +411,8 @@ public struct BSONDocument {
364
411
message: " Validation Failed: \( error. message) "
365
412
)
366
413
}
414
+
415
+ return keySet
367
416
}
368
417
}
369
418
}
@@ -449,11 +498,11 @@ extension BSONDocument: BSONValue {
449
498
450
499
internal static func read( from buffer: inout ByteBuffer ) throws -> BSON {
451
500
let reader = buffer. readerIndex
452
- guard let byteLength = buffer. readInteger ( endianness: . little, as: Int32 . self) else {
501
+ guard let encodedLength = buffer. readInteger ( endianness: . little, as: Int32 . self) else {
453
502
throw BSONError . InternalError ( message: " Cannot read document byte length " )
454
503
}
455
504
buffer. moveReaderIndex ( to: reader)
456
- guard let bytes = buffer. readBytes ( length: Int ( byteLength ) ) else {
505
+ guard let bytes = buffer. readBytes ( length: Int ( encodedLength ) ) else {
457
506
throw BSONError . InternalError ( message: " Cannot read document contents " )
458
507
}
459
508
return . document( try BSONDocument ( fromBSON: Data ( bytes) ) )
0 commit comments