1use std::ops::{Deref, DerefMut};
2
3#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
18#[repr(transparent)]
19pub struct Utf8Lossy<T>(pub T);
20
21impl<T: std::fmt::Display> std::fmt::Display for Utf8Lossy<T> {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 self.0.fmt(f)
24 }
25}
26
27impl<T> From<T> for Utf8Lossy<T> {
28 fn from(value: T) -> Self {
29 Self(value)
30 }
31}
32
33impl<T> Deref for Utf8Lossy<T> {
34 type Target = T;
35
36 fn deref(&self) -> &Self::Target {
37 &self.0
38 }
39}
40
41impl<T> DerefMut for Utf8Lossy<T> {
42 fn deref_mut(&mut self) -> &mut Self::Target {
43 &mut self.0
44 }
45}
46
47impl<T, R> AsRef<R> for Utf8Lossy<T>
48where
49 R: ?Sized,
50 <Utf8Lossy<T> as Deref>::Target: AsRef<R>,
51{
52 fn as_ref(&self) -> &R {
53 self.deref().as_ref()
54 }
55}
56
57impl<T, R: ?Sized> AsMut<R> for Utf8Lossy<T>
58where
59 <Utf8Lossy<T> as Deref>::Target: AsMut<R>,
60{
61 fn as_mut(&mut self) -> &mut R {
62 self.deref_mut().as_mut()
63 }
64}
65
66#[cfg(feature = "serde")]
67pub(crate) const UTF8_LOSSY_NEWTYPE: &str = "$__bson_private_utf8_lossy";
68
69#[cfg(feature = "serde")]
70impl<T: serde::Serialize> serde::Serialize for Utf8Lossy<T> {
71 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72 where
73 S: serde::Serializer,
74 {
75 self.0.serialize(serializer)
76 }
77}
78
79#[cfg(feature = "serde")]
80impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for Utf8Lossy<T> {
81 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82 where
83 D: serde::Deserializer<'de>,
84 {
85 struct V<T>(std::marker::PhantomData<fn() -> T>);
86 impl<'de, T: serde::Deserialize<'de>> serde::de::Visitor<'de> for V<T> {
87 type Value = Utf8Lossy<T>;
88 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
89 formatter.write_str("Utf8Lossy wrapper")
90 }
91 fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
92 where
93 D: serde::Deserializer<'de>,
94 {
95 T::deserialize(deserializer).map(Utf8Lossy)
96 }
97 }
98 deserializer.deserialize_newtype_struct(UTF8_LOSSY_NEWTYPE, V(std::marker::PhantomData))
99 }
100}