@@ -62,14 +62,39 @@ pub(crate) fn get_int_raw(val: RawBsonRef<'_>) -> Option<i64> {
6262 }
6363}
6464
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+
6588/// Coerce numeric types into an `u64` if it would be lossless to do so. If this Bson is not numeric
6689/// or the conversion would be lossy (e.g. 1.5 -> 1), this returns `None`.
6790#[ allow( clippy:: cast_possible_truncation) ]
6891pub ( crate ) fn get_u64 ( val : & Bson ) -> Option < u64 > {
6992 match * val {
7093 Bson :: Int32 ( i) => u64:: try_from ( i) . ok ( ) ,
7194 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+ }
7398 _ => None ,
7499 }
75100}
@@ -291,6 +316,31 @@ impl RawDocumentCollection for RawArrayBuf {
291316 }
292317}
293318
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+
294344#[ cfg( test) ]
295345mod test {
296346 use crate :: bson_util:: num_decimal_digits;
0 commit comments