taitan-orm-parser 0.1.10

Next Generation ORM based on sqlx
Documentation
use crate::attr_parser::{AttrParser, NamedAttribute};
use crate::condition_def::{ConditionDef, VariantsOrFields};
use crate::{FieldDef, InputParser};
use case::CaseExt;
use std::borrow::Cow;
use syn::parse::Parser;
use syn::DeriveInput;

#[derive(PartialEq, Clone, Copy, Default)]
pub struct ConditionParser;

impl ConditionParser {
    pub fn parse(input: &DeriveInput) -> ConditionDef {
        let struct_name = input.ident.to_string();
        let table_name_attr: Option<NamedAttribute> = AttrParser::extract(&input.attrs, "table");
        let table_name = if let Some(attr) = &table_name_attr {
            attr.get_single_value().to_owned()
        } else {
            Cow::Owned(struct_name.to_snake())
        };
        let serde_attr: Option<NamedAttribute> = AttrParser::extract(&input.attrs, "serde_struct");
        let serde_structs = serde_attr.map(|attr| attr.values).unwrap_or_default();

        let is_enum = InputParser::is_enum(&input.data);
        let variants_or_fields = if is_enum {
            let variants = InputParser::get_enum_variant_defs(&input.data).unwrap();
            VariantsOrFields::Variants(variants)
        } else {
            let fields = InputParser::get_fields(&input.data);
            let defs = fields
                .iter()
                .map(|v| FieldDef::parse(v, false, None, None))
                .collect();
            VariantsOrFields::Fields(defs)
        };

        ConditionDef {
            struct_name: Cow::Owned(struct_name),
            table_name,
            variants_or_fields,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::{FieldName, NamedVariantDef, ParsedField, TableColumnDef};
    use syn::parse_quote;

    #[test]
    fn test_parse_001() {
        let input = parse_quote! {
            enum LocationSpec001 {
                A{name: Expr<String>},
            }
        };

        let cond_def = ConditionParser::parse(&input);
        let field = match &cond_def.variants_or_fields {
            VariantsOrFields::Variants(v) => v
                .first()
                .unwrap()
                .fields
                .first()
                .unwrap()
                .struct_field
                .origin_field
                .clone(),
            _ => unreachable!(),
        };
        let variant = NamedVariantDef {
            name: "A".to_owned(),
            named: true,
            fields: vec![FieldDef {
                struct_field: ParsedField {
                    name: FieldName::named("name"),
                    rust_type: Cow::Borrowed("Expr < String >"),
                    option_nest_level: 0,
                    is_location_expr: true,
                    is_enum_variant: true,
                    lifetime: None,
                    origin_field: field,
                },
                table_column: TableColumnDef {
                    name: None,
                    column_type: None,
                    default_value: None,
                    generated: None,
                    nullable: false,
                    auto_inc: false,
                },
            }],
        };
        let expected_def = ConditionDef {
            struct_name: Cow::Borrowed("LocationSpec001"),
            table_name: Cow::Borrowed("location_spec001"),
            variants_or_fields: VariantsOrFields::Variants(vec![variant]),
        };
        assert_eq!(cond_def, expected_def);
    }

    #[test]
    fn test_parse_002() {
        let input = parse_quote! {
            enum LocationSpec002 {
                A(Expr<String>, Expr<String>),
            }
        };
        let cond_def = ConditionParser::parse(&input);

        let field = match &cond_def.variants_or_fields {
            VariantsOrFields::Variants(v) => v
                .first()
                .unwrap()
                .fields
                .first()
                .unwrap()
                .struct_field
                .origin_field
                .clone(),
            _ => unreachable!(),
        };
        let field2 = match &cond_def.variants_or_fields {
            VariantsOrFields::Variants(v) => v
                .first()
                .unwrap()
                .fields
                .get(1)
                .unwrap()
                .struct_field
                .origin_field
                .clone(),
            _ => unreachable!(),
        };
        let variant1 = NamedVariantDef {
            name: "A".to_owned(),
            named: false,
            fields: vec![
                FieldDef {
                    struct_field: ParsedField {
                        name: FieldName::unnamed(0),
                        rust_type: Cow::Borrowed("Expr < String >"),
                        option_nest_level: 0,
                        is_location_expr: true,
                        is_enum_variant: true,
                        lifetime: None,
                        origin_field: field,
                    },
                    table_column: TableColumnDef {
                        name: Some(Cow::Borrowed("a")),
                        column_type: None,
                        default_value: None,
                        generated: None,
                        nullable: false,
                        auto_inc: false,
                    },
                },
                FieldDef {
                    struct_field: ParsedField {
                        name: FieldName::unnamed(1),
                        rust_type: Cow::Borrowed("Expr < String >"),
                        option_nest_level: 0,
                        is_location_expr: true,
                        is_enum_variant: true,
                        lifetime: None,
                        origin_field: field2,
                    },
                    table_column: TableColumnDef {
                        name: Some(Cow::Borrowed("a")),
                        column_type: None,
                        default_value: None,
                        generated: None,
                        nullable: false,
                        auto_inc: false,
                    },
                },
            ],
        };


        let expected_def = ConditionDef {
            struct_name: Cow::Borrowed("LocationSpec002"),
            table_name: Cow::Borrowed("location_spec002"),
            variants_or_fields: VariantsOrFields::Variants(vec![variant1]),
        };
        assert_eq!(cond_def, expected_def);
    }
}