| 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 | pub fn span(&self) -> Span { |
| 27 | match self { |
| 28 | DefaultExpression::Explicit(block) => block.span(), |
| 29 | DefaultExpression::Trait => Span::call_site(), |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | #[cfg (test)] |
| 34 | pub fn explicit<I: Into<BlockContents>>(content: I) -> Self { |
| 35 | DefaultExpression::Explicit(content.into()) |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | impl darling::FromMeta for DefaultExpression { |
| 40 | fn from_word() -> darling::Result<Self> { |
| 41 | Ok(DefaultExpression::Trait) |
| 42 | } |
| 43 | |
| 44 | fn from_expr(expr: &syn::Expr) -> darling::Result<Self> { |
| 45 | if let syn::Expr::Lit(el: &ExprLit) = expr { |
| 46 | if let syn::Lit::Str(_) = el.lit { |
| 47 | return Self::from_value(&el.lit); |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | Ok(Self::Explicit(expr.clone().into())) |
| 52 | } |
| 53 | |
| 54 | fn from_value(value: &syn::Lit) -> darling::Result<Self> { |
| 55 | Ok(Self::Explicit(BlockContents::from_value(value)?)) |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | /// Wrapper for `DefaultExpression` |
| 60 | struct DefaultExpressionWithCrateRoot<'a> { |
| 61 | crate_root: &'a syn::Path, |
| 62 | expr: &'a DefaultExpression, |
| 63 | } |
| 64 | |
| 65 | impl<'a> ToTokens for DefaultExpressionWithCrateRoot<'a> { |
| 66 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { |
| 67 | let crate_root: &'a Path = self.crate_root; |
| 68 | match self.expr { |
| 69 | DefaultExpression::Explicit(ref block: &BlockContents) => block.to_tokens(tokens), |
| 70 | DefaultExpression::Trait => quoteTokenStream!( |
| 71 | #crate_root::export::core::default::Default::default() |
| 72 | ) |
| 73 | .to_tokens(tokens), |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | |