@@ -2,25 +2,27 @@ pub(crate) mod async_encoding;
2
2
3
3
use std:: time:: Duration ;
4
4
5
- use bson:: { doc, oid:: ObjectId , Bson , Document } ;
6
5
use serde:: { ser, Deserialize , Deserializer , Serialize , Serializer } ;
7
6
8
- use crate :: error:: { ErrorKind , Result } ;
7
+ use crate :: {
8
+ bson:: { doc, oid:: ObjectId , Binary , Bson , Document , JavaScriptCodeWithScope , Regex } ,
9
+ error:: { ErrorKind , Result } ,
10
+ } ;
9
11
10
12
/// Coerce numeric types into an `i64` if it would be lossless to do so. If this Bson is not numeric
11
13
/// or the conversion would be lossy (e.g. 1.5 -> 1), this returns `None`.
12
14
pub ( crate ) fn get_int ( val : & Bson ) -> Option < i64 > {
13
15
match * val {
14
- Bson :: I32 ( i) => Some ( i64:: from ( i) ) ,
15
- Bson :: I64 ( i) => Some ( i) ,
16
- Bson :: FloatingPoint ( f) if f == f as i64 as f64 => Some ( f as i64 ) ,
16
+ Bson :: Int32 ( i) => Some ( i64:: from ( i) ) ,
17
+ Bson :: Int64 ( i) => Some ( i) ,
18
+ Bson :: Double ( f) if f == f as i64 as f64 => Some ( f as i64 ) ,
17
19
_ => None ,
18
20
}
19
21
}
20
22
21
23
pub ( crate ) fn add_id ( doc : & mut Document ) {
22
24
doc. entry ( "_id" . to_string ( ) )
23
- . or_insert_with ( || Bson :: ObjectId ( ObjectId :: new ( ) . unwrap ( ) ) ) ;
25
+ . or_insert_with ( || Bson :: ObjectId ( ObjectId :: new ( ) ) ) ;
24
26
}
25
27
26
28
pub ( crate ) fn to_bson_array ( docs : & [ Document ] ) -> Bson {
@@ -61,12 +63,15 @@ pub(crate) fn update_document_check(update: &Document) -> Result<()> {
61
63
}
62
64
}
63
65
64
- pub ( crate ) fn serialize_duration_as_i64_millis < S : Serializer > (
66
+ pub ( crate ) fn serialize_duration_as_int_millis < S : Serializer > (
65
67
val : & Option < Duration > ,
66
68
serializer : S ,
67
69
) -> std:: result:: Result < S :: Ok , S :: Error > {
68
70
match val {
69
- Some ( duration) => serializer. serialize_i64 ( duration. as_millis ( ) as i64 ) ,
71
+ Some ( duration) if duration. as_millis ( ) > i32:: MAX as u128 => {
72
+ serializer. serialize_i64 ( duration. as_millis ( ) as i64 )
73
+ }
74
+ Some ( duration) => serializer. serialize_i32 ( duration. as_millis ( ) as i32 ) ,
70
75
None => serializer. serialize_none ( ) ,
71
76
}
72
77
}
@@ -128,7 +133,7 @@ pub fn doc_size_bytes(doc: &Document) -> usize {
128
133
129
134
pub fn size_bytes ( val : & Bson ) -> usize {
130
135
match val {
131
- Bson :: FloatingPoint ( _) => 8 ,
136
+ Bson :: Double ( _) => 8 ,
132
137
//
133
138
// * length prefix (4 bytes)
134
139
// * number of UTF-8 bytes
@@ -158,7 +163,9 @@ pub fn size_bytes(val: &Bson) -> usize {
158
163
// for $pattern and $opts:
159
164
// * number of UTF-8 bytes
160
165
// * null terminator (1 byte)
161
- Bson :: RegExp ( pattern, opts) => pattern. len ( ) + 1 + opts. len ( ) + 1 ,
166
+ Bson :: RegularExpression ( Regex { pattern, options } ) => {
167
+ pattern. len ( ) + 1 + options. len ( ) + 1
168
+ }
162
169
//
163
170
// * length prefix (4 bytes)
164
171
// * number of UTF-8 bytes
@@ -170,24 +177,37 @@ pub fn size_bytes(val: &Bson) -> usize {
170
177
// * number of UTF-8 bytes in code
171
178
// * null terminator for code (1 byte)
172
179
// * length of document
173
- Bson :: JavaScriptCodeWithScope ( code, scope) => {
180
+ Bson :: JavaScriptCodeWithScope ( JavaScriptCodeWithScope { code, scope } ) => {
174
181
4 + 4 + code. len ( ) + 1 + doc_size_bytes ( scope)
175
182
}
176
- Bson :: I32 ( _) => 4 ,
177
- Bson :: I64 ( _) => 8 ,
178
- Bson :: TimeStamp ( _) => 8 ,
183
+ Bson :: Int32 ( _) => 4 ,
184
+ Bson :: Int64 ( _) => 8 ,
185
+ Bson :: Timestamp ( _) => 8 ,
179
186
//
180
187
// * i32 length prefix (4 bytes)
181
188
// * subtype (1 byte)
182
189
// * number of bytes
183
- Bson :: Binary ( _ , bytes) => 4 + 1 + bytes. len ( ) ,
190
+ Bson :: Binary ( Binary { bytes, .. } ) => 4 + 1 + bytes. len ( ) ,
184
191
Bson :: ObjectId ( _) => 12 ,
185
- Bson :: UtcDatetime ( _) => 8 ,
192
+ Bson :: DateTime ( _) => 8 ,
186
193
//
187
194
// * i32 length prefix (4 bytes)
188
195
// * subtype (1 byte)
189
196
// * number of UTF-8 bytes
190
197
Bson :: Symbol ( s) => 4 + 1 + s. len ( ) ,
198
+ Bson :: Decimal128 ( ..) => 128 / 8 ,
199
+ Bson :: Undefined | Bson :: MaxKey | Bson :: MinKey => 0 ,
200
+ // DbPointer doesn't have public details exposed by the BSON library, but it comprises of a
201
+ // namespace and an ObjectId. Since our methods to calculate the size of BSON values are
202
+ // only used to estimate the cutoff for batches when making a large insert, we can just
203
+ // assume the largest possible size for a namespace, which is 120 bytes. Therefore, the size
204
+ // is:
205
+ //
206
+ // * i32 length prefix (4 bytes)
207
+ // * namespace (120 bytes)
208
+ // * null terminator (1 byte)
209
+ // * objectid (12 bytes)
210
+ Bson :: DbPointer ( ..) => 4 + 120 + 1 + 12 ,
191
211
}
192
212
}
193
213
@@ -209,7 +229,16 @@ fn num_decimal_digits(n: usize) -> usize {
209
229
210
230
#[ cfg( test) ]
211
231
mod test {
212
- use bson:: { doc, oid:: ObjectId , spec:: BinarySubtype , Bson } ;
232
+ use crate :: bson:: {
233
+ doc,
234
+ oid:: ObjectId ,
235
+ spec:: BinarySubtype ,
236
+ Binary ,
237
+ Bson ,
238
+ JavaScriptCodeWithScope ,
239
+ Regex ,
240
+ Timestamp ,
241
+ } ;
213
242
use chrono:: { DateTime , NaiveDateTime , Utc } ;
214
243
215
244
use super :: doc_size_bytes;
@@ -220,23 +249,23 @@ mod test {
220
249
let doc = doc ! {
221
250
"double" : -12.3 ,
222
251
"string" : "foo" ,
223
- "array" : [ "foobar" , -7 , Bson :: Null , Bson :: TimeStamp ( 1278 ) , false ] ,
252
+ "array" : [ "foobar" , -7 , Bson :: Null , Bson :: Timestamp ( Timestamp { time : 12345 , increment : 67890 } ) , false ] ,
224
253
"document" : {
225
254
"x" : 1 ,
226
255
"yyz" : "Rush is one of the greatest bands of all time" ,
227
256
} ,
228
257
"bool" : true ,
229
258
"null" : Bson :: Null ,
230
- "regex" : Bson :: RegExp ( "foobar" . into( ) , "i" . into( ) ) ,
259
+ "regex" : Bson :: RegularExpression ( Regex { pattern : "foobar" . into( ) , options : "i" . into( ) } ) ,
231
260
"code" : Bson :: JavaScriptCode ( "foo(x) { return x + 1; }" . into( ) ) ,
232
- "code with scope" : Bson :: JavaScriptCodeWithScope (
233
- "foo(x) { return x + y; }" . into( ) ,
234
- doc! { "y" : -17 } ,
235
- ) ,
261
+ "code with scope" : Bson :: JavaScriptCodeWithScope ( JavaScriptCodeWithScope {
262
+ code : "foo(x) { return x + y; }" . into( ) ,
263
+ scope : doc! { "y" : -17 } ,
264
+ } ) ,
236
265
"i32" : 12i32 ,
237
266
"i64" : -126i64 ,
238
- "timestamp" : Bson :: TimeStamp ( 1223334444 ) ,
239
- "binary" : Bson :: Binary ( BinarySubtype :: Generic , vec![ 3 , 222 , 11 ] ) ,
267
+ "timestamp" : Bson :: Timestamp ( Timestamp { time : 12233 , increment : 34444 } ) ,
268
+ "binary" : Bson :: Binary ( Binary { subtype : BinarySubtype :: Generic , bytes : vec![ 3 , 222 , 11 ] } ) ,
240
269
"objectid" : ObjectId :: with_bytes( [ 1 ; 12 ] ) ,
241
270
"datetime" : DateTime :: from_utc(
242
271
NaiveDateTime :: from_timestamp( 4444333221 , 0 ) ,
@@ -248,7 +277,7 @@ mod test {
248
277
let size_bytes = doc_size_bytes ( & doc) ;
249
278
250
279
let mut serialized_bytes = Vec :: new ( ) ;
251
- bson :: encode_document ( & mut serialized_bytes, & doc ) . unwrap ( ) ;
280
+ doc . to_writer ( & mut serialized_bytes) . unwrap ( ) ;
252
281
253
282
assert_eq ! ( size_bytes, serialized_bytes. len( ) ) ;
254
283
}
0 commit comments