Skip to content

Commit 8755bfb

Browse files
authored
RUST-2215 Ergonomics for HumanReadable (#540)
1 parent fe28445 commit 8755bfb

File tree

1 file changed

+58
-2
lines changed

1 file changed

+58
-2
lines changed

src/serde_helpers.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Collection of helper functions for serializing to and deserializing from BSON using Serde
22
3-
use std::{convert::TryFrom, marker::PhantomData, result::Result};
3+
use std::{
4+
convert::TryFrom,
5+
marker::PhantomData,
6+
ops::{Deref, DerefMut},
7+
result::Result,
8+
};
49

510
use serde::{de::Visitor, ser, Deserialize, Serialize, Serializer};
611

@@ -718,7 +723,8 @@ pub mod timestamp_as_u32 {
718723
/// Wrapping a type in `HumanReadable` signals to the BSON serde integration that it and all
719724
/// recursively contained types should be serialized to and deserialized from their human-readable
720725
/// formats.
721-
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
726+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
727+
#[repr(transparent)]
722728
pub struct HumanReadable<T>(pub T);
723729

724730
pub(crate) const HUMAN_READABLE_NEWTYPE: &str = "$__bson_private_human_readable";
@@ -754,6 +760,56 @@ impl<'de, T: Deserialize<'de>> Deserialize<'de> for HumanReadable<T> {
754760
}
755761
}
756762

763+
impl<T: std::fmt::Display> std::fmt::Display for HumanReadable<T> {
764+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
765+
self.0.fmt(f)
766+
}
767+
}
768+
769+
impl<T> From<T> for HumanReadable<T> {
770+
fn from(value: T) -> Self {
771+
Self(value)
772+
}
773+
}
774+
775+
impl<T> Deref for HumanReadable<T> {
776+
type Target = T;
777+
778+
fn deref(&self) -> &Self::Target {
779+
&self.0
780+
}
781+
}
782+
783+
impl<T> DerefMut for HumanReadable<T> {
784+
fn deref_mut(&mut self) -> &mut Self::Target {
785+
&mut self.0
786+
}
787+
}
788+
789+
impl<T, R> AsRef<R> for HumanReadable<T>
790+
where
791+
R: ?Sized,
792+
<HumanReadable<T> as Deref>::Target: AsRef<R>,
793+
{
794+
fn as_ref(&self) -> &R {
795+
self.deref().as_ref()
796+
}
797+
}
798+
799+
impl<T, R: ?Sized> AsMut<R> for HumanReadable<T>
800+
where
801+
<HumanReadable<T> as Deref>::Target: AsMut<R>,
802+
{
803+
fn as_mut(&mut self) -> &mut R {
804+
self.deref_mut().as_mut()
805+
}
806+
}
807+
808+
// One could imagine passthrough Borrow impls; however, it turns out that can't be made to work
809+
// because of the existing base library impl of Borrow<T> for T will conflict despite that not
810+
// actually being possible to construct (https://github.com/rust-lang/rust/issues/50237). So,
811+
// sadly, Borrow impls for HumanReadable are deliberately omitted :(
812+
757813
/// Wrapper type for deserializing BSON bytes with invalid UTF-8 sequences.
758814
///
759815
/// Any invalid UTF-8 strings contained in the wrapped type will be replaced with the Unicode

0 commit comments

Comments
 (0)