macro for adding traits is done.
This commit is contained in:
parent
2d2602b057
commit
cb3bbdbb78
6 changed files with 191 additions and 468 deletions
|
@ -3,13 +3,12 @@ use std::{
|
||||||
env,
|
env,
|
||||||
fs,
|
fs,
|
||||||
error::Error,
|
error::Error,
|
||||||
io::{Write, Read}, fmt::format, path::Path,
|
io::{Write, Read},
|
||||||
};
|
};
|
||||||
use rand::rngs::adapter::ReseedingRng;
|
use sing_util::TraitProfile;
|
||||||
use serde::{Serialize, Deserialize};
|
use syn::{parse_macro_input, AttributeArgs, ItemImpl, ImplItem};
|
||||||
use syn::{parse_macro_input, DeriveInput, AttributeArgs, ItemImpl, ImplItem};
|
use quote::{quote, spanned::Spanned, ToTokens};
|
||||||
use quote::{quote, spanned::Spanned};
|
|
||||||
use proc_macro2::{Span, Spacing, Delimiter, TokenStream, Literal, TokenTree, Ident, Punct, Group};
|
|
||||||
|
|
||||||
extern crate sing_util;
|
extern crate sing_util;
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
@ -51,25 +50,26 @@ fn load_trait_state() -> Result<HashMap<String, sing_util::TraitProfile>, Box<dy
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn my_derive(input: proc_macro::TokenStream, annotated_item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn sing_add_trait(input: proc_macro::TokenStream, annotated_item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let input = parse_macro_input!(input as ItemImpl);
|
let input = parse_macro_input!(input as ItemImpl);
|
||||||
let annotated_item = parse_macro_input!(annotated_item as AttributeArgs);
|
let annotated_item = parse_macro_input!(annotated_item as AttributeArgs);
|
||||||
|
|
||||||
let trait_name;
|
let trait_name;
|
||||||
match input.trait_ {
|
match &input.trait_ {
|
||||||
Some((_b, p, _f)) => {
|
Some((_b, p, _f)) => {
|
||||||
trait_name = p;
|
trait_name = p.into_token_stream().to_string();
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
syn::Error::new(input.__span(), "This attribute can only be used on trait impl blocks.")
|
syn::Error::new(input.__span(), "This attribute can only be used on trait impl blocks.")
|
||||||
.to_compile_error();
|
.to_compile_error();
|
||||||
|
trait_name = String::from("");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut trait_functions = vec!();
|
let mut trait_functions = vec!();
|
||||||
for fun in input.items {
|
for fun in &input.items {
|
||||||
match fun {
|
match fun {
|
||||||
ImplItem::Method(m) => trait_functions.push(m.sig),
|
ImplItem::Method(m) => trait_functions.push(m.sig.to_token_stream()),
|
||||||
_ => {
|
_ => {
|
||||||
syn::Error::new(input.__span(), "Found unexpected item that is not a method.")
|
syn::Error::new(input.__span(), "Found unexpected item that is not a method.")
|
||||||
.to_compile_error();
|
.to_compile_error();
|
||||||
|
@ -77,8 +77,17 @@ pub fn my_derive(input: proc_macro::TokenStream, annotated_item: proc_macro::To
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_state = load_trait_state().unwrap();
|
let mut trait_state = load_trait_state().unwrap();
|
||||||
|
|
||||||
|
let profile = TraitProfile::new(trait_functions);
|
||||||
|
if trait_state.contains_key(trait_name.as_str()) {
|
||||||
|
let err = format!("Trait {} is implemented twice!", trait_name);
|
||||||
|
syn::Error::new(input.__span(), err.as_str())
|
||||||
|
.to_compile_error();
|
||||||
|
} else {
|
||||||
|
trait_state.insert(trait_name, profile);
|
||||||
|
}
|
||||||
|
|
||||||
save_trait_state(trait_state).unwrap();
|
save_trait_state(trait_state).unwrap();
|
||||||
|
|
||||||
// Build the output, possibly using quasi-quotation
|
// Build the output, possibly using quasi-quotation
|
||||||
|
|
|
@ -2,11 +2,17 @@
|
||||||
name = "sing_util"
|
name = "sing_util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
bench = false
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
# build = "build.rs"
|
||||||
|
#
|
||||||
|
# [build-dependencies]
|
||||||
|
# lalrpop = "0.19"
|
||||||
|
#
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ron = "0.7"
|
|
||||||
rand = "0.7"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
syn = { version = "1.0", features = ["full"] }
|
||||||
|
proc-macro2 = "1.0"
|
||||||
|
|
|
@ -1,37 +1,37 @@
|
||||||
use std::{
|
use core::fmt::Debug;
|
||||||
collections::HashMap,
|
|
||||||
env,
|
|
||||||
fs,
|
|
||||||
error::Error,
|
|
||||||
io::{Write, Read}, fmt::format,
|
|
||||||
};
|
|
||||||
use rand::rngs::adapter::ReseedingRng;
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
use proc_macro2::TokenStream;
|
||||||
pub struct FunctionProfile{
|
use serde::{Serialize, Deserialize};
|
||||||
inputs: String,
|
use serde_wrapper::TokenStreamWrapper;
|
||||||
outputs: String,
|
|
||||||
}
|
mod serde_wrapper;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct TraitProfile{
|
pub struct TraitProfile{
|
||||||
functions: HashMap<String, FunctionProfile>,
|
//functions: HashMap<String, FunctionProfile>,
|
||||||
}
|
functions: Vec<TokenStreamWrapper>,
|
||||||
|
}
|
||||||
|
|
||||||
impl TraitProfile {
|
impl TraitProfile{
|
||||||
pub fn get_fun_profile(&self, query: &String) -> Option<&FunctionProfile> {
|
pub fn new(streams: Vec<TokenStream>) -> Self {
|
||||||
self.functions.get(query)
|
let mut inner = vec!();
|
||||||
|
|
||||||
|
for stream in streams {
|
||||||
|
inner.push(TokenStreamWrapper::new(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
Self{
|
||||||
|
functions: inner
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum DeduplicatedFunctionProfile {
|
enum DeduplicatedFunctionProfile {
|
||||||
Single(String, FunctionProfile),
|
Single(String, TokenStreamWrapper),
|
||||||
Multiple(Vec<String>, FunctionProfile),
|
Multiple(Vec<String>, TokenStreamWrapper),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*impl<T> Evaluator<T> {
|
/*impl<T> Evaluator<T> {
|
||||||
fn deduplicate_functions(&self) -> Self<T> {
|
fn deduplicate_functions(&self) -> Self<T> {
|
||||||
let mut self = self.clone();
|
let mut self = self.clone();
|
||||||
|
|
71
sing_util/src/serde_wrapper.rs
Normal file
71
sing_util/src/serde_wrapper.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use std::{str::FromStr, fmt::{self, format}};
|
||||||
|
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use serde::{Serialize, Serializer, Deserialize, Deserializer, de::{Visitor, self}};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TokenStreamWrapper(TokenStream);
|
||||||
|
|
||||||
|
impl TokenStreamWrapper {
|
||||||
|
pub fn new(stream: TokenStream) -> Self {
|
||||||
|
Self(stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for TokenStreamWrapper {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
||||||
|
where
|
||||||
|
S: Serializer
|
||||||
|
{
|
||||||
|
let inner = &self.0;
|
||||||
|
serializer.serialize_newtype_struct("Lifetime", &inner.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for TokenStreamWrapper {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
let tok_str = deserializer.deserialize_string(TokenStreamVisitor)?;
|
||||||
|
|
||||||
|
match TokenStream::from_str(&tok_str.as_str()) {
|
||||||
|
Ok(t) => Ok(Self(t)),
|
||||||
|
Err(e) => Err(de::Error::custom(
|
||||||
|
format!("string does not represent a valid TokenStream: {}", e)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TokenStreamVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for TokenStreamVisitor {
|
||||||
|
type Value = String;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("A string representing a TokenStream")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(value.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(value.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
src/lib.rs
15
src/lib.rs
|
@ -1,5 +1,6 @@
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use serde_wrapper::TokenStreamWrapper;
|
use serde_wrapper::TokenStreamWrapper;
|
||||||
|
|
||||||
|
@ -11,6 +12,20 @@ struct TraitProfile{
|
||||||
functions: Vec<TokenStreamWrapper>,
|
functions: Vec<TokenStreamWrapper>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TraitProfile{
|
||||||
|
pub fn new(streams: Vec<TokenStream>) -> Self {
|
||||||
|
let mut inner = vec!();
|
||||||
|
|
||||||
|
for stream in streams {
|
||||||
|
inner.push(TokenStreamWrapper::new(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
Self{
|
||||||
|
functions: inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum DeduplicatedFunctionProfile {
|
enum DeduplicatedFunctionProfile {
|
||||||
Single(String, TokenStreamWrapper),
|
Single(String, TokenStreamWrapper),
|
||||||
|
|
|
@ -1,370 +1,17 @@
|
||||||
|
use std::{str::FromStr, fmt::{self, format}};
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use serde::{Serialize, Deserialize, Serializer, Deserializer, ser::{SerializeStruct, SerializeTupleVariant, SerializeStructVariant}};
|
use serde::{Serialize, Serializer, Deserialize, Deserializer, de::{Visitor, self}};
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub (crate) struct ImplItemMethodWrapper(ImplItemMethod);
|
|
||||||
|
|
||||||
impl Debug for ImplItemMethodWrapper {
|
|
||||||
fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for ImplItemMethodWrapper {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
where
|
|
||||||
S: Serializer
|
|
||||||
{
|
|
||||||
let inner = &self.0;
|
|
||||||
let mut state = serializer.serialize_struct("Color", 4)?;
|
|
||||||
|
|
||||||
// Attribute macros are not important in our case.
|
|
||||||
state.serialize_field("vis", &VisibilityWrapper(&inner.vis));
|
|
||||||
// Defaultness are also not important here.
|
|
||||||
state.serialize_field("sig", &SignatureWrapper(&inner.sig));
|
|
||||||
// We can throw away the block too.
|
|
||||||
|
|
||||||
state.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for ImplItemMethodWrapper {
|
|
||||||
fn deserialize<D>(_: D) -> Result<Self, <D as Deserializer<'de>>::Error> where D: Deserializer<'de> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VisibilityWrapper<'a>(&'a Visibility);
|
|
||||||
|
|
||||||
impl Serialize for VisibilityWrapper<'_> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
where
|
|
||||||
S: Serializer
|
|
||||||
{
|
|
||||||
match &self.0 {
|
|
||||||
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"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SignatureWrapper<'a>(&'a Signature);
|
|
||||||
|
|
||||||
impl Serialize for SignatureWrapper<'_> {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
where
|
|
||||||
S: Serializer
|
|
||||||
{
|
|
||||||
let inner = &self.0;
|
|
||||||
let mut state = serializer.serialize_struct("Signature", 7)?;
|
|
||||||
|
|
||||||
let mut prefixes = vec!();
|
|
||||||
if inner.constness.is_some() {
|
|
||||||
prefixes.push("const")
|
|
||||||
}
|
|
||||||
if inner.asyncness.is_some() {
|
|
||||||
prefixes.push("async")
|
|
||||||
}
|
|
||||||
if inner.unsafety.is_some() {
|
|
||||||
prefixes.push("unsafe")
|
|
||||||
}
|
|
||||||
state.serialize_field("prefixes", &prefixes)?;
|
|
||||||
|
|
||||||
match &inner.abi {
|
|
||||||
Some(a) => state.serialize_field(
|
|
||||||
"abi",
|
|
||||||
&Some(
|
|
||||||
format!(
|
|
||||||
"extern {}",
|
|
||||||
match &a.name {
|
|
||||||
Some(n) => n.value(),
|
|
||||||
None => String::from(""),
|
|
||||||
}
|
|
||||||
).as_str()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
None => state.serialize_field("abi", &None::<String>),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
// No need to serialize the Fn token
|
|
||||||
state.serialize_field("ident", &inner.ident.to_string())?;
|
|
||||||
|
|
||||||
state.serialize_field("generics", &GenericsWrapper(inner.generics))?;
|
|
||||||
|
|
||||||
// Parentheses do not need to be serialized either
|
|
||||||
|
|
||||||
serialize_iterator_struct(
|
|
||||||
&mut state,
|
|
||||||
Box::new(inner
|
|
||||||
.inputs
|
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
),
|
|
||||||
"inputs",
|
|
||||||
| inp: &FnArg | -> Result<(PatWrapper, Option<TypeWrapper>), Box<dyn Error>> {
|
|
||||||
match inp {
|
|
||||||
FnArg::Receiver(r) => Ok(patopt_from_receiver(r.clone())),
|
|
||||||
FnArg::Typed(t) => Ok((PatWrapper(*t.pat.clone()), Some(TypeWrapper(*t.ty.clone())))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
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())))?;}
|
|
||||||
};
|
|
||||||
|
|
||||||
state.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct GenericsWrapper(Generics);
|
|
||||||
|
|
||||||
impl Serialize for GenericsWrapper {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::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<TypeWrapper>), Box<dyn Error>> {
|
|
||||||
match inp {
|
|
||||||
GenericParam::Type(t) => t,
|
|
||||||
GenericParam::Lifetime() => {},
|
|
||||||
GenericParam::Const() => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
state.end()*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PatWrapper(Pat);
|
|
||||||
|
|
||||||
impl Serialize for PatWrapper {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
where
|
|
||||||
S: Serializer
|
|
||||||
{
|
|
||||||
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::<String>);
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.mutability.is_some() {
|
|
||||||
state.serialize_field("mutability", &Some(String::from("mut")));
|
|
||||||
} else {
|
|
||||||
state.serialize_field("mutability", &None::<String>);
|
|
||||||
}
|
|
||||||
|
|
||||||
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::<PatWrapper>);
|
|
||||||
}
|
|
||||||
|
|
||||||
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::<QSelfWrapper>);
|
|
||||||
}
|
|
||||||
|
|
||||||
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::<String>);
|
|
||||||
}
|
|
||||||
|
|
||||||
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<PatWrapper, Box<dyn Error>> {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<PatWrapper, Box<dyn Error>> {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!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TypeWrapper( Type);
|
|
||||||
|
|
||||||
impl Serialize for TypeWrapper {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
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<PatWrapper, Box<dyn Error>> {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<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::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<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
where
|
|
||||||
S: Serializer
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LifetimeWrapper(Lifetime);
|
|
||||||
|
|
||||||
impl Serialize for LifetimeWrapper {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
where
|
|
||||||
S: Serializer
|
|
||||||
{
|
|
||||||
let inner = &self.0;
|
|
||||||
serializer.serialize_newtype_struct("Lifetime", &inner.ident.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct TokenStreamWrapper(TokenStream);
|
pub struct TokenStreamWrapper(TokenStream);
|
||||||
|
|
||||||
|
impl TokenStreamWrapper {
|
||||||
|
pub fn new(stream: TokenStream) -> Self {
|
||||||
|
Self(stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Serialize for TokenStreamWrapper {
|
impl Serialize for TokenStreamWrapper {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
||||||
where
|
where
|
||||||
|
@ -375,75 +22,50 @@ impl Serialize for TokenStreamWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for TokenStreamWrapper {
|
||||||
struct TraitBoundWrapper(TraitBound);
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
impl Serialize for TraitBoundWrapper {
|
D: Deserializer<'de>
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
|
||||||
where
|
|
||||||
S: Serializer
|
|
||||||
{
|
{
|
||||||
let inner = &self.0;
|
let tok_str = deserializer.deserialize_string(TokenStreamVisitor)?;
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn patopt_from_receiver(r: Receiver) -> (PatWrapper, Option<TypeWrapper>) {
|
match TokenStream::from_str(&tok_str.as_str()) {
|
||||||
let mut ident = String::from("");
|
Ok(t) => Ok(Self(t)),
|
||||||
|
Err(e) => Err(de::Error::custom(
|
||||||
if let Some((_, lt)) = &r.reference {
|
format!("string does not represent a valid TokenStream: {}", e)
|
||||||
ident.push('&');
|
))
|
||||||
|
|
||||||
match lt {
|
|
||||||
Some(l) => ident.push_str(
|
|
||||||
l.ident
|
|
||||||
.to_string()
|
|
||||||
.as_str()
|
|
||||||
),
|
|
||||||
None => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
ident.push(' ');
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TokenStreamVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for TokenStreamVisitor {
|
||||||
|
type Value = String;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("A string representing a TokenStream")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(value.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(value.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
(PatWrapper(Pat::Ident(PatIdent{
|
|
||||||
attrs: vec!(),
|
|
||||||
by_ref: None,
|
|
||||||
mutability: r.mutability,
|
|
||||||
ident: Ident::new(&ident, Span::call_site()),
|
|
||||||
subpat: None,
|
|
||||||
})), None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_iterator_struct<S, T, F, U> (serializer: &mut S, iterator: Box<dyn Iterator<Item = T>>, field_name: &'static str, item_fun: F)
|
|
||||||
-> Result<(), Box<dyn Error>>
|
|
||||||
where
|
|
||||||
F: Fn(&T) -> Result<U, Box<dyn Error>>,
|
|
||||||
S: SerializeStruct ,
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thanks to weird traits in Serde we need to duplicate code here…
|
|
||||||
// TODO: Maybe to this as a macro
|
|
||||||
fn serialize_iterator_struct_variant<S, T, F, U> (serializer: &mut S, iterator: Box<dyn Iterator<Item = T>>, field_name: &'static str, item_fun: F)
|
|
||||||
-> Result<(), Box<dyn Error>>
|
|
||||||
where
|
|
||||||
F: Fn(&T) -> Result<U, Box<dyn Error>>,
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue