diplomat_core/ast/
idents.rs

1use proc_macro2::Span;
2use quote::{ToTokens, TokenStreamExt};
3use serde::{Deserialize, Serialize};
4use std::borrow::{Borrow, Cow};
5use std::fmt;
6
7/// An identifier, analogous to `syn::Ident` and `proc_macro2::Ident`.
8#[derive(Hash, Eq, PartialEq, Serialize, Clone, Debug, Ord, PartialOrd)]
9#[serde(transparent)]
10pub struct Ident(Cow<'static, str>);
11
12impl Ident {
13    /// Validate a string
14    fn validate(string: &str) -> syn::Result<()> {
15        syn::parse_str::<syn::Ident>(string).map(|_| {})
16    }
17
18    /// Attempt to create a new `Ident`.
19    ///
20    /// This function fails if the input isn't valid according to
21    /// `proc_macro2::Ident`'s invariants.
22    pub fn try_new(string: String) -> syn::Result<Self> {
23        Self::validate(&string).map(|_| Self(Cow::from(string)))
24    }
25
26    pub fn to_syn(&self) -> syn::Ident {
27        syn::Ident::new(self.as_str(), Span::call_site())
28    }
29
30    /// Get the `&str` representation.
31    pub fn as_str(&self) -> &str {
32        &self.0
33    }
34
35    /// An [`Ident`] containing "this".
36    pub const THIS: Self = Ident(Cow::Borrowed("this"));
37}
38
39impl From<&'static str> for Ident {
40    fn from(string: &'static str) -> Self {
41        Self::validate(string).unwrap();
42        Self(Cow::from(string))
43    }
44}
45
46impl From<String> for Ident {
47    fn from(string: String) -> Self {
48        Self::validate(&string).unwrap();
49        Self(Cow::from(string))
50    }
51}
52
53impl<'de> Deserialize<'de> for Ident {
54    /// The derived `Deserialize` allows for creating `Ident`s that do not uphold
55    /// the proper invariants. This custom impl ensures that this cannot happen.
56    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57    where
58        D: serde::Deserializer<'de>,
59    {
60        Ok(Ident::from(String::deserialize(deserializer)?))
61    }
62}
63
64impl Borrow<str> for Ident {
65    fn borrow(&self) -> &str {
66        self.as_str()
67    }
68}
69
70impl fmt::Display for Ident {
71    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72        self.as_str().fmt(f)
73    }
74}
75
76impl From<&syn::Ident> for Ident {
77    fn from(ident: &syn::Ident) -> Self {
78        Self(Cow::from(ident.to_string()))
79    }
80}
81
82impl ToTokens for Ident {
83    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
84        tokens.append(self.to_syn());
85    }
86}