@@ -74,12 +74,27 @@ public struct BSONDocument {
74
74
* - SeeAlso: http://bsonspec.org/
75
75
*/
76
76
public init ( fromBSON bson: ByteBuffer ) throws {
77
- let storage = BSONDocumentStorage ( bson)
77
+ let storage = BSONDocumentStorage ( bson. slice ( ) )
78
78
try storage. validate ( )
79
- self = BSONDocument ( fromUnsafeBSON: storage)
79
+ self . storage = storage
80
+ }
81
+
82
+ /**
83
+ * Initialize a new `BSONDocument` from the provided BSON data without validating the elements. The first four
84
+ * bytes must accurately reflect the length of the buffer, however.
85
+ *
86
+ * If invalid BSON data is provided, undefined behavior or server-side errors may occur when using the
87
+ * resultant `BSONDocument`.
88
+ *
89
+ * - Throws: `BSONError.InvalidArgumentError` if the provided BSON's length does not match the encoded length.
90
+ */
91
+ public init ( fromBSONWithoutValidatingElements bson: ByteBuffer ) throws {
92
+ let storage = BSONDocumentStorage ( bson)
93
+ try self . init ( fromBSONWithoutValidatingElements: storage)
80
94
}
81
95
82
- internal init ( fromUnsafeBSON storage: BSONDocumentStorage ) {
96
+ internal init ( fromBSONWithoutValidatingElements storage: BSONDocumentStorage ) throws {
97
+ try storage. validateLength ( )
83
98
self . storage = storage
84
99
}
85
100
@@ -129,23 +144,15 @@ public struct BSONDocument {
129
144
130
145
/// The keys in this `BSONDocument`.
131
146
public var keys : [ String ] {
132
- do {
133
- return try BSONDocumentIterator . getKeys ( from: self . storage. buffer)
134
- } catch {
135
- fatalError ( " Failed to retrieve keys for document " )
136
- }
147
+ BSONDocumentIterator . getKeys ( from: self . storage. buffer)
137
148
}
138
149
139
150
/// The values in this `BSONDocument`.
140
151
public var values : [ BSON ] { self . map { _, val in val } }
141
152
142
153
/// The number of (key, value) pairs stored at the top level of this document.
143
154
public var count : Int {
144
- do {
145
- return try BSONDocumentIterator . getKeys ( from: self . storage. buffer) . count
146
- } catch {
147
- return 0
148
- }
155
+ BSONDocumentIterator . getKeys ( from: self . storage. buffer) . count
149
156
}
150
157
151
158
/// A copy of the `ByteBuffer` backing this document, containing raw BSON data. As `ByteBuffer`s implement
@@ -158,7 +165,8 @@ public struct BSONDocument {
158
165
159
166
/// Returns a `Boolean` indicating whether this `BSONDocument` contains the provided key.
160
167
public func hasKey( _ key: String ) -> Bool {
161
- ( try ? BSONDocumentIterator . find ( key: key, in: self ) ) != nil
168
+ let it = self . makeIterator ( )
169
+ return it. findValue ( forKey: key) != nil
162
170
}
163
171
164
172
/**
@@ -174,19 +182,10 @@ public struct BSONDocument {
174
182
*/
175
183
public subscript( key: String ) -> BSON ? {
176
184
get {
177
- do {
178
- return try BSONDocumentIterator . find ( key: key, in: self ) ? . value
179
- } catch {
180
- fatalError ( " Error looking up key \( key) in document: \( error) " )
181
- }
185
+ BSONDocumentIterator . find ( key: key, in: self ) ? . value
182
186
}
183
187
set {
184
- // The only time this would crash is document too big error
185
- do {
186
- return try self . set ( key: key, to: newValue)
187
- } catch {
188
- fatalError ( " Failed to set \( key) to \( String ( describing: newValue) ) : \( error) " )
189
- }
188
+ self . set ( key: key, to: newValue)
190
189
}
191
190
}
192
191
@@ -251,10 +250,9 @@ public struct BSONDocument {
251
250
)
252
251
}
253
252
newStorage. buffer. writeBytes ( suffix)
253
+ newStorage. encodedLength = newSize
254
254
255
- var document = BSONDocument ( fromUnsafeBSON: newStorage)
256
- document. storage. encodedLength = newSize
257
- return document
255
+ return try BSONDocument ( fromBSONWithoutValidatingElements: newStorage)
258
256
}
259
257
260
258
/// Appends the provided key value pair without checking to see if the key already exists.
@@ -271,8 +269,8 @@ public struct BSONDocument {
271
269
* Sets a BSON element with the corresponding key
272
270
* if element.value is nil the element is deleted from the BSON
273
271
*/
274
- internal mutating func set( key: String , to value: BSON ? ) throws {
275
- guard let range = try BSONDocumentIterator . findByteRange ( for: key, in: self ) else {
272
+ private mutating func set( key: String , to value: BSON ? ) {
273
+ guard let range = BSONDocumentIterator . findByteRange ( for: key, in: self ) else {
276
274
guard let value = value else {
277
275
// no-op: key does not exist and the value is nil
278
276
return
@@ -285,18 +283,18 @@ public struct BSONDocument {
285
283
let suffixLength = self . storage. encodedLength - range. endIndex
286
284
287
285
guard
288
- let prefix = self . storage. buffer. getBytes ( at: 0 , length: prefixLength) ,
286
+ var prefix = self . storage. buffer. getSlice ( at: 0 , length: prefixLength) ,
289
287
let suffix = self . storage. buffer. getBytes ( at: range. endIndex, length: suffixLength)
290
288
else {
291
- throw BSONError . InternalError (
292
- message : " Cannot slice buffer from " +
289
+ fatalError (
290
+ " Cannot slice buffer from " +
293
291
" 0 to len \( range. startIndex) and from \( range. endIndex) " +
294
292
" to len \( suffixLength) : \( self . storage. buffer) "
295
293
)
296
294
}
297
295
298
296
var newStorage = BSONDocumentStorage ( )
299
- newStorage. buffer. writeBytes ( prefix)
297
+ newStorage. buffer. writeBuffer ( & prefix)
300
298
301
299
var newSize = self . storage. encodedLength - ( range. endIndex - range. startIndex)
302
300
if let value = value {
@@ -305,7 +303,7 @@ public struct BSONDocument {
305
303
newSize += size
306
304
307
305
guard newSize <= BSON_MAX_SIZE else {
308
- throw BSONError . DocumentTooLargeError ( value: value. bsonValue, forKey: key)
306
+ fatalError ( BSONError . DocumentTooLargeError ( value: value. bsonValue, forKey: key) . message )
309
307
}
310
308
}
311
309
@@ -389,8 +387,12 @@ public struct BSONDocument {
389
387
return totalBytes
390
388
}
391
389
392
- internal func validate( ) throws {
393
- // Pull apart the underlying binary into [KeyValuePair], should reveal issues
390
+ /// Verify that the encoded length matches the actual length of the buffer and that the buffer is
391
+ /// isn't too small or too large.
392
+ ///
393
+ /// - Throws: `BSONError.InvalidArgumentError` if validation fails
394
+ ///
395
+ internal func validateLength( ) throws {
394
396
guard let encodedLength = self . buffer. getInteger ( at: 0 , endianness: . little, as: Int32 . self) else {
395
397
throw BSONError . InvalidArgumentError ( message: " Validation Failed: Cannot read encoded length " )
396
398
}
@@ -403,11 +405,16 @@ public struct BSONDocument {
403
405
404
406
guard encodedLength == self . buffer. readableBytes else {
405
407
throw BSONError . InvalidArgumentError (
406
- message: " BSONDocument's encoded byte length is \( encodedLength) , however the " +
408
+ message: " BSONDocument's encoded byte length is \( encodedLength) , however the " +
407
409
" buffer has \( self . buffer. readableBytes) readable bytes "
408
410
)
409
411
}
412
+ }
410
413
414
+ internal func validate( ) throws {
415
+ try self . validateLength ( )
416
+
417
+ // Pull apart the underlying binary into [KeyValuePair], should reveal issues
411
418
var keySet = Set < String > ( )
412
419
let iter = BSONDocumentIterator ( over: self . buffer)
413
420
do {
@@ -528,7 +535,7 @@ extension BSONDocument: BSONValue {
528
535
throw BSONError . InternalError ( message: " Cannot read document contents " )
529
536
}
530
537
531
- return . document( BSONDocument ( fromUnsafeBSON : BSONDocument . BSONDocumentStorage ( bytes) ) )
538
+ return . document( try BSONDocument ( fromBSONWithoutValidatingElements : BSONDocument . BSONDocumentStorage ( bytes) ) )
532
539
}
533
540
534
541
internal func write( to buffer: inout ByteBuffer ) {
0 commit comments