azure_functions_shared_codegen/
lib.rs

1//! # Azure Functions for Rust
2//!
3//! This crate supports code generation for the `azure-functions-shared` crate.
4#![deny(unused_extern_crates)]
5#![recursion_limit = "128"]
6#![cfg_attr(feature = "unstable", feature(proc_macro_diagnostic))]
7extern crate proc_macro;
8
9mod binding;
10
11use binding::binding_impl;
12use proc_macro2::{Delimiter, Span};
13use syn::{
14    buffer::TokenBuffer, spanned::Spanned, Attribute, AttributeArgs, Ident, Lit, Meta, NestedMeta,
15    Path, PathSegment,
16};
17
18fn last_segment_in_path(path: &Path) -> &PathSegment {
19    path.segments
20        .iter()
21        .last()
22        .expect("expected at least one segment in path")
23}
24
25fn parse_attribute_args(attr: &Attribute) -> AttributeArgs {
26    let span = attr.span();
27    let stream: proc_macro::TokenStream = match TokenBuffer::new2(attr.tokens.clone())
28        .begin()
29        .group(Delimiter::Parenthesis)
30    {
31        Some((tree, _, _)) => tree.token_stream().into(),
32        None => macro_panic(span, "failed to parse attribute"),
33    };
34
35    syn::parse_macro_input::parse::<AttributeArgs>(stream)
36        .map_err(move |e| macro_panic(span, format!("failed to parse attribute arguments: {}", e)))
37        .unwrap()
38}
39
40fn iter_attribute_args<F>(args: &[NestedMeta], mut callback: F)
41where
42    F: FnMut(&Ident, &Lit) -> bool,
43{
44    for arg in args {
45        match arg {
46            NestedMeta::Meta(m) => {
47                match m {
48                    Meta::NameValue(nvp) => {
49                        if !callback(&last_segment_in_path(&nvp.path).ident, &nvp.lit) {
50                            return;
51                        }
52                    }
53                    _ => macro_panic(m.span(), "expected name-value pair for an argument"),
54                };
55            }
56            _ => macro_panic(arg.span(), "expected a name-vaule pair for an argument"),
57        };
58    }
59}
60
61#[cfg(feature = "unstable")]
62fn macro_panic<T>(span: Span, message: T) -> !
63where
64    T: AsRef<str>,
65{
66    span.unstable().error(message.as_ref()).emit();
67    panic!("aborting due to previous error");
68}
69
70#[cfg(not(feature = "unstable"))]
71fn macro_panic<T>(_: Span, message: T) -> !
72where
73    T: AsRef<str>,
74{
75    panic!("{}", message.as_ref());
76}
77
78#[proc_macro_attribute]
79pub fn binding(
80    args: proc_macro::TokenStream,
81    input: proc_macro::TokenStream,
82) -> proc_macro::TokenStream {
83    binding_impl(args, input)
84}