nongoose-derive 0.1.0-beta.1

Macros implementation of #[derive(Schema)]
Documentation
use proc_macro2::TokenStream;
use quote::{format_ident, quote};

use crate::schema::data::SchemaData;

pub(crate) fn getter(schema_data: &SchemaData) -> TokenStream {
  let nongoose = crate::utils::crates::get_nongoose_crate_name();

  if !schema_data.relations.is_empty() {
    let mut static_relations = quote!();
    let mut get_relations = quote!();
    let mut set_relations = quote!();

    for (field_ident, relation_type, schema_ident) in schema_data.relations.iter() {
      let field_ident_name = format!("{}", quote!(#field_ident));
      let field_id_ident = format_ident!("{}_id", field_ident_name);

      let schema_ident_name = schema_ident.value().to_string();
      let schema_ident = format_ident!("{}", schema_ident_name);

      static_relations.extend(quote! {
        #nongoose::types::SchemaRelation {
          field_ident: #field_ident_name.to_string(),
          field_value: #nongoose::bson::Bson::Null,

          relation_type: #nongoose::types::SchemaRelationType::parse_str(#relation_type).unwrap(),

          schema_ident: #schema_ident_name.to_string(),
          schema_name: <#schema_ident>::__get_collection_name(),
        },
      });

      if relation_type == "one_to_one" || relation_type == "many_to_one" {
        get_relations.extend(quote! {
          #nongoose::types::SchemaRelation {
            field_ident: #field_ident_name.to_string(),
            field_value: if let Some(field_data) = self.#field_ident.clone() {
              field_data.__get_id().into()
            } else {
              self.#field_id_ident.clone().into()
            },

            relation_type: #nongoose::types::SchemaRelationType::parse_str(#relation_type).unwrap(),

            schema_ident: #schema_ident_name.to_string(),
            schema_name: <#schema_ident>::__get_collection_name(),
          },
        });
      } else if relation_type == "one_to_many" {
        get_relations.extend(quote! {
          #nongoose::types::SchemaRelation {
            field_ident: #field_ident_name.to_string(),
            field_value: self.#field_ident.clone().into(),

            relation_type: #nongoose::types::SchemaRelationType::parse_str(#relation_type).unwrap(),

            schema_ident: #schema_ident_name.to_string(),
            schema_name: <#schema_ident>::__get_collection_name(),
          },
        });
      }

      if !set_relations.is_empty() {
        set_relations.extend(quote!(else));
      }

      set_relations.extend(quote! {
        if field == #field_ident_name {
          self.#field_ident = #nongoose::bson::from_bson(new_value)?;
          return Ok(());
        }
      });
    }

    if !static_relations.is_empty() && !get_relations.is_empty() && !set_relations.is_empty() {
      return quote! {
        fn __relations() -> Vec<#nongoose::types::SchemaRelation> {
          vec![#static_relations]
        }

        fn __get_relations(&self) -> Option<Vec<#nongoose::types::SchemaRelation>> {
          let relations = vec![#get_relations];
          if !relations.is_empty() {
            Some(relations)
          } else {
            None
          }
        }

        fn __set_relations(&mut self, field: &str, new_value: #nongoose::bson::Bson) -> #nongoose::Result<()> {
          #set_relations
          Err(#nongoose::Error::NoImplemented)
        }
      };
    }
  }

  quote! {
    fn __relations() -> Vec<#nongoose::types::SchemaRelation> {
      Vec::new()
    }

    fn __get_relations(&self) -> Option<Vec<#nongoose::types::SchemaRelation>> {
      None
    }

    fn __set_relations(&mut self, _field: &str, _new_value: #nongoose::bson::Bson) -> #nongoose::Result<()> {
      Ok(())
    }
  }
}