blob: ad3c650632054ebd64f53ed626dca2535ef0c872 [file] [log] [blame]
use quote;
use syn;
use util::*;
#[derive(Debug)]
pub struct Attr {
column_name: Option<syn::Ident>,
field_name: Option<syn::Ident>,
sql_type: Option<syn::Ty>,
flags: Vec<syn::Ident>,
pub ty: syn::Ty,
pub field_position: syn::Ident,
}
impl Attr {
pub fn from_struct_field((index, field): (usize, &syn::Field)) -> Self {
let field_name = field.ident.clone();
let column_name = ident_value_of_attr_with_name(&field.attrs, "column_name")
.cloned()
.or_else(|| field_name.clone());
let ty = field.ty.clone();
let sql_type = str_value_of_attr_with_name(&field.attrs, "sql_type")
.map(|st| syn::parse::ty(st).expect("#[sql_type] did not contain a valid Rust type"));
let flags = list_value_of_attr_with_name(&field.attrs, "diesel")
.unwrap_or_else(Vec::new)
.into_iter()
.cloned()
.collect();
Attr {
column_name,
field_name,
sql_type,
ty,
flags,
field_position: index.to_string().into(),
}
}
pub fn field_name(&self) -> &syn::Ident {
self.field_name.as_ref().unwrap_or(&self.field_position)
}
pub fn column_name(&self) -> &syn::Ident {
self.column_name
.as_ref()
.or_else(|| self.field_name.as_ref())
.expect(
"All fields of tuple structs must be annotated with `#[column_name=\"something\"]`",
)
}
pub fn sql_type(&self) -> Option<&syn::Ty> {
self.sql_type.as_ref()
}
pub fn has_flag<T>(&self, flag: &T) -> bool
where
T: ?Sized,
syn::Ident: PartialEq<T>,
{
self.flags.iter().any(|f| f == flag)
}
fn field_kind(&self) -> &str {
if is_option_ty(&self.ty) {
"option"
} else if self.column_name.is_none() && self.field_name.is_none() {
"bare"
} else {
"regular"
}
}
}
impl quote::ToTokens for Attr {
fn to_tokens(&self, tokens: &mut quote::Tokens) {
tokens.append("{");
if let Some(ref name) = self.field_name {
tokens.append("field_name: ");
name.to_tokens(tokens);
tokens.append(", ");
}
if let Some(ref name) = self.column_name {
tokens.append("column_name: ");
name.to_tokens(tokens);
tokens.append(", ");
}
tokens.append("field_ty: ");
self.ty.to_tokens(tokens);
tokens.append(", ");
tokens.append("field_kind: ");
tokens.append(self.field_kind());
tokens.append(", ");
tokens.append("inner_field_ty: ");
inner_of_option_ty(&self.ty)
.unwrap_or(&self.ty)
.to_tokens(tokens);
tokens.append(", ");
tokens.append("}");
}
}