1
use partialdebug::placeholder::PartialDebug;
2
use proc_macro2::Ident;
3
use quote::ToTokens;
4
use std::convert::TryFrom;
5
use syn::{Attribute, Field, Type};
6

            
7
use super::field_annotation::EntityFieldAnnotation;
8
/// Represents any of the fields and annotations (if any valid annotation) found for an Rust struct
9
#[derive(PartialDebug, Clone)]
10
pub struct EntityField {
11
    pub name: Ident,
12
    pub field_type: Type,
13
    pub attributes: Vec<EntityFieldAnnotation>,
14
}
15

            
16
impl EntityField {
17
19
    pub fn get_field_type_as_string(&self) -> String {
18
19
        match &self.field_type {
19
            Type::Array(type_) => type_.to_token_stream().to_string(),
20
            Type::BareFn(type_) => type_.to_token_stream().to_string(),
21
            Type::Group(type_) => type_.to_token_stream().to_string(),
22
            Type::ImplTrait(type_) => type_.to_token_stream().to_string(),
23
            Type::Infer(type_) => type_.to_token_stream().to_string(),
24
            Type::Macro(type_) => type_.to_token_stream().to_string(),
25
            Type::Never(type_) => type_.to_token_stream().to_string(),
26
            Type::Paren(type_) => type_.to_token_stream().to_string(),
27
19
            Type::Path(type_) => type_.to_token_stream().to_string(),
28
            Type::Ptr(type_) => type_.to_token_stream().to_string(),
29
            Type::Reference(type_) => type_.to_token_stream().to_string(),
30
            Type::Slice(type_) => type_.to_token_stream().to_string(),
31
            Type::TraitObject(type_) => type_.to_token_stream().to_string(),
32
            Type::Tuple(type_) => type_.to_token_stream().to_string(),
33
            Type::Verbatim(type_) => type_.to_token_stream().to_string(),
34
            _ => "".to_owned(),
35
        }
36
19
    }
37

            
38
38
    pub fn new(name: &Ident, raw_helper_attributes: &[Attribute], ty: &Type) -> syn::Result<Self> {
39
38
        let mut attributes = Vec::new();
40
44
        for attr in raw_helper_attributes {
41
6
            let result = Some(EntityFieldAnnotation::try_from(&attr)?);
42
6
            match result {
43
6
                Some(res) => attributes.push(res),
44
                None => continue,
45
            }
46
        }
47

            
48
38
        Ok(Self {
49
38
            name: name.clone(),
50
38
            field_type: ty.clone(),
51
38
            attributes,
52
        })
53
38
    }
54
}
55

            
56
impl TryFrom<&Field> for EntityField {
57
    type Error = syn::Error;
58

            
59
38
    fn try_from(field: &Field) -> Result<Self, Self::Error> {
60
38
        let name = field.ident.as_ref().ok_or_else(|| {
61
            syn::Error::new_spanned(
62
                field.to_token_stream(),
63
                "Expected a structure with named fields, unnamed field given",
64
            )
65
        })?;
66

            
67
38
        Self::new(name, &field.attrs, &field.ty)
68
38
    }
69
}