use std::borrow::{Borrow, Cow};
use crate::{
de::Result as DeResult, ser::Result as SerResult, Deserialize, DeserializerTrait, Serialize,
SerializerTrait, Symbol, Visitor,
};
#[repr(transparent)]
pub struct Sym(pub(crate) str);
impl Sym {
pub const fn new(str: &str) -> &Self {
unsafe { std::mem::transmute(str) }
}
pub const fn as_str(&self) -> &str {
&self.0
}
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn is_ivar(&self) -> bool {
self.0.starts_with('@')
}
pub fn to_ivar(&self) -> Cow<'_, Self> {
if self.is_ivar() {
Cow::Borrowed(self)
} else {
Cow::Owned(Symbol::new(format!("@{}", self.as_str())))
}
}
pub fn to_rust_field_name(&self) -> Option<&Self> {
self.0.strip_prefix('@').map(Self::new)
}
pub fn to_symbol(&self) -> Symbol {
self.to_owned()
}
pub const fn len(&self) -> usize {
self.0.len()
}
}
impl Borrow<str> for Sym {
fn borrow(&self) -> &str {
&self.0
}
}
impl AsRef<str> for Sym {
fn as_ref(&self) -> &str {
&self.0
}
}
impl AsRef<[u8]> for Sym {
fn as_ref(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl ToOwned for Sym {
type Owned = Symbol;
fn to_owned(&self) -> Self::Owned {
Symbol(self.0.to_string())
}
}
impl Default for &Sym {
fn default() -> Self {
Sym::new("")
}
}
impl std::fmt::Display for Sym {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(":{}", &self.0))
}
}
impl std::fmt::Debug for Sym {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Sym").field(&&self.0).finish()
}
}
impl std::hash::Hash for Sym {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<'a> From<&'a str> for &'a Sym {
fn from(value: &'a str) -> Self {
Sym::new(value)
}
}
impl<'a> From<&'a Sym> for &'a str {
fn from(value: &'a Sym) -> Self {
&value.0
}
}
impl PartialEq<str> for Sym {
fn eq(&self, other: &str) -> bool {
self.0.eq(other)
}
}
impl PartialEq<String> for Sym {
fn eq(&self, other: &String) -> bool {
self.0.eq(other)
}
}
impl PartialEq<Symbol> for Sym {
fn eq(&self, other: &Symbol) -> bool {
self.0.eq(&other.0)
}
}
impl PartialEq<Sym> for Sym {
fn eq(&self, other: &Sym) -> bool {
self.0.eq(&other.0)
}
}
impl Eq for Sym {}
struct SymVisitor;
impl<'de> Visitor<'de> for SymVisitor {
type Value = &'de Sym;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("a symbol")
}
fn visit_symbol(self, symbol: &'de Sym) -> DeResult<Self::Value> {
Ok(symbol)
}
}
impl<'de> Deserialize<'de> for &'de Sym {
fn deserialize<D>(deserializer: D) -> DeResult<Self>
where
D: DeserializerTrait<'de>,
{
deserializer.deserialize(SymVisitor)
}
}
impl Serialize for Sym {
fn serialize<S>(&self, serializer: S) -> SerResult<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_symbol(self)
}
}