graphrecords-macros 0.5.0

High-performance graph-based data records
Documentation
use super::PlanModel;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{DeriveInput, Result};

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

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

    let payload_eq = payload.clone();
    let payload_hash = payload;

    Ok(quote! {
        #[automatically_derived]
        impl #impl_generics #crate_path::optimizer::PlanNode for #ident #type_generics #where_clause {
            fn inputs(&self) -> ::std::vec::Vec<&dyn #crate_path::optimizer::PlanNode> {
                let mut inputs: ::std::vec::Vec<&dyn #crate_path::optimizer::PlanNode> =
                    ::std::vec::Vec::new();
                #( inputs.push(#crate_path::Operand::context(&self.#inputs)); )*
                inputs
            }

            fn dyn_eq(&self, other: &dyn #crate_path::optimizer::PlanNode) -> bool {
                let ::core::option::Option::Some(other) = other.downcast::<Self>() else {
                    return false;
                };

                #(
                    if self.#payload_eq != other.#payload_eq {
                        return false;
                    }
                )*

                #crate_path::optimizer::PlanNode::inputs(self)
                    .into_iter()
                    .zip(#crate_path::optimizer::PlanNode::inputs(other))
                    .all(|(self_input, other_input)| {
                        #crate_path::optimizer::PlanNode::dyn_eq(self_input, other_input)
                    })
            }

            fn dyn_hash(&self, mut state: &mut dyn ::core::hash::Hasher) {
                ::core::hash::Hash::hash(&::core::any::Any::type_id(self), &mut state);
                #( ::core::hash::Hash::hash(&self.#payload_hash, &mut state); )*

                for input in #crate_path::optimizer::PlanNode::inputs(self) {
                    #crate_path::optimizer::PlanNode::dyn_hash(input, state);
                }
            }
        }
    })
}