1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use proc_macro2::{Ident, Span};
use syn::{Lit, LitStr};

/// Convert any literal path into a [syn::Path].
macro_rules! path {
	(:: $($segment:ident)::*) => {
		path!(@private Some(Default::default()), $($segment),*)
	};
	($($segment:ident)::*) => {
		path!(@private None, $($segment),*)
	};
	(@private $leading_colon:expr, $($segment:ident),*) => {
		{
			#[allow(unused_mut)]
			let mut segments: ::syn::punctuated::Punctuated<::syn::PathSegment, _> = Default::default();
			$(
				segments.push(::syn::PathSegment {
					ident: ::proc_macro2::Ident::new(stringify!($segment), ::proc_macro2::Span::call_site()),
					arguments: Default::default()
				});
			)*
			::syn::Path {
				leading_colon: $leading_colon,
				segments
			}
		}
	};
}

/// Convert [Ident], [String] and [&str] into a [LitStr].
pub(super) trait ToLitStr {
	fn to_lit_str(&self) -> LitStr;
}

impl ToLitStr for Ident {
	fn to_lit_str(&self) -> LitStr {
		LitStr::new(&self.to_string(), self.span())
	}
}

impl ToLitStr for String {
	fn to_lit_str(&self) -> LitStr {
		LitStr::new(self, Span::call_site())
	}
}

impl ToLitStr for &str {
	fn to_lit_str(&self) -> LitStr {
		LitStr::new(self, Span::call_site())
	}
}

/// Convert a [Lit] to one specific literal type.
pub(crate) trait ExpectLit {
	fn expect_str(self) -> syn::Result<LitStr>;
}

impl ExpectLit for Lit {
	fn expect_str(self) -> syn::Result<LitStr> {
		match self {
			Self::Str(str) => Ok(str),
			_ => Err(syn::Error::new(self.span(), "Expected string literal"))
		}
	}
}