@@ -62,14 +62,39 @@ pub(crate) fn get_int_raw(val: RawBsonRef<'_>) -> Option<i64> {
62
62
}
63
63
}
64
64
65
+ #[ allow( private_bounds) ]
66
+ pub ( crate ) fn round_clamp < T : RoundClampTarget > ( input : f64 ) -> T {
67
+ T :: round_clamp ( input)
68
+ }
69
+
70
+ trait RoundClampTarget {
71
+ fn round_clamp ( input : f64 ) -> Self ;
72
+ }
73
+
74
+ impl RoundClampTarget for u64 {
75
+ #[ allow( clippy:: cast_sign_loss, clippy:: cast_possible_truncation) ]
76
+ fn round_clamp ( input : f64 ) -> Self {
77
+ input as u64
78
+ }
79
+ }
80
+
81
+ impl RoundClampTarget for u32 {
82
+ #[ allow( clippy:: cast_sign_loss, clippy:: cast_possible_truncation) ]
83
+ fn round_clamp ( input : f64 ) -> Self {
84
+ input as u32
85
+ }
86
+ }
87
+
65
88
/// Coerce numeric types into an `u64` if it would be lossless to do so. If this Bson is not numeric
66
89
/// or the conversion would be lossy (e.g. 1.5 -> 1), this returns `None`.
67
90
#[ allow( clippy:: cast_possible_truncation) ]
68
91
pub ( crate ) fn get_u64 ( val : & Bson ) -> Option < u64 > {
69
92
match * val {
70
93
Bson :: Int32 ( i) => u64:: try_from ( i) . ok ( ) ,
71
94
Bson :: Int64 ( i) => u64:: try_from ( i) . ok ( ) ,
72
- Bson :: Double ( f) if ( f - ( f as u64 as f64 ) ) . abs ( ) <= f64:: EPSILON => Some ( f as u64 ) ,
95
+ Bson :: Double ( f) if ( f - ( round_clamp :: < u64 > ( f) as f64 ) ) . abs ( ) <= f64:: EPSILON => {
96
+ Some ( round_clamp ( f) )
97
+ }
73
98
_ => None ,
74
99
}
75
100
}
@@ -291,6 +316,31 @@ impl RawDocumentCollection for RawArrayBuf {
291
316
}
292
317
}
293
318
319
+ pub ( crate ) mod option_u64_as_i64 {
320
+ use serde:: { Deserialize , Serialize } ;
321
+
322
+ pub ( crate ) fn serialize < S : serde:: Serializer > (
323
+ value : & Option < u64 > ,
324
+ s : S ,
325
+ ) -> std:: result:: Result < S :: Ok , S :: Error > {
326
+ let conv: Option < i64 > = value
327
+ . as_ref ( )
328
+ . map ( |& u| u. try_into ( ) )
329
+ . transpose ( )
330
+ . map_err ( serde:: ser:: Error :: custom) ?;
331
+ conv. serialize ( s)
332
+ }
333
+
334
+ pub ( crate ) fn deserialize < ' de , D : serde:: Deserializer < ' de > > (
335
+ d : D ,
336
+ ) -> std:: result:: Result < Option < u64 > , D :: Error > {
337
+ let conv = Option :: < i64 > :: deserialize ( d) ?;
338
+ conv. map ( |i| i. try_into ( ) )
339
+ . transpose ( )
340
+ . map_err ( serde:: de:: Error :: custom)
341
+ }
342
+ }
343
+
294
344
#[ cfg( test) ]
295
345
mod test {
296
346
use crate :: bson_util:: num_decimal_digits;
0 commit comments