Coverage Report

Created: 2026-08-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bson-rust/src/serde_helpers.rs
Line
Count
Source
1
//! Collection of helper functions for serializing to and deserializing from BSON using Serde.
2
//!
3
//! The submodules here provide converter types that can be used with the `#[serde(with = ...)]`
4
//! annotation.  These modules follow a naming convention:
5
//! * _module name_ - the _base type_ to be converted
6
//! * _module_`::AsFoo` - when serializing/deserializing a field of the base type, store it as a
7
//!   _Foo_ value
8
//! * _module_`::FromFoo` - when serializing/deserializing a field of type _Foo_, store it as a
9
//!   value of the base type
10
//!
11
//! For example, the [`object_id`] module provides both [`object_id::AsHexString`] and
12
//! [`object_id::FromHexString`]:
13
//! ```
14
//! # use serde::{Deserialize, Serialize};
15
//! use bson::{doc, serde_helpers::object_id, oid::ObjectId};
16
//!
17
//! #[derive(Deserialize, Serialize)]
18
//! struct Example {
19
//!   // No conversions applied; will serialize as the BSON value.
20
//!   basic: ObjectId,
21
//!   // In code, an ObjectId; when serialized, a hex string.
22
//!   #[serde(with = "object_id::AsHexString")]
23
//!   as_hex: ObjectId,
24
//!   // In code, a hex string; serializes as a BSON objectid.
25
//!   #[serde(with = "object_id::FromHexString")]
26
//!   from_hex: String,
27
//! }
28
//! ```
29
//!
30
//! If the `serde_with-3` feature is enabled, these converters can also be used with the
31
//! `#[serde_as(as = ...)]` annotation, which provides similar conversion functionality with the
32
//! added flexibility of handling many container types automatically:
33
//! ```
34
//! # #[cfg(feature = "serde_with-3")]
35
//! # {
36
//! # use serde::{Deserialize, Serialize};
37
//! use bson::{doc, serde_helpers::object_id, oid::ObjectId};
38
//!
39
//! #[serde_with::serde_as]
40
//! #[derive(Deserialize, Serialize)]
41
//! struct Example {
42
//!   #[serde_as(as = "Option<object_id::AsHexString>")]
43
//!   optional: Option<ObjectId>,
44
//! }
45
//! # }
46
//! ```
47
//! See the crate documentation for [`serde_with`](https://docs.rs/serde_with/latest/serde_with/) for more details.
48
49
use serde::{Deserialize, Serialize, de::Visitor};
50
use std::{
51
    marker::PhantomData,
52
    ops::{Deref, DerefMut},
53
    result::Result,
54
};
55
56
/// Type converters for serializing and deserializing [`crate::oid::ObjectId`].
57
///
58
/// ## Available converters
59
/// - [`object_id::AsHexString`] — converts an [`crate::oid::ObjectId`] to and from a hex string.
60
/// - [`object_id::FromHexString`] — converts a hex string to and from an [`crate::oid::ObjectId`].
61
pub mod object_id {
62
    use crate::oid::ObjectId;
63
    use serde::{Deserialize, Deserializer, Serialize, Serializer};
64
65
    serde_conv_doc!(
66
        /// Converts an [`ObjectId`] to and from a hex string.
67
        /// ```rust
68
        /// # #[cfg(feature = "serde_with-3")]
69
        /// # {
70
        /// use bson::{serde_helpers::object_id, oid::ObjectId};
71
        /// use serde::{Serialize, Deserialize};
72
        /// use serde_with::serde_as;
73
        /// #[serde_as]
74
        /// #[derive(Serialize, Deserialize)]
75
        /// struct Item {
76
        ///     #[serde_as(as = "object_id::AsHexString")]
77
        ///     pub id: ObjectId,
78
        /// }
79
        /// # }
80
        /// ```
81
        pub AsHexString,
82
        ObjectId,
83
0
        |oid: &ObjectId| -> Result<String, String> {
84
0
            Ok(oid.to_hex())
85
0
        },
86
0
        |hex: String| -> Result<ObjectId, String> {
87
0
            ObjectId::parse_str(&hex).map_err(|e| format!("Invalid ObjectId string, {}: {}", hex, e))
88
0
        }
89
    );
90
91
    serde_conv_doc!(
92
        /// Converts a hex string to and from an [`ObjectId`].
93
        /// ```rust
94
        /// # #[cfg(feature = "serde_with-3")]
95
        /// # {
96
        /// use bson::serde_helpers::object_id;
97
        /// use serde::{Serialize, Deserialize};
98
        /// use serde_with::serde_as;
99
        /// #[serde_as]
100
        /// #[derive(Serialize, Deserialize)]
101
        /// struct Item {
102
        ///     #[serde_as(as = "object_id::FromHexString")]
103
        ///     pub id: String,
104
        /// }
105
        /// # }
106
        /// ```
107
        pub FromHexString,
108
        String,
109
0
        |hex: &String| -> Result<ObjectId, String> {
110
0
            ObjectId::parse_str(hex).map_err(|e| format!("Invalid ObjectId string, {}: {}", hex, e))
111
0
        },
112
0
        |oid: ObjectId| -> Result<String, String> {
113
0
            Ok(oid.to_hex())
114
0
        }
115
    );
116
}
117
118
/// Type converters for serializing and deserializing [`crate::DateTime`].
119
///
120
/// ## Available converters
121
/// - [`datetime::AsRfc3339String`] — converts a [`crate::DateTime`] to and from an RFC 3339 string.
122
/// - [`datetime::FromRfc3339String`] — converts a RFC 3339 string to and from a
123
///   [`crate::DateTime`].
124
/// - [`datetime::FromI64`] — converts an `i64` to and from a [`crate::DateTime`].
125
/// - [`datetime::AsI64`] — converts a [`crate::DateTime`] to and from an `i64`.
126
/// - [`datetime::FromChrono04DateTime`] — converts a [`chrono::DateTime`] to and from a
127
///   [`crate::DateTime`].
128
/// - [`datetime::FromJiff02Timestamp`] — converts a [`jiff::Timestamp`] to and from a
129
///   [`crate::DateTime`].
130
/// - [`datetime::FromTime03OffsetDateTime`] — converts a [`time::OffsetDateTime`] to and from a
131
///   [`crate::DateTime`].
132
pub mod datetime {
133
    use crate::DateTime;
134
    #[cfg(feature = "chrono-0_4")]
135
    use chrono::Utc;
136
    use serde::{Deserialize, Deserializer, Serialize, Serializer};
137
138
    serde_conv_doc!(
139
        /// Converts a [`DateTime`] to and from an RFC 3339 (ISO 8601) formatted string.
140
        /// ```rust
141
        /// # #[cfg(feature = "serde_with-3")]
142
        /// # {
143
        /// use bson::{serde_helpers::datetime, DateTime};
144
        /// use serde::{Serialize, Deserialize};
145
        /// use serde_with::serde_as;
146
        /// #[serde_as]
147
        /// #[derive(Serialize, Deserialize)]
148
        /// struct Event {
149
        ///     #[serde_as(as = "datetime::AsRfc3339String")]
150
        ///     pub date: DateTime,
151
        /// }
152
        /// # }
153
        /// ```
154
        pub AsRfc3339String,
155
        DateTime,
156
0
        |date: &DateTime| -> Result<String, String> {
157
0
            date.try_to_rfc3339_string().map_err(|e| {
158
0
                format!("Cannot format DateTime {} as RFC 3339 string: {}", date, e)
159
0
            })
160
0
        },
161
0
        |string: String| -> Result<DateTime, String> {
162
0
            DateTime::parse_rfc3339_str(&string).map_err(|e| format!("Cannot format RFC 3339 string {} as DateTime: {}", string, e))
163
0
        }
164
    );
165
166
    serde_conv_doc!(
167
        /// Converts an RFC 3339 (ISO 8601) formatted string to and from a [`DateTime`].
168
        /// ```rust
169
        /// # #[cfg(feature = "serde_with-3")]
170
        /// # {
171
        /// use bson::serde_helpers::datetime;
172
        /// use serde::{Serialize, Deserialize};
173
        /// use serde_with::serde_as;
174
        /// #[serde_as]
175
        /// #[derive(Serialize, Deserialize)]
176
        /// struct Event {
177
        ///     #[serde_as(as = "datetime::FromRfc3339String")]
178
        ///     pub date: String,
179
        /// }
180
        /// # }
181
        pub FromRfc3339String,
182
        String,
183
0
        |string: &String| -> Result<DateTime, String> {
184
0
            DateTime::parse_rfc3339_str(string).map_err(|e| format!("Cannot format RFC 3339 string {} as DateTime: {}", string, e))
185
0
        },
186
0
        |date: DateTime| -> Result<String, String> {
187
0
            date.try_to_rfc3339_string().map_err(|e| {
188
0
                format!("Cannot format DateTime {} as RFC 3339 string: {}", date, e)
189
0
            })
190
0
        }
191
    );
192
193
    serde_conv_doc!(
194
        /// Converts an `i64` integer to and from a [`DateTime`].
195
        ///
196
        /// The `i64` should represent milliseconds. See [`DateTime::from_millis`] for more details.
197
        /// ```rust
198
        /// # #[cfg(feature = "serde_with-3")]
199
        /// # {
200
        /// use bson::serde_helpers::datetime;
201
        /// use serde::{Serialize, Deserialize};
202
        /// use serde_with::serde_as;
203
        /// #[serde_as]
204
        /// #[derive(Serialize, Deserialize)]
205
        /// struct Item {
206
        ///     #[serde_as(as = "datetime::FromI64")]
207
        ///     pub now: i64,
208
        /// }
209
        /// # }
210
        /// ```
211
        pub FromI64,
212
        i64,
213
0
        |value: &i64| -> Result<DateTime, String> {
214
0
            Ok(DateTime::from_millis(*value))
215
0
        },
216
0
        |date: DateTime| -> Result<i64, String> {
217
0
            Ok(date.timestamp_millis())
218
0
        }
219
    );
220
221
    serde_conv_doc!(
222
        /// Converts a [`DateTime`] to and from an `i64` integer.
223
        ///
224
        /// The `i64` should represent milliseconds. See [`DateTime::from_millis`] for more details.
225
        /// ```rust
226
        /// # #[cfg(feature = "serde_with-3")]
227
        /// # {
228
        /// use bson::{serde_helpers::datetime, DateTime};
229
        /// use serde::{Serialize, Deserialize};
230
        /// use serde_with::serde_as;
231
        /// #[serde_as]
232
        /// #[derive(Serialize, Deserialize)]
233
        /// struct Item {
234
        ///     #[serde_as(as = "datetime::AsI64")]
235
        ///     pub now: DateTime,
236
        /// }
237
        /// # }
238
        /// ```
239
        pub AsI64,
240
        DateTime,
241
0
        |date: &DateTime| -> Result<i64, String> {
242
0
            Ok(date.timestamp_millis())
243
0
        },
244
0
        |value: i64| -> Result<DateTime, String> {
245
0
            Ok(DateTime::from_millis(value))
246
0
        }
247
    );
248
249
    #[cfg(feature = "chrono-0_4")]
250
    serde_conv_doc!(
251
        /// Converts a [`chrono::DateTime`] to and from a [`DateTime`].
252
        /// ```rust
253
        /// # #[cfg(all(feature = "chrono-0_4", feature = "serde_with-3"))]
254
        /// # {
255
        /// use bson::serde_helpers::datetime;
256
        /// use serde::{Serialize, Deserialize};
257
        /// use serde_with::serde_as;
258
        /// #[serde_as]
259
        /// #[derive(Serialize, Deserialize)]
260
        /// struct Event {
261
        ///     #[serde_as(as = "datetime::FromChrono04DateTime")]
262
        ///     pub date: chrono::DateTime<chrono::Utc>,
263
        /// }
264
        /// # }
265
        /// ```
266
        pub FromChrono04DateTime,
267
        chrono::DateTime<Utc>,
268
        |chrono_date: &chrono::DateTime<Utc>| -> Result<DateTime, String> {
269
            Ok(DateTime::from_chrono(*chrono_date))
270
        },
271
        |bson_date: DateTime| -> Result<chrono::DateTime<Utc>, String> {
272
            Ok(bson_date.to_chrono())
273
        }
274
    );
275
276
    #[cfg(feature = "jiff-0_2")]
277
    serde_conv_doc!(
278
        /// Converts a [`jiff::Timestamp`] to and from a [`DateTime`].
279
        /// ```rust
280
        /// # #[cfg(all(feature = "jiff-0_2", feature = "serde_with-3"))]
281
        /// # {
282
        /// use bson::serde_helpers::datetime;
283
        /// use serde::{Serialize, Deserialize};
284
        /// use serde_with::serde_as;
285
        /// #[serde_as]
286
        /// #[derive(Serialize, Deserialize)]
287
        /// struct Event {
288
        ///     #[serde_as(as = "datetime::FromJiff02Timestamp")]
289
        ///     pub date: jiff::Timestamp,
290
        /// }
291
        /// # }
292
        /// ```
293
        pub FromJiff02Timestamp,
294
        jiff::Timestamp,
295
        |jiff_ts: &jiff::Timestamp| -> Result<DateTime, String> {
296
            Ok(DateTime::from_jiff(*jiff_ts))
297
        },
298
        |bson_date: DateTime| -> Result<jiff::Timestamp, String> {
299
            Ok(bson_date.to_jiff())
300
        }
301
    );
302
303
    #[cfg(feature = "time-0_3")]
304
    serde_conv_doc!(
305
        /// Converts a [`time::OffsetDateTime`] to and from a [`DateTime`].
306
        /// ```rust
307
        /// # #[cfg(all(feature = "time-0_3", feature = "serde_with-3"))]
308
        /// # {
309
        /// use bson::serde_helpers::datetime;
310
        /// use serde::{Serialize, Deserialize};
311
        /// use serde_with::serde_as;
312
        /// #[serde_as]
313
        /// #[derive(Serialize, Deserialize)]
314
        /// struct Event {
315
        ///     #[serde_as(as = "datetime::FromTime03OffsetDateTime")]
316
        ///     pub date: time::OffsetDateTime,
317
        /// }
318
        /// # }
319
        /// ```
320
        pub FromTime03OffsetDateTime,
321
        time::OffsetDateTime,
322
        |value: &time::OffsetDateTime| -> Result<DateTime, String> {
323
            Ok(DateTime::from_time_0_3(*value))
324
        },
325
        |date: DateTime| -> Result<time::OffsetDateTime, String> {
326
            Ok(date.to_time_0_3())
327
        }
328
    );
329
}
330
331
/// Type converters for serializing and deserializing [`crate::Timestamp`].
332
///
333
/// ## Available converters
334
/// - [`timestamp::AsU32`] — converts a [`crate::Timestamp`] to and from a `u32`.
335
/// - [`timestamp::FromU32`] — converts a `u32` to and from a [`crate::Timestamp`].
336
pub mod timestamp {
337
    use crate::Timestamp;
338
    use serde::{Deserialize, Deserializer, Serialize, Serializer};
339
340
    serde_conv_doc!(
341
        /// Converts a [`Timestamp`] to and from a `u32`.
342
        ///
343
        /// The `u32` should represent seconds since the Unix epoch.
344
        ///
345
        /// Serialization errors if the Timestamp has a non-zero increment.
346
        /// ```rust
347
        /// # #[cfg(feature = "serde_with-3")]
348
        /// # {
349
        /// use bson::{serde_helpers::timestamp, Timestamp};
350
        /// use serde::{Serialize, Deserialize};
351
        /// use serde_with::serde_as;
352
        /// #[serde_as]
353
        /// #[derive(Serialize, Deserialize)]
354
        /// struct Item {
355
        ///     #[serde_as(as = "timestamp::AsU32")]
356
        ///     pub timestamp: Timestamp,
357
        /// }
358
        /// # }
359
        /// ```
360
        pub AsU32,
361
        Timestamp,
362
0
        |timestamp: &Timestamp| -> Result<u32, String> {
363
0
            if timestamp.increment != 0 {
364
0
                return Err(format!("Cannot convert Timestamp with a non-zero increment to u32: {:?}", timestamp));
365
0
            }
366
0
            Ok(timestamp.time)
367
0
        },
368
0
        |value: u32| -> Result<Timestamp, String> {
369
0
            Ok(Timestamp { time: value, increment: 0 })
370
0
        }
371
    );
372
373
    serde_conv_doc!(
374
        /// Converts a `u32` to and from a [`Timestamp`].
375
        ///
376
        /// The `u32` should represent seconds since the Unix epoch.
377
        ///
378
        /// Deserialization errors if the Timestamp has a non-zero increment.
379
        /// ```rust
380
        /// # #[cfg(feature = "serde_with-3")]
381
        /// # {
382
        /// use bson::serde_helpers::timestamp;
383
        /// use serde::{Serialize, Deserialize};
384
        /// use serde_with::serde_as;
385
        /// #[serde_as]
386
        /// #[derive(Serialize, Deserialize)]
387
        /// struct Event {
388
        ///     #[serde_as(as = "timestamp::FromU32")]
389
        ///     pub time: u32,
390
        /// }
391
        /// # }
392
        /// ```
393
        pub FromU32,
394
        u32,
395
0
        |value: &u32| -> Result<Timestamp, String> {
396
0
            Ok(Timestamp { time: *value, increment: 0 })
397
0
        },
398
0
        |timestamp: Timestamp| -> Result<u32, String> {
399
0
            if timestamp.increment != 0 {
400
0
                return Err(format!("Cannot convert Timestamp with a non-zero increment to u32: {:?}", timestamp));
401
0
            }
402
0
            Ok(timestamp.time)
403
0
        }
404
    );
405
}
406
407
/// Type converters for serializing and deserializing `u32`.
408
///
409
/// ## Available converters
410
/// - [`u32::AsF64`] — converts a `u32` to and from an `f64`.
411
/// - [`u32::AsI32`] — converts a `u32` to and from an `i32`.
412
/// - [`u32::AsI64`] — converts a `u32` to and from an `i64`.
413
pub mod u32 {
414
    use serde::{Deserialize, Deserializer, Serialize, Serializer};
415
416
    serde_conv_doc!(
417
        /// Converts a `u32` to and from an `f64`.
418
        ///
419
        /// Deserialization errors if an exact conversion is not possible.
420
        /// ```rust
421
        /// # #[cfg(feature = "serde_with-3")]
422
        /// # {
423
        /// use bson::serde_helpers::u32;
424
        /// use serde::{Serialize, Deserialize};
425
        /// use serde_with::serde_as;
426
        /// #[serde_as]
427
        /// #[derive(Serialize, Deserialize)]
428
        /// struct FileInfo {
429
        ///     #[serde_as(as = "u32::AsF64")]
430
        ///     pub size_bytes: u32,
431
        /// }
432
        /// # }
433
        /// ```
434
        pub AsF64,
435
        u32,
436
0
        |value: &u32| -> Result<f64, String> {
437
0
            Ok(f64::from(*value))
438
0
        },
439
0
        |value: f64| -> Result<u32, String> {
440
0
            if (value - value as u32 as f64).abs() <= f64::EPSILON {
441
0
                Ok(value as u32)
442
            } else {
443
0
                Err(format!("Cannot convert f64 {} to u32", value))
444
            }
445
0
        }
446
    );
447
448
    serde_conv_doc!(
449
        /// Converts a `u32` to and from an `i32`.
450
        ///
451
        /// Errors if an exact conversion is not possible.
452
        /// ```rust
453
        /// # #[cfg(feature = "serde_with-3")]
454
        /// # {
455
        /// use bson::{serde_helpers::u32};
456
        /// use serde::{Serialize, Deserialize};
457
        /// use serde_with::serde_as;
458
        /// #[serde_as]
459
        /// #[derive(Serialize, Deserialize)]
460
        /// struct Item {
461
        ///     #[serde_as(as = "u32::AsI32")]
462
        ///     pub value: u32,
463
        /// }
464
        /// # }
465
        /// ```
466
        pub AsI32,
467
        u32,
468
0
        |value: &u32| -> Result<i32, String> {
469
0
            i32::try_from(*value).map_err(|e| format!("Cannot convert u32 {} to i32: {}", value, e))
470
0
        },
471
0
        |value: i32| -> Result<u32, String> {
472
0
            u32::try_from(value).map_err(|e| format!("Cannot convert i32 {} to u32: {}", value, e))
473
0
        }
474
    );
475
476
    serde_conv_doc!(
477
        /// Converts a `u32` to and from an `i64`.
478
        ///
479
        /// Deserialization errors if an exact conversion is not possible.
480
        /// ```rust
481
        /// # #[cfg(feature = "serde_with-3")]
482
        /// # {
483
        /// use bson::{serde_helpers::u32};
484
        /// use serde::{Serialize, Deserialize};
485
        /// use serde_with::serde_as;
486
        /// #[serde_as]
487
        /// #[derive(Serialize, Deserialize)]
488
        /// struct Item {
489
        ///     #[serde_as(as = "u32::AsI64")]
490
        ///     pub value: u32,
491
        /// }
492
        /// # }
493
        /// ```
494
        pub AsI64,
495
        u32,
496
0
        |value: &u32| -> Result<i64, String> {
497
0
            Ok(i64::from(*value))
498
0
        },
499
0
        |value: i64| -> Result<u32, String> {
500
0
            u32::try_from(value).map_err(|e| format!("Cannot convert i64 {} to u32: {}", value, e))
501
0
        }
502
    );
503
}
504
505
/// Type converters for serializing and deserializing `u64`.
506
///
507
/// ## Available converters
508
/// - [`u64::AsF64`] — converts a `u64` to and from an `f64`.
509
/// - [`u64::AsI32`] — converts a `u64` to and from an `i32`.
510
/// - [`u64::AsI64`] — converts a `u64` to and from an `i64`.
511
pub mod u64 {
512
    use serde::{Deserialize, Deserializer, Serialize, Serializer};
513
514
    serde_conv_doc!(
515
        /// Converts a `u64` to and from an `f64`.
516
        ///
517
        /// Errors if an exact conversion is not possible.
518
        ///
519
        /// ```rust
520
        /// # #[cfg(feature = "serde_with-3")]
521
        /// # {
522
        /// use bson::serde_helpers::u64;
523
        /// use serde::{Serialize, Deserialize};
524
        /// use serde_with::serde_as;
525
        /// #[serde_as]
526
        /// #[derive(Serialize, Deserialize)]
527
        /// struct FileInfo {
528
        ///     #[serde_as(as = "u64::AsF64")]
529
        ///     pub size_bytes: u64,
530
        /// }
531
        /// # }
532
        /// ```
533
        pub AsF64,
534
        u64,
535
0
        |value: &u64| -> Result<f64, String> {
536
0
            if value < &u64::MAX && *value == *value as f64 as u64 {
537
0
                Ok(*value as f64)
538
            } else {
539
0
                Err(format!("Cannot convert u64 {} to f64", value))
540
            }
541
0
        },
542
0
        |value: f64| -> Result<u64, String> {
543
0
            if (value - value as u64 as f64).abs() <= f64::EPSILON {
544
0
               Ok(value as u64)
545
            } else {
546
0
                Err(format!("Cannot convert f64 {} to u64", value))
547
            }
548
0
        }
549
    );
550
551
    serde_conv_doc!(
552
        /// Converts a `u64` to and from an `i32`.
553
        ///
554
        /// Errors if an exact conversion is not possible.
555
        /// ```rust
556
        /// # #[cfg(feature = "serde_with-3")]
557
        /// # {
558
        /// use bson::{serde_helpers::u64};
559
        /// use serde::{Serialize, Deserialize};
560
        /// use serde_with::serde_as;
561
        /// #[serde_as]
562
        /// #[derive(Serialize, Deserialize)]
563
        /// struct Item {
564
        ///     #[serde_as(as = "u64::AsI32")]
565
        ///     pub value: u64,
566
        /// }
567
        /// # }
568
        /// ```
569
        pub AsI32,
570
        u64,
571
0
        |value: &u64| -> Result<i32, String> {
572
0
            i32::try_from(*value).map_err(|e| format!("Cannot convert u64 {} to i32: {}", value, e))
573
0
        },
574
0
        |value: i32| -> Result<u64, String> {
575
0
            u64::try_from(value).map_err(|e| format!("Cannot convert i32 {} to u64: {}", value, e))
576
0
        }
577
    );
578
579
    serde_conv_doc!(
580
        /// Converts a `u64` to and from an `i64`.
581
        ///
582
        /// Errors if an exact conversion is not possible.
583
        /// ```rust
584
        /// # #[cfg(feature = "serde_with-3")]
585
        /// # {
586
        /// use bson::{serde_helpers::u64};
587
        /// use serde::{Serialize, Deserialize};
588
        /// use serde_with::serde_as;
589
        /// #[serde_as]
590
        /// #[derive(Serialize, Deserialize)]
591
        /// struct Item {
592
        ///     #[serde_as(as = "u64::AsI64")]
593
        ///     pub value: u64,
594
        /// }
595
        /// # }
596
        /// ```
597
        pub AsI64,
598
        u64,
599
0
        |value: &u64| -> Result<i64, String> {
600
0
            i64::try_from(*value).map_err(|e| format!("Cannot convert u64 {} to i64: {}", value, e))
601
0
        },
602
0
        |value: i64| -> Result<u64, String> {
603
0
            u64::try_from(value).map_err(|e| format!("Cannot convert i64 {} to u64: {}", value, e))
604
0
        }
605
    );
606
}
607
608
/// Type converters for serializing and deserializing [`uuid::Uuid`].
609
///
610
/// ## Available converters
611
/// - [`uuid_1::FromBson`] - serializes a [`crate::Uuid`] as a [`uuid::Uuid`].
612
/// - [`uuid_1::AsBinary`] — serializes a [`uuid::Uuid`] as a [`crate::Binary`].
613
/// - [`uuid_1::AsCSharpLegacyBinary`] — serializes a [`uuid::Uuid`] as a [`crate::Binary`] in the
614
///   legacy C# driver UUID format.
615
/// - [`uuid_1::AsJavaLegacyBinary`] — serializes a [`uuid::Uuid`] as a [`crate::Binary`] in the
616
///   legacy Java driver UUID format.
617
/// - [`uuid_1::AsPythonLegacyBinary`] — serializes a [`uuid::Uuid`] as a [`crate::Binary`] in the
618
///   legacy Python driver UUID format.
619
#[cfg(feature = "uuid-1")]
620
pub mod uuid_1 {
621
    use serde::{Deserialize, Deserializer, Serialize, Serializer};
622
    use uuid::Uuid;
623
624
    serde_conv_doc!(
625
        /// Converts a [`crate::Uuid`] to and from a [`uuid::Uuid`].
626
        /// ```
627
        /// # #[cfg(all(feature = "uuid-1", feature = "serde_with-3"))]
628
        /// # {
629
        /// use bson::serde_helpers::uuid_1;
630
        /// use serde::{Serialize, Deserialize};
631
        /// use serde_with::serde_as;
632
        /// #[serde_as]
633
        /// #[derive(Serialize, Deserialize)]
634
        /// struct Item {
635
        ///     #[serde_as(as = "uuid_1::FromBson")]
636
        ///     pub id: bson::Uuid,
637
        /// }
638
        /// # }
639
        /// ```
640
        pub FromBson,
641
        crate::Uuid,
642
        |bson_uuid: &crate::Uuid| -> Result<Uuid, String> {
643
            Ok((*bson_uuid).into())
644
        },
645
        |uuid: Uuid| -> Result<crate::Uuid, String> {
646
            Ok(crate::Uuid::from(uuid))
647
        }
648
    );
649
650
    serde_conv_doc!(
651
        /// Serializes a [`Uuid`] as a [`crate::Binary`] and deserializes a [`Uuid`] from a [`crate::Binary`].
652
        /// ```rust
653
        /// # #[cfg(all(feature = "uuid-1", feature = "serde_with-3"))]
654
        /// # {
655
        /// use bson::serde_helpers::uuid_1;
656
        /// use serde::{Serialize, Deserialize};
657
        /// use serde_with::serde_as;
658
        /// use uuid::Uuid;
659
        /// #[serde_as]
660
        /// #[derive(Serialize, Deserialize)]
661
        /// struct Item {
662
        ///     #[serde_as(as = "uuid_1::AsBinary")]
663
        ///     pub id: Uuid,
664
        /// }
665
        /// # }
666
        /// ```
667
        pub AsBinary,
668
        Uuid,
669
        |uuid: &Uuid| -> Result<crate::uuid::Uuid, String> {
670
            Ok(crate::uuid::Uuid::from(*uuid))
671
        },
672
        |bson_uuid: crate::uuid::Uuid| -> Result<Uuid, String> {
673
            Ok(bson_uuid.into())
674
        }
675
    );
676
677
    serde_conv_doc!(
678
        /// Serializes a [`Uuid`] to a [`crate::Binary`] in the legacy C# driver UUID format and
679
        /// deserializes [`Uuid`] from a [`crate::Binary`] in the legacy C# driver format.
680
        /// ```rust
681
        /// # #[cfg(all(feature = "uuid-1", feature = "serde_with-3"))]
682
        /// # {
683
        /// use bson::serde_helpers::uuid_1;
684
        /// use serde::{Serialize, Deserialize};
685
        /// use serde_with::serde_as;
686
        /// use uuid::Uuid;
687
        /// #[serde_as]
688
        /// #[derive(Serialize, Deserialize)]
689
        /// struct Item {
690
        ///     #[serde_as(as = "uuid_1::AsCSharpLegacyBinary")]
691
        ///     pub id: Uuid,
692
        /// }
693
        /// # }
694
        /// ```
695
        pub AsCSharpLegacyBinary,
696
        Uuid,
697
        |uuid: &Uuid| -> Result<crate::Binary, String> {
698
            let inner = crate::uuid::Uuid::from(*uuid);
699
            Ok(crate::Binary::from_uuid_with_representation(
700
                inner,
701
                crate::uuid::UuidRepresentation::CSharpLegacy,
702
            ))
703
        },
704
        |binary: crate::Binary| -> Result<Uuid, String> {
705
            let inner = binary
706
                .to_uuid_with_representation(crate::uuid::UuidRepresentation::CSharpLegacy)
707
                .map_err(|e| e.to_string())?;
708
            Ok(inner.into())
709
        }
710
    );
711
712
    serde_conv_doc!(
713
        /// Serializes a [`Uuid`] to a [`crate::Binary`] in the legacy Java driver UUID format and
714
        /// deserializes [`Uuid`] from a [`crate::Binary`] in the legacy Java driver format.
715
        /// ```rust
716
        /// # #[cfg(all(feature = "uuid-1", feature = "serde_with-3"))]
717
        /// # {
718
        /// use bson::serde_helpers::uuid_1;
719
        /// use serde::{Serialize, Deserialize};
720
        /// use serde_with::serde_as;
721
        /// use uuid::Uuid;
722
        /// #[serde_as]
723
        /// #[derive(Serialize, Deserialize)]
724
        /// struct Item {
725
        ///     #[serde_as(as = "uuid_1::AsJavaLegacyBinary")]
726
        ///     pub id: Uuid,
727
        /// }
728
        /// # }
729
        /// ```
730
        pub AsJavaLegacyBinary,
731
        Uuid,
732
        |uuid: &Uuid| -> Result<crate::Binary, String> {
733
            let inner = crate::uuid::Uuid::from(*uuid);
734
            Ok(crate::Binary::from_uuid_with_representation(
735
                inner,
736
                crate::uuid::UuidRepresentation::JavaLegacy,
737
            ))
738
        },
739
        |binary: crate::Binary| -> Result<Uuid, String> {
740
            let inner = binary
741
                .to_uuid_with_representation(crate::uuid::UuidRepresentation::JavaLegacy)
742
                .map_err(|e| e.to_string())?;
743
            Ok(inner.into())
744
        }
745
    );
746
747
    serde_conv_doc!(
748
        /// Serializes a [`Uuid`] to a [`crate::Binary`] in the legacy Python driver UUID format and
749
        /// deserializes [`Uuid`] from a [`crate::Binary`] in the legacy Python driver format.
750
        /// ```rust
751
        /// # #[cfg(all(feature = "uuid-1", feature = "serde_with-3"))]
752
        /// # {
753
        /// use bson::serde_helpers::uuid_1;
754
        /// use serde::{Serialize, Deserialize};
755
        /// use serde_with::serde_as;
756
        /// use uuid::Uuid;
757
        /// #[serde_as]
758
        /// #[derive(Serialize, Deserialize)]
759
        /// struct Item {
760
        ///     #[serde_as(as = "uuid_1::AsPythonLegacyBinary")]
761
        ///     pub id: Uuid,
762
        /// }
763
        /// # }
764
        /// ```
765
        pub AsPythonLegacyBinary,
766
        Uuid,
767
        |uuid: &Uuid| -> Result<crate::Binary, String> {
768
            let inner = crate::uuid::Uuid::from(*uuid);
769
            Ok(crate::Binary::from_uuid_with_representation(
770
                inner,
771
                crate::uuid::UuidRepresentation::PythonLegacy,
772
            ))
773
        },
774
        |binary: crate::Binary| -> Result<Uuid, String> {
775
            let inner = binary
776
                .to_uuid_with_representation(crate::uuid::UuidRepresentation::PythonLegacy)
777
                .map_err(|e| e.to_string())?;
778
            Ok(inner.into())
779
        }
780
    );
781
}
782
783
/// Wrapping a type in `HumanReadable` signals to the BSON serde integration that it and all
784
/// recursively contained types should be serialized to and deserialized from their human-readable
785
/// formats.
786
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
787
#[repr(transparent)]
788
pub struct HumanReadable<T>(pub T);
789
790
pub(crate) const HUMAN_READABLE_NEWTYPE: &str = "$__bson_private_human_readable";
791
792
impl<T: Serialize> Serialize for HumanReadable<T> {
793
0
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
794
0
    where
795
0
        S: serde::Serializer,
796
    {
797
0
        serializer.serialize_newtype_struct(HUMAN_READABLE_NEWTYPE, &self.0)
798
0
    }
799
}
800
801
impl<'de, T: Deserialize<'de>> Deserialize<'de> for HumanReadable<T> {
802
0
    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
