1 | use crate::BlockContents; |
2 | use proc_macro2::Span; |
3 | use quote::ToTokens; |
4 | |
5 | /// A `DefaultExpression` can be either explicit or refer to the canonical trait. |
6 | #[derive (Debug, Clone)] |
7 | pub enum DefaultExpression { |
8 | Explicit(BlockContents), |
9 | Trait, |
10 | } |
11 | |
12 | impl DefaultExpression { |
13 | /// Add the crate root path so the default expression can be emitted |
14 | /// to a `TokenStream`. |
15 | /// |
16 | /// This function is needed because the crate root is inherited from the container, so it cannot |
17 | /// be provided at parse time to [`darling::FromMeta::from_word`] when reading, and [`ToTokens`] does not |
18 | /// accept any additional parameters, so it annot be provided at emit time. |
19 | pub fn with_crate_root<'a>(&'a self, crate_root: &'a syn::Path) -> impl 'a + ToTokens { |
20 | DefaultExpressionWithCrateRoot { |
21 | crate_root, |
22 | expr: self, |
23 | } |
24 | } |
25 | |
26 | #[cfg (test)] |
27 | pub fn explicit<I: Into<BlockContents>>(content: I) -> Self { |
28 | DefaultExpression::Explicit(content.into()) |
29 | } |
30 | } |
31 | |
32 | impl darling::FromMeta for DefaultExpression { |
33 | fn from_word() -> darling::Result<Self> { |
34 | Ok(DefaultExpression::Trait) |
35 | } |
36 | |
37 | fn from_value(value: &syn::Lit) -> darling::Result<Self> { |
38 | Ok(Self::Explicit(BlockContents::from_value(value)?)) |
39 | } |
40 | } |
41 | |
42 | impl syn::spanned::Spanned for DefaultExpression { |
43 | fn span(&self) -> Span { |
44 | match self { |
45 | DefaultExpression::Explicit(block: &BlockContents) => block.span(), |
46 | DefaultExpression::Trait => Span::call_site(), |
47 | } |
48 | } |
49 | } |
50 | |
51 | /// Wrapper for `DefaultExpression` |
52 | struct DefaultExpressionWithCrateRoot<'a> { |
53 | crate_root: &'a syn::Path, |
54 | expr: &'a DefaultExpression, |
55 | } |
56 | |
57 | impl<'a> ToTokens for DefaultExpressionWithCrateRoot<'a> { |
58 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { |
59 | let crate_root: &Path = self.crate_root; |
60 | match self.expr { |
61 | DefaultExpression::Explicit(ref block: &BlockContents) => block.to_tokens(tokens), |
62 | DefaultExpression::Trait => quoteTokenStream!( |
63 | #crate_root::export::core::default::Default::default() |
64 | ) |
65 | .to_tokens(tokens), |
66 | } |
67 | } |
68 | } |
69 | |