use std::borrow::Borrow; use std::str::FromStr; /// Opaque string storage internal to `toml_edit` #[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct InternalString(Inner); #[cfg(feature = "kstring")] type Inner = kstring::KString; #[cfg(not(feature = "kstring"))] type Inner = String; impl InternalString { /// Create an empty string pub fn new() -> Self { InternalString(Inner::new()) } /// Access the underlying string #[inline] pub fn as_str(&self) -> &str { self.0.as_str() } } impl std::fmt::Debug for InternalString { #[inline] fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { self.0.fmt(formatter) } } impl std::ops::Deref for InternalString { type Target = str; #[inline] fn deref(&self) -> &str { self.as_str() } } impl Borrow for InternalString { #[inline] fn borrow(&self) -> &str { self.as_str() } } impl AsRef for InternalString { #[inline] fn as_ref(&self) -> &str { self.as_str() } } impl From<&str> for InternalString { #[inline] fn from(s: &str) -> Self { #[cfg(feature = "kstring")] let inner = kstring::KString::from_ref(s); #[cfg(not(feature = "kstring"))] let inner = String::from(s); InternalString(inner) } } impl From for InternalString { #[inline] fn from(s: String) -> Self { #[allow(clippy::useless_conversion)] // handle any string type InternalString(s.into()) } } impl From<&String> for InternalString { #[inline] fn from(s: &String) -> Self { InternalString(s.into()) } } impl From<&InternalString> for InternalString { #[inline] fn from(s: &InternalString) -> Self { s.clone() } } impl From> for InternalString { #[inline] fn from(s: Box) -> Self { InternalString(s.into()) } } impl FromStr for InternalString { type Err = core::convert::Infallible; #[inline] fn from_str(s: &str) -> Result { Ok(Self::from(s)) } } impl std::fmt::Display for InternalString { #[inline] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.as_str().fmt(f) } } #[cfg(feature = "serde")] impl serde::Serialize for InternalString { #[inline] fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_str(self.as_str()) } } #[cfg(feature = "serde")] impl<'de> serde::Deserialize<'de> for InternalString { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_string(StringVisitor) } } #[cfg(feature = "serde")] struct StringVisitor; #[cfg(feature = "serde")] impl<'de> serde::de::Visitor<'de> for StringVisitor { type Value = InternalString; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { formatter.write_str("a string") } fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { Ok(InternalString::from(v)) } fn visit_string(self, v: String) -> Result where E: serde::de::Error, { Ok(InternalString::from(v)) } fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error, { match std::str::from_utf8(v) { Ok(s) => Ok(InternalString::from(s)), Err(_) => Err(serde::de::Error::invalid_value( serde::de::Unexpected::Bytes(v), &self, )), } } fn visit_byte_buf(self, v: Vec) -> Result where E: serde::de::Error, { match String::from_utf8(v) { Ok(s) => Ok(InternalString::from(s)), Err(e) => Err(serde::de::Error::invalid_value( serde::de::Unexpected::Bytes(&e.into_bytes()), &self, )), } } }