Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
nrxus committed Feb 19, 2024
1 parent 25c4de1 commit 068b112
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 317 deletions.
25 changes: 22 additions & 3 deletions faux_macros/src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub struct Mockable {
real: syn::ItemStruct,
// the morphed definition, wraps the real struct around a MaybeFaux
morphed: syn::ItemStruct,
// Whether the real object should be wrapped when putting it in MaybeFaux::Real
self_type: SelfType,
}

impl Mockable {
Expand Down Expand Up @@ -43,18 +45,35 @@ impl Mockable {
syn::Fields::Unnamed(syn::parse_quote! { (#vis faux::MaybeFaux<#wrapped_self>) })
};

Mockable { real, morphed }
Mockable {
real,
morphed,
self_type: args.self_type,
}
}
}

impl From<Mockable> for proc_macro::TokenStream {
fn from(mockable: Mockable) -> Self {
let Mockable { real, morphed } = mockable;
let Mockable {
real,
morphed,
self_type,
} = mockable;
let (impl_generics, ty_generics, where_clause) = real.generics.split_for_impl();
let name = &morphed.ident;
let name_str = name.to_string();
let real_name = &real.ident;

let inner = match self_type {
// TODO: deprecate Box
SelfType::Owned | SelfType::Box => {
quote! { ::faux::MaybeFaux<#real_name #ty_generics> }
}
SelfType::Rc => quote! { ::faux::MaybeFaux<Rc<#real_name #ty_generics>> },
SelfType::Arc => quote! { ::faux::MaybeFaux<Arc<#real_name #ty_generics>> },
};

proc_macro::TokenStream::from(quote! {
#morphed

Expand All @@ -65,7 +84,7 @@ impl From<Mockable> for proc_macro::TokenStream {
}

unsafe impl #impl_generics ::faux::MockWrapper for #name #ty_generics #where_clause {
type Inner = ::faux::MaybeFaux<#real_name #ty_generics>;
type Inner = #inner;

fn inner(self) -> Self::Inner {
self.0
Expand Down
6 changes: 2 additions & 4 deletions faux_macros/src/methods/morphed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,9 @@ impl<'a> Signature<'a> {
proxy_real = quote! { std::boxed::Box::new(#proxy_real) };
}

let call_stub = quote! { self.#faux_ident(#args) };
let call_stub = quote! { wrapper.#faux_ident(#args) };

method_data
.self_kind
.method_body(real_self, proxy_real, call_stub)
Ok(method_data.self_kind.method_body(proxy_real, call_stub))
}

fn proxy_real<'p>(
Expand Down
155 changes: 14 additions & 141 deletions faux_macros/src/methods/receiver.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::self_type::SelfType;

use proc_macro2::TokenStream;
use quote::quote;

use std::{
boxed::Box,
Expand Down Expand Up @@ -44,146 +41,22 @@ impl SelfKind {
}
}

fn matchable_self(&self) -> darling::Result<TokenStream> {
let get_self = match self {
SelfKind::Owned
| SelfKind::Pointer(PointerKind::Ref)
| SelfKind::Pointer(PointerKind::MutRef) => {
quote! { self }
}
SelfKind::Pointer(PointerKind::Arc) | SelfKind::Pointer(PointerKind::Rc) => {
quote! { &*self }
}
SelfKind::Pointer(PointerKind::Box) => quote! { *self },
SelfKind::Pointer(PointerKind::Pin(p)) => {
let unpinned = quote! { unsafe { std::pin::Pin::into_inner_unchecked(self) } };
match **p {
PointerKind::Ref | PointerKind::MutRef => unpinned,
PointerKind::Rc | PointerKind::Arc => {
let panic_msg = "faux tried to get a unique instance of Self and failed";
let self_of_receiver = match **p {
PointerKind::Arc => SelfType::Arc,
PointerKind::Rc => SelfType::Rc,
_ => unreachable!(),
};
let path = self_of_receiver.path().unwrap();
quote! {{
match #path::try_unwrap(#unpinned) {
Ok(owned) => owned,
Err(_) => panic!(#panic_msg),
}
}}
}
PointerKind::Box => quote! { *#unpinned },
PointerKind::Pin(_) => {
return Err(darling::Error::custom("faux does not support nest Pins"));
}
}
}
};

Ok(get_self)
}

pub fn method_body(
&self,
self_type: SelfType,
proxy_real: TokenStream,
call_stub: TokenStream,
) -> darling::Result<syn::Expr> {
let get_self = self.matchable_self()?;

let project_real = match self.project_real(self_type) {
Ok(value) => value,
Err(value) => return value,
};

let proxy_real = quote! {
#project_real
#proxy_real
};

Ok(syn::parse_quote! {
match &self.0 {
faux::MaybeFaux::Faux(_) => { #call_stub },
_ => match #get_self {
Self(faux::MaybeFaux::Real(_maybe_faux_real)) => { #proxy_real },
Self(faux::MaybeFaux::Faux(_)) => unreachable!(),
pub fn method_body(&self, proxy_real: TokenStream, call_stub: TokenStream) -> syn::Expr {
syn::parse_quote! {{
use ::faux::MockWrapper;
let inner = self.inner();
if let Some(_) = ::faux::FauxCaller::<_>::try_as_faux(&inner) {
let wrapper = ::faux::MockWrapper::wrap(inner);
#call_stub
} else {
match ::faux::FauxCaller::<_>::try_into_real(inner) {
Some(_maybe_faux_real) => {
#proxy_real
},
None => unreachable!(),
}
}
})
}

fn project_real(&self, self_type: SelfType) -> Result<TokenStream, darling::Result<syn::Expr>> {
Ok(match (self, self_type) {
(SelfKind::Owned, SelfType::Owned)
| (SelfKind::Pointer(PointerKind::Ref), SelfType::Owned)
| (SelfKind::Pointer(PointerKind::MutRef), SelfType::Owned)
| (SelfKind::Pointer(PointerKind::Box), SelfType::Box) => quote! {},
(SelfKind::Pointer(PointerKind::Ref), _) => quote! {
let _maybe_faux_real = &*_maybe_faux_real;
},
(SelfKind::Pointer(PointerKind::MutRef), SelfType::Box) => quote! {
let _maybe_faux_real = &mut *_maybe_faux_real;
},
(SelfKind::Owned, SelfType::Box) => quote! {
let _maybe_faux_real = *_maybe_faux_real;
},
(SelfKind::Pointer(PointerKind::Box), SelfType::Owned) => quote! {
let _maybe_faux_real = std::boxed::Box::new(_maybe_faux_real);
},
(SelfKind::Pointer(PointerKind::Rc), SelfType::Rc)
| (SelfKind::Pointer(PointerKind::Arc), SelfType::Arc) => quote! {
let _maybe_faux_real = _maybe_faux_real.clone();
},
(SelfKind::Pointer(PointerKind::Rc), SelfType::Owned)
| (SelfKind::Pointer(PointerKind::Arc), SelfType::Owned) => {
let self_of_receiver = match self {
SelfKind::Pointer(PointerKind::Arc) => SelfType::Arc,
SelfKind::Pointer(PointerKind::Rc) => SelfType::Rc,
_ => unreachable!(),
};
let path = self_of_receiver.path();
let new_path = self_of_receiver.new_path().unwrap();
let panic_msg = format!("faux tried to get a unique instance of Self from and failed. Consider adding a `self_type = \"{}\"` argument to both the #[create] and #[method] attributes tagging this struct and its impl.", self_of_receiver);

quote! {
let owned = match #path::try_unwrap(self) {
Ok(owned) => owned,
Err(_) => panic!(#panic_msg),
};

let _maybe_faux_real = match owned {
Self(faux::MaybeFaux::Real(_maybe_faux_real)) => #new_path(_maybe_faux_real),
_ => unreachable!()
};
}
}
(SelfKind::Pointer(PointerKind::Pin(pointer)), SelfType::Owned) => match **pointer {
PointerKind::Ref | PointerKind::MutRef => quote! {
let _maybe_faux_real = unsafe { std::pin::Pin::new_unchecked(_maybe_faux_real) };
},
PointerKind::Box => quote! {
let _maybe_faux_real = unsafe { std::pin::Pin::new_unchecked(std::boxed::Box::new(_maybe_faux_real)) };
},
PointerKind::Rc | PointerKind::Arc => {
let self_of_receiver = match **pointer {
PointerKind::Arc => SelfType::Arc,
PointerKind::Rc => SelfType::Rc,
_ => unreachable!(),
};
let new_path = self_of_receiver.new_path().unwrap();

quote! {
let _maybe_faux_real = unsafe { std::pin::Pin::new_unchecked(#new_path(_maybe_faux_real)) };
}
}
PointerKind::Pin(_) => unreachable!(),
},
(receiver, specified) => {
return Err(Err(darling::Error::custom(format!("faux cannot convert from the receiver_type of this method: `{}`, into the self_type specified: `{}`", receiver, specified))));
}
})
}}
}
}

Expand Down

0 comments on commit 068b112

Please sign in to comment.