obce_codegen/
id.rs

1use itertools::Itertools;
2use proc_macro2::TokenStream;
3use quote::quote;
4use syn::{
5    Error,
6    Path,
7};
8
9use crate::{
10    format_err_spanned,
11    utils::into_u32,
12};
13
14pub fn generate(input: TokenStream) -> Result<TokenStream, Error> {
15    let path: Path = syn::parse2(input)?;
16
17    match path.segments.len() {
18        1 => {
19            let extension = path.segments.first().unwrap();
20
21            Ok(quote! {
22                <dyn #extension as ::obce::codegen::ExtensionDescription>::ID
23            })
24        }
25        2 => {
26            let (extension, method) = path.segments.iter().tuple_windows().next().unwrap();
27
28            let method_hash = into_u32(&method.ident);
29
30            Ok(quote! {
31                <dyn #extension as ::obce::codegen::MethodDescription<#method_hash>>::ID
32            })
33        }
34        // Support only two-segment paths to correctly identify
35        // whether a user wants to get an identifier of a chain extension
36        // or a chain extension method itself.
37        _ => {
38            return Err(format_err_spanned!(
39                path,
40                "id macro supports only two-segment paths (ChainExtension, ChainExtension::method)"
41            ))
42        }
43    }
44}