/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 | | } |