diff --git a/formbeam_derive/src/derive_form.rs b/formbeam_derive/src/derive_form.rs index 199772d..ba73e8a 100644 --- a/formbeam_derive/src/derive_form.rs +++ b/formbeam_derive/src/derive_form.rs @@ -50,6 +50,7 @@ fn identify_base_type(unprefixed: &Ident) -> FieldType { "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "u64" | "i64" | "u128" | "i128" | "f32" | "f64" => FieldType::Numeric, "String" => FieldType::String, + "bool" => FieldType::Boolean, other => { panic!("unsupported field type: `{other}`") } @@ -89,6 +90,11 @@ fn identify_type(ty: &Type) -> (FieldType, bool) { } syn::GenericArgument::Type(ty) => { let (base_type, check_needed) = identify_type(ty); + if base_type == FieldType::Boolean { + panic!( + "Option isn't supported (does it even make sense?)" + ); + } if !check_needed { panic!("unsupported field type with nested Options or something like that"); } @@ -115,7 +121,11 @@ fn identify_type(ty: &Type) -> (FieldType, bool) { } } else { match &segment.arguments { - syn::PathArguments::None => (identify_base_type(&segment.ident), true), + syn::PathArguments::None => { + let base_type = identify_base_type(&segment.ident); + let needed = base_type != FieldType::Boolean; + (base_type, needed) + } syn::PathArguments::AngleBracketed(_) => { panic!("unsupported field type: non-Option with args") } @@ -169,7 +179,7 @@ fn parse_field_attrs(f: &Field) -> FieldInfo { return Ok(()); } - // #[form(min_chars = 2)] + // #[form(min_chars(2))] if meta.path.is_ident("min_chars") { let content; parenthesized!(content in meta.input); @@ -182,7 +192,7 @@ fn parse_field_attrs(f: &Field) -> FieldInfo { return Ok(()); } - // #[form(max_chars = 2)] + // #[form(max_chars(2))] if meta.path.is_ident("max_chars") { let content; parenthesized!(content in meta.input); @@ -195,7 +205,7 @@ fn parse_field_attrs(f: &Field) -> FieldInfo { return Ok(()); } - // #[form(regex = "\A[0-9]+\Z")] + // #[form(regex("\A[0-9]+\Z"))] if meta.path.is_ident("regex") { let content; parenthesized!(content in meta.input); @@ -333,9 +343,12 @@ struct FieldInfo { regex: Option, } +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] enum FieldType { Numeric, String, + /// Boolean indicating the presence and non-emptiness of the field. + Boolean, } fn write_form_info(fields: &[(Field, FieldInfo)]) -> TokenStream { @@ -518,5 +531,6 @@ fn converter_from_raw_to_field(f: &Ident, field_info: &FieldInfo) -> TokenStream raw.parse().map_err(|_| #f_name)? ), FieldType::String => quote!(raw.to_owned()), + FieldType::Boolean => quote!(!raw.is_empty()), } }