summaryrefslogtreecommitdiff
path: root/src/generate/struc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/generate/struc.rs')
-rw-r--r--src/generate/struc.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/generate/struc.rs b/src/generate/struc.rs
new file mode 100644
index 0000000..9b2ff51
--- /dev/null
+++ b/src/generate/struc.rs
@@ -0,0 +1,50 @@
+use crate::{
+ info_structures::StructInfo,
+ utils::{self, replace_this_with_lifetime},
+};
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::Error;
+
+/// Creates the struct that will actually store the data. This involves properly organizing the
+/// fields, collecting metadata about them, reversing the order everything is stored in, and
+/// converting any uses of 'this to 'static.
+pub fn create_actual_struct_def(info: &StructInfo) -> Result<TokenStream, Error> {
+ let vis = utils::submodule_contents_visiblity(&info.vis);
+ let ident = &info.ident;
+ let generics = &info.generics;
+
+ let field_defs: Vec<_> = info
+ .fields
+ .iter()
+ // Reverse the order of all fields. We ensure that items in the struct are only dependent
+ // on references to items above them. Rust drops items in a struct in forward declaration order.
+ // This would cause parents being dropped before children, necessitating the reversal.
+ .rev()
+ .map(|field| {
+ let name = &field.name;
+ let ty = field.stored_type();
+ quote! {
+ #[doc(hidden)]
+ #name: #ty
+ }
+ })
+ .collect();
+
+ // Create the new struct definition.
+ let mut where_clause = quote! {};
+ if let Some(clause) = &generics.where_clause {
+ where_clause = quote! { #clause };
+ }
+ let def = quote! {
+ #vis struct #ident #generics #where_clause {
+ #(#field_defs),*
+ }
+ };
+
+ // Finally, replace the fake 'this lifetime with the one we found.
+ let fake_lifetime = info.fake_lifetime();
+ let def = replace_this_with_lifetime(quote! { #def }, fake_lifetime.clone());
+
+ Ok(def)
+}