graphrecords-macros 0.5.0

High-performance graph-based data records
Documentation
use crate::{attribute::FromAttributes, query::resolve_query_crate_path};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{DeriveInput, Generics, Ident, LitStr, Path, Result, meta::ParseNestedMeta};

#[derive(Default)]
struct PhaseLabelAttributes {
    crate_path: Option<Path>,
}

impl FromAttributes for PhaseLabelAttributes {
    const NAMESPACE: &'static str = "phase_label";

    fn parse_meta(&mut self, meta: ParseNestedMeta) -> Result<()> {
        if meta.path.is_ident("crate") {
            self.crate_path = Some(meta.value()?.parse::<LitStr>()?.parse()?);
            Ok(())
        } else {
            Err(meta.error("unknown phase_label attribute"))
        }
    }
}

struct PhaseLabelModel {
    ident: Ident,
    generics: Generics,
    crate_path: Path,
}

impl PhaseLabelModel {
    fn parse(input: &DeriveInput) -> Result<Self> {
        let crate_path = match PhaseLabelAttributes::from_attributes(&input.attrs)?.crate_path {
            Some(path) => path,
            None => resolve_query_crate_path()?,
        };

        Ok(Self {
            ident: input.ident.clone(),
            generics: input.generics.clone(),
            crate_path,
        })
    }
}

pub fn expand(input: &DeriveInput) -> Result<TokenStream> {
    let PhaseLabelModel {
        ident,
        generics,
        crate_path,
    } = PhaseLabelModel::parse(input)?;

    let (impl_generics, type_generics, where_clause) = generics.split_for_impl();

    Ok(quote! {
        #[automatically_derived]
        impl #impl_generics #crate_path::optimizer::PhaseLabel for #ident #type_generics #where_clause {
            fn dyn_eq(&self, other: &dyn #crate_path::optimizer::PhaseLabel) -> bool {
                match #crate_path::optimizer::PhaseLabel::as_any(other).downcast_ref::<Self>() {
                    ::core::option::Option::Some(other) => self == other,
                    ::core::option::Option::None => false,
                }
            }

            fn dyn_hash(&self, mut state: &mut dyn ::core::hash::Hasher) {
                ::core::hash::Hash::hash(&::core::any::TypeId::of::<Self>(), &mut state);
                ::core::hash::Hash::hash(self, &mut state);
            }

            fn dyn_debug(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, formatter)
            }

            fn as_any(&self) -> &dyn ::core::any::Any {
                self
            }
        }
    })
}