use crate::transformer::{StructTable, Transformer};
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use scylla_orm::table_metadata::{ColumnInTable, ColumnKind, ColumnType};
#[derive(Clone)]
pub struct Field {
pub ident: Ident,
pub ident_ty: TokenStream,
pub ty: TokenStream,
pub borrow_ty: TokenStream,
pub from_borrow_to_owned: TokenStream,
pub attributes: TokenStream,
pub pk_attributes: TokenStream,
}
pub struct StructFieldMetadata {
pub field_ts: TokenStream,
pub primary_key_fields: Vec<Field>,
pub fields: Vec<Field>,
pub non_primary_key_fields: Vec<Field>,
}
impl StructFieldMetadata {
pub fn pk_fields_ident(&self) -> Vec<Ident> {
self.primary_key_fields
.iter()
.map(|c| format_ident!("{}", c.ident))
.collect()
}
}
pub(crate) fn column_to_property(
struct_table: StructTable,
columns: &[ColumnInTable],
transformer: &impl Transformer,
) -> StructFieldMetadata {
let mut pk_fields = vec![];
let mut fields = vec![];
let mut non_pk_fields = vec![];
let mut ts = TokenStream::new();
for column in columns {
let pk_attributes = match column.kind() {
ColumnKind::PartitionKey => {
quote! {
#[partition_key]
}
}
ColumnKind::Regular => quote! {}, ColumnKind::Clustering => {
quote! {
#[clustering_key]
}
}
};
let mut field_ts = pk_attributes.clone();
let struct_field = transformer.struct_field(struct_table.clone(), &column.column_name);
let attrs = struct_field.attributes;
let pk_attributes = TokenStream::default();
field_ts.extend(quote! {
#attrs
});
let clone = "clone()".to_string();
let (mut ty, mut borrow_ty, from_borrow_to_owned) = if let Some(json) = struct_field.json {
assert_eq!("text", &column.data_type);
field_ts.extend(quote! {
#[json]
});
(json.clone(), json, clone)
} else {
let ty = ColumnType::new(column.data_type.as_str()).to_ty();
let (borrow_ty, from_borrow_to_owned) = if column.data_type.as_str() == "text" {
("str".to_string(), "to_string()".to_string())
} else {
(ty.clone(), clone)
};
(ty, borrow_ty, from_borrow_to_owned)
};
if struct_field.is_nullable {
let make_nullable = |t| format!("std::option::Option<{}>", t);
ty = make_nullable(ty);
borrow_ty = make_nullable(borrow_ty);
}
let ty: TokenStream = ty.parse().unwrap();
let ident = format_ident!("{}", column.column_name);
let attributes = field_ts.clone();
field_ts.extend(quote! {
pub #ident: #ty,
});
let field = Field {
ident,
ident_ty: field_ts.clone(),
ty,
borrow_ty: borrow_ty.parse().unwrap(),
from_borrow_to_owned: from_borrow_to_owned.parse().unwrap(),
attributes,
pk_attributes,
};
fields.push(field.clone());
if column.kind() == ColumnKind::Regular {
non_pk_fields.push(field);
} else {
pk_fields.push(field);
}
ts.extend(field_ts);
}
StructFieldMetadata {
field_ts: ts,
primary_key_fields: pk_fields,
fields,
non_primary_key_fields: non_pk_fields,
}
}