From 2d2602b057dd750ec3ad308d05f8c9daf65ca7c6 Mon Sep 17 00:00:00 2001 From: Thelie Date: Wed, 2 Mar 2022 18:14:48 +0100 Subject: [PATCH] Just realized I can just serialize the tokenstream :) --- Cargo.toml | 2 +- sing_macros/src/lib.rs | 1 - src/lib.rs | 8 +- src/serde_wrapper.rs | 305 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 272 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8bf2b35..6ad597c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,4 @@ bench = false [dependencies] serde = { version = "1.0", features = ["derive"] } syn = { version = "1.0", features = ["full"] } - +proc-macro2 = "1.0" diff --git a/sing_macros/src/lib.rs b/sing_macros/src/lib.rs index 67ee217..d10de99 100644 --- a/sing_macros/src/lib.rs +++ b/sing_macros/src/lib.rs @@ -79,7 +79,6 @@ pub fn my_derive(input: proc_macro::TokenStream, annotated_item: proc_macro::To let trait_state = load_trait_state().unwrap(); - save_trait_state(trait_state).unwrap(); // Build the output, possibly using quasi-quotation diff --git a/src/lib.rs b/src/lib.rs index 71e27f0..27b151e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,20 +1,20 @@ use core::fmt::Debug; use serde::{Serialize, Deserialize}; -use serde_wrapper::ImplItemMethodWrapper; +use serde_wrapper::TokenStreamWrapper; mod serde_wrapper; #[derive(Debug, Clone, Serialize, Deserialize)] struct TraitProfile{ //functions: HashMap, - functions: Vec, + functions: Vec, } #[derive(Debug, Clone)] enum DeduplicatedFunctionProfile { - Single(String, ImplItemMethodWrapper), - Multiple(Vec, ImplItemMethodWrapper), + Single(String, TokenStreamWrapper), + Multiple(Vec, TokenStreamWrapper), } /*impl Evaluator { diff --git a/src/serde_wrapper.rs b/src/serde_wrapper.rs index a773d09..df4b0a1 100644 --- a/src/serde_wrapper.rs +++ b/src/serde_wrapper.rs @@ -1,5 +1,6 @@ -use serde::{Serialize, Deserialize, Serializer, Deserializer, ser::SerializeStruct}; -use syn::{ImplItemMethod, Visibility, Signature, Pat, FnArg, Type, PatIdent, Ident, __private::Span, Receiver, ReturnType, Generics}; +use proc_macro2::TokenStream; +use serde::{Serialize, Deserialize, Serializer, Deserializer, ser::{SerializeStruct, SerializeTupleVariant, SerializeStructVariant}}; +use syn::{ImplItemMethod, Visibility, Signature, Pat, FnArg, Type, PatIdent, Ident, __private::{Span, ToTokens}, Receiver, ReturnType, Generics, GenericParam, QSelf, Path, Lifetime, TraitBound, TypeParamBound}; use core::fmt::{Debug, Formatter}; use std::error::Error; @@ -45,22 +46,15 @@ impl Serialize for VisibilityWrapper<'_> { S: Serializer { match &self.0 { - Visibility::Public(_) => serializer.serialize_str("pub"), - Visibility::Crate(_) => serializer.serialize_str("crate"), - Visibility::Restricted(r) => { - let mut path_str = String::from(""); - - for seg in &r.path.segments { - // There should be no arguments in the paths passed here. - path_str.push_str(seg.ident.to_string().as_str()); - path_str.push_str("::"); - } - - serializer.serialize_str( - format!("pub ({})", path_str).as_str() - ) - }, - Visibility::Inherited => serializer.serialize_str("inherited"), + Visibility::Public(_) => serializer.serialize_unit_variant("Visibility", 0, "Pub"), + Visibility::Crate(_) => serializer.serialize_unit_variant("Visibility", 1, "Crate"), + Visibility::Restricted(r) => serializer.serialize_newtype_variant( + "Visibility", + 2, + "Restricted", + &PathWrapper(*r.path), + ), + Visibility::Inherited => serializer.serialize_unit_variant("Visibility", 3, "Inherited"), } } } @@ -104,13 +98,13 @@ impl Serialize for SignatureWrapper<'_> { }?; // No need to serialize the Fn token - state.serialize_field("ident", &inner.ident.to_string()); + state.serialize_field("ident", &inner.ident.to_string())?; - state.serialize_field("generics", &GenericsWrapper(&inner.generics)); + state.serialize_field("generics", &GenericsWrapper(inner.generics))?; // Parentheses do not need to be serialized either - serialize_iterator( + serialize_iterator_struct( &mut state, Box::new(inner .inputs @@ -129,25 +123,46 @@ impl Serialize for SignatureWrapper<'_> { state.serialize_field("variadic", match inner.variadic{ Some(_) => "...", None => "", - }); + })?; match &inner.output{ - ReturnType::Default => {state.serialize_field("output", "()");}, - ReturnType::Type(_, t) => {(state.serialize_field("output", &TypeWrapper(*t.clone())));} + ReturnType::Default => {state.serialize_field("output", "()")?;}, + ReturnType::Type(_, t) => {(state.serialize_field("output", &TypeWrapper(*t.clone())))?;} }; state.end() } } -struct GenericsWrapper<'a>(&'a Generics); +struct GenericsWrapper(Generics); -impl Serialize for GenericsWrapper<'_> { +impl Serialize for GenericsWrapper { fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> where S: Serializer { todo!() + /*let inner = &self.0; + let mut state = serializer.serialize_struct("Signature", 7)?; + + serialize_iterator( + &mut state, + Box::new(inner + .params + .clone() + .into_iter() + ), + "params", + | inp: &GenericParam | -> Result<(PatWrapper, Option), Box> { + match inp { + GenericParam::Type(t) => t, + GenericParam::Lifetime() => {}, + GenericParam::Const() => {}, + } + } + ); + + state.end()*/ } } @@ -158,7 +173,106 @@ impl Serialize for PatWrapper { where S: Serializer { - todo!() + let inner = &self.0; + + match inner { + Pat::Box(b) => serializer.serialize_newtype_variant("Pat", 0, "Box", &PatWrapper(*b.pat.clone())), + Pat::Ident(i) => { + let mut state = serializer.serialize_struct_variant("Pat", 1, "Ident", 4)?; + + if i.by_ref.is_some() { + state.serialize_field("by_ref", &Some(String::from("ref"))); + } else { + state.serialize_field("by_ref", &None::); + } + + if i.mutability.is_some() { + state.serialize_field("mutability", &Some(String::from("mut"))); + } else { + state.serialize_field("mutability", &None::); + } + + state.serialize_field("ident", &i.ident.to_string()); + + if let Some((_, s)) = &i.subpat { + state.serialize_field("subpat", &PatWrapper(*s.clone())); + } else { + state.serialize_field("subpat", &None::); + } + + state.end() + } + Pat::Path(p) => { + let mut state = serializer.serialize_struct_variant("Pat", 5, "Path", 2)?; + + if let Some(q) = &p.qself { + state.serialize_field("QSelf", &Some(QSelfWrapper(q.clone()))); + } else { + state.serialize_field("QSelf", &None::); + } + + state.serialize_field("Path", &PathWrapper(p.path.clone())); + + state.end() + } + Pat::Reference(r) => { + let mut state = serializer.serialize_struct_variant("Pat", 7, "Reference", 2)?; + + if r.mutability.is_some() { + state.serialize_field("mutability", &Some(String::from("mut"))); + } else { + state.serialize_field("mutability", &None::); + } + + state.serialize_field("pat", &PatWrapper(*r.pat.clone())); + + state.end() + } + Pat::Slice(s) => { + let mut state = serializer.serialize_struct_variant("Pat", 9, "Slice", 1)?; + + serialize_iterator_struct_variant( + &mut state, + Box::new( + s.elems + .clone() + .into_iter() + ), + "elems", + |p: &Pat| -> Result> {Ok(PatWrapper(p.clone()))} + ); + + state.end() + } + Pat::Tuple(t) => { + let mut state = serializer.serialize_struct_variant("Pat", 11, "Tuple", 1)?; + + serialize_iterator_struct_variant( + &mut state, + Box::new( + t.elems + .clone() + .into_iter() + ), + "elems", + |p: &Pat| -> Result> {Ok(PatWrapper(p.clone()))} + ); + + state.end() + } + Pat::Type(t) => { + let mut state = serializer.serialize_struct_variant("Pat", 13, "Type", 2)?; + + state.serialize_field("pat", &PatWrapper(*t.pat.clone())); + state.serialize_field("ty", &TypeWrapper(*t.ty.clone())); + + state.end() + } + Pat::Verbatim(t) => serializer.serialize_newtype_variant("Pat", 14, "Verbatim", &t.to_string()), + Pat::Wild(_) => serializer.serialize_unit_variant("Pat", 15, "Wild"), + // The rest can't be used in function arguments. + _ => unimplemented!() + } } } @@ -169,30 +283,128 @@ impl Serialize for TypeWrapper { where S: Serializer { + let inner = &self.0; + + match inner { + Type::Array(a) => { + let mut state = serializer.serialize_struct_variant("Pat", 0, "Type", 2)?; + + state.serialize_field("elem", &TypeWrapper(*a.elem.clone())); + // TODO: this is somewhat inelegant: + state.serialize_field("len", &a.len.to_token_stream().to_string()); + + state.end() + } + Type::Group(g) => serializer.serialize_newtype_variant("Type", 2, "Group", &TypeWrapper(*g.elem.clone())), + Type::ImplTrait(t) => { + let mut state = serializer.serialize_struct_variant("Pat", 11, "Tuple", 1)?; + + serialize_iterator_struct_variant( + &mut state, + Box::new( + t.bounds + .clone() + .into_iter() + ), + "elems", + |p: &TypeParamBound| -> Result> {Ok(PatWrapper(p.clone()))} + ); + + state.end() + } + // The rest can't be used in function arguments. + _ => unimplemented!() + } + } +} + +struct PathWrapper(Path); + +impl Serialize for PathWrapper { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer + { + /*let mut path_str = String::from(""); + + for seg in &r.path.segments { + // There should be no arguments in the paths passed here. + path_str.push_str(seg.ident.to_string().as_str()); + path_str.push_str("::"); + } + + serializer.serialize_str( + format!("pub ({})", path_str).as_str() + )*/ todo!() } } +struct QSelfWrapper(QSelf); + +impl Serialize for QSelfWrapper { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer + { + todo!() + } +} + +struct LifetimeWrapper(Lifetime); + +impl Serialize for LifetimeWrapper { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer + { + let inner = &self.0; + serializer.serialize_newtype_struct("Lifetime", &inner.ident.to_string()) + } +} + +pub struct TokenStreamWrapper(TokenStream); + +impl Serialize for TokenStreamWrapper { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer + { + let inner = &self.0; + serializer.serialize_newtype_struct("Lifetime", &inner.to_string()) + } +} + + +struct TraitBoundWrapper(TraitBound); + +impl Serialize for TraitBoundWrapper { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer + { + let inner = &self.0; + todo!(); + } +} + fn patopt_from_receiver(r: Receiver) -> (PatWrapper, Option) { let mut ident = String::from(""); - match &r.reference { - Some((_, lt)) => { - ident.push_str("&"); + if let Some((_, lt)) = &r.reference { + ident.push('&'); match lt { Some(l) => ident.push_str( - &l.ident + l.ident .to_string() .as_str() ), None => {}, } - ident.push_str(" "); - }, - None => {}, - } + ident.push(' '); + } (PatWrapper(Pat::Ident(PatIdent{ attrs: vec!(), @@ -203,16 +415,33 @@ fn patopt_from_receiver(r: Receiver) -> (PatWrapper, Option) { })), None) } -fn serialize_iterator (serializer: &mut S, iterator: Box>, field_name: &'static str, get_string_fun: F) +fn serialize_iterator_struct (serializer: &mut S, iterator: Box>, field_name: &'static str, item_fun: F) -> Result<(), Box> where F: Fn(&T) -> Result>, - S: SerializeStruct, + S: SerializeStruct , U: Serialize, { let mut p_vec = vec!(); for item in iterator { - p_vec.push(get_string_fun(&item)?); + p_vec.push(item_fun(&item)?); + } + serializer.serialize_field(field_name, &p_vec); + Ok(()) +} + +// Thanks to weird traits in Serde we need to duplicate code hereā€¦ +// TODO: Maybe to this as a macro +fn serialize_iterator_struct_variant (serializer: &mut S, iterator: Box>, field_name: &'static str, item_fun: F) + -> Result<(), Box> +where + F: Fn(&T) -> Result>, + S: SerializeStructVariant , + U: Serialize, +{ + let mut p_vec = vec!(); + for item in iterator { + p_vec.push(item_fun(&item)?); } serializer.serialize_field(field_name, &p_vec); Ok(())