sqlx_core/ext/
ustr.rs

1use std::borrow::Borrow;
2use std::fmt::{self, Debug, Display, Formatter};
3use std::hash::{Hash, Hasher};
4use std::ops::Deref;
5use std::sync::Arc;
6
7// U meaning micro
8// a micro-string is either a reference-counted string or a static string
9// this guarantees these are cheap to clone everywhere
10#[derive(Clone, Eq)]
11pub enum UStr {
12    Static(&'static str),
13    Shared(Arc<str>),
14}
15
16impl UStr {
17    pub fn new(s: &str) -> Self {
18        UStr::Shared(Arc::from(s.to_owned()))
19    }
20
21    /// Apply [str::strip_prefix], without copying if possible.
22    pub fn strip_prefix(this: &Self, prefix: &str) -> Option<Self> {
23        match this {
24            UStr::Static(s) => s.strip_prefix(prefix).map(Self::Static),
25            UStr::Shared(s) => s.strip_prefix(prefix).map(|s| Self::Shared(s.into())),
26        }
27    }
28}
29
30impl Deref for UStr {
31    type Target = str;
32
33    #[inline]
34    fn deref(&self) -> &str {
35        match self {
36            UStr::Static(s) => s,
37            UStr::Shared(s) => s,
38        }
39    }
40}
41
42impl Hash for UStr {
43    #[inline]
44    fn hash<H: Hasher>(&self, state: &mut H) {
45        // Forward the hash to the string representation of this
46        // A derive(Hash) encodes the enum discriminant
47        (**self).hash(state);
48    }
49}
50
51impl Borrow<str> for UStr {
52    #[inline]
53    fn borrow(&self) -> &str {
54        self
55    }
56}
57
58impl PartialEq<UStr> for UStr {
59    fn eq(&self, other: &UStr) -> bool {
60        (**self).eq(&**other)
61    }
62}
63
64impl From<&'static str> for UStr {
65    #[inline]
66    fn from(s: &'static str) -> Self {
67        UStr::Static(s)
68    }
69}
70
71impl<'a> From<&'a UStr> for UStr {
72    fn from(value: &'a UStr) -> Self {
73        value.clone()
74    }
75}
76
77impl From<String> for UStr {
78    #[inline]
79    fn from(s: String) -> Self {
80        UStr::Shared(s.into())
81    }
82}
83
84impl Debug for UStr {
85    #[inline]
86    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
87        f.pad(self)
88    }
89}
90
91impl Display for UStr {
92    #[inline]
93    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
94        f.pad(self)
95    }
96}
97
98// manual impls because otherwise things get a little screwy with lifetimes
99
100#[cfg(feature = "offline")]
101impl<'de> serde::Deserialize<'de> for UStr {
102    fn deserialize<D>(deserializer: D) -> Result<Self, <D as serde::Deserializer<'de>>::Error>
103    where
104        D: serde::Deserializer<'de>,
105    {
106        Ok(String::deserialize(deserializer)?.into())
107    }
108}
109
110#[cfg(feature = "offline")]
111impl serde::Serialize for UStr {
112    fn serialize<S>(
113        &self,
114        serializer: S,
115    ) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>
116    where
117        S: serde::Serializer,
118    {
119        serializer.serialize_str(self)
120    }
121}