803
0
    where
804
0
        D: serde::Deserializer<'de>,
805
    {
806
        struct V<T>(PhantomData<fn() -> T>);
807
        impl<'de, T: Deserialize<'de>> Visitor<'de> for V<T> {
808
            type Value = HumanReadable<T>;
809
0
            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
810
0
                formatter.write_str("HumanReadable wrapper")
811
0
            }
812
0
            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
813
0
            where
814
0
                D: serde::Deserializer<'de>,
815
            {
816
0
                T::deserialize(deserializer).map(HumanReadable)
817
0
            }
818
        }
819
0
        deserializer.deserialize_newtype_struct(HUMAN_READABLE_NEWTYPE, V(PhantomData))
820
0
    }
821
}
822
823
impl<T: std::fmt::Display> std::fmt::Display for HumanReadable<T> {
824
0
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
825
0
        self.0.fmt(f)
826
0
    }
827
}
828
829
impl<T> From<T> for HumanReadable<T> {
830
0
    fn from(value: T) -> Self {
831
0
        Self(value)
832
0
    }
833
}
834
835
impl<T> Deref for HumanReadable<T> {
836
    type Target = T;
837
838
0
    fn deref(&self) -> &Self::Target {
839
0
        &self.0
840
0
    }
841
}
842
843
impl<T> DerefMut for HumanReadable<T> {
844
0
    fn deref_mut(&mut self) -> &mut Self::Target {
845
0
        &mut self.0
846
0
    }
847
}
848
849
impl<T, R> AsRef<R> for HumanReadable<T>
850
where
851
    R: ?Sized,
852
    <HumanReadable<T> as Deref>::Target: AsRef<R>,
853
{
854
0
    fn as_ref(&self) -> &R {
855
0
        self.deref().as_ref()
856
0
    }
857
}
858
859
impl<T, R: ?Sized> AsMut<R> for HumanReadable<T>
860
where
861
    <HumanReadable<T> as Deref>::Target: AsMut<R>,
862
{
863
0
    fn as_mut(&mut self) -> &mut R {
864
0
        self.deref_mut().as_mut()
865
0
    }
866
}