api_def.rs 2.11 KiB
Newer Older
Pierre Krieger's avatar
Pierre Krieger committed
//! Contains implementation of the `syn::parse::Parse` trait. Allows parsing the input tokens
//! stream in a structured way.
Pierre Krieger's avatar
Pierre Krieger committed

Pierre Krieger's avatar
Pierre Krieger committed
/// Multiple `ApiDefinition`s grouped into one struct.
///
/// Represents the entire content of the procedural macro.
Pierre Krieger's avatar
Pierre Krieger committed
#[derive(Debug)]
pub struct ApiDefinitions {
    pub apis: Vec<ApiDefinition>,
}

impl syn::parse::Parse for ApiDefinitions {
    fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
        let mut out = ApiDefinitions {
            apis: Vec::new(),
        };

        while !input.is_empty() {
            out.apis.push(input.parse()?);
        }

        Ok(out)
    }
}

Pierre Krieger's avatar
Pierre Krieger committed
/// A single API defined by the user.
Pierre Krieger's avatar
Pierre Krieger committed
#[derive(Debug)]
pub struct ApiDefinition {
Pierre Krieger's avatar
Pierre Krieger committed
    /// Name of the API. For example `System`.
Pierre Krieger's avatar
Pierre Krieger committed
    pub name: syn::Ident,
Pierre Krieger's avatar
Pierre Krieger committed
    /// List of RPC functions defined for this API.
Pierre Krieger's avatar
Pierre Krieger committed
    pub definitions: Vec<syn::Signature>,
}

impl syn::parse::Parse for ApiDefinition {
    fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
        let name = input.parse()?;
        let group: proc_macro2::Group = input.parse()?;
        assert_eq!(group.delimiter(), proc_macro2::Delimiter::Brace);
        let defs: ApiMethods = syn::parse2(group.stream())?;

        Ok(ApiDefinition {
            name,
            definitions: defs.definitions,
        })
    }
}

Pierre Krieger's avatar
Pierre Krieger committed
/// Implementation detail of `ApiDefinition`.
/// Parses one single block of function definitions.
Pierre Krieger's avatar
Pierre Krieger committed
#[derive(Debug)]
struct ApiMethods {
    definitions: Vec<syn::Signature>,
}

impl syn::parse::Parse for ApiMethods {
    fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
        let mut out = ApiMethods {
            definitions: Vec::new(),
        };

        while !input.is_empty() {
            let def: syn::TraitItemMethod = input.parse()?;
            if def.default.is_some() {
                panic!("It is forbidden to provide a default implementation for methods in the \
                        API definition: {:?}", def);
            }

            // TODO: do something with the function attributes?

            out.definitions.push(def.sig);
        }

        Ok(out)
    }
}