Skip to content

Commit

Permalink
feat: Cast deps to empty
Browse files Browse the repository at this point in the history
  • Loading branch information
jawoznia committed Aug 10, 2023
1 parent 9e42a78 commit 0932047
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 20 deletions.
27 changes: 21 additions & 6 deletions sylvia-derive/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -946,20 +946,35 @@ impl<'a> GlueMessage<'a> {
interface_names.push(quote! {&#name :: messages()});

let interfaces_cnt = interface_names.len();
let custom_query = custom.query_or_default();

let dispatch_arms = interfaces.iter().map(|interface| {
let ContractMessageAttr {
variant,
has_custom_msg,
has_custom_query,
..
} = interface;

match *has_custom_msg&& msg_ty == &MsgType::Exec
{
true => quote! { #contract_name :: #variant(msg) => Ok( #sylvia ::into_response::IntoResponse::into_response(msg.dispatch(contract, Into::into(ctx))?)?) },
false => quote! { #contract_name :: #variant(msg) => msg.dispatch(contract, Into::into(ctx)) }
}
let ctx= match (msg_ty, has_custom_query) {
(MsgType::Exec, true )=> quote! {
// ( #sylvia ::into_deps::IntoDepsMut::into_deps_mut(&mut ctx.0), ctx.1, ctx.2)
( <&mut #sylvia ::cw_std::DepsMut< #custom_query > as #sylvia ::into_deps::IntoDepsMut<#sylvia ::cw_std::Empty>>::into_deps_mut(&mut ctx.0), ctx.1, ctx.2)
},
(MsgType::Query, true )=> quote! {
( #sylvia ::into_deps::IntoDeps::into_deps(&ctx.0), ctx.1)
},
_=> quote! { ctx },
};

match (msg_ty, has_custom_msg) {
(MsgType::Exec, true) => quote! {
#contract_name :: #variant(msg) => #sylvia ::into_response::IntoResponse::into_response(msg.dispatch(contract, Into::into( #ctx ))?)
},
_ => quote! {
#contract_name :: #variant(msg) => msg.dispatch(contract, Into::into( #ctx ))
},
}
});

let dispatch_arm = quote! {#contract_name :: #contract (msg) =>msg.dispatch(contract, ctx)};
Expand Down Expand Up @@ -1042,7 +1057,7 @@ impl<'a> GlueMessage<'a> {
pub fn dispatch(
self,
contract: &#contract,
ctx: #ctx_type,
mut ctx: #ctx_type,
) -> #ret_type {
const _: () = {
let msgs: [&[&str]; #interfaces_cnt] = [#(#interface_names),*];
Expand Down
47 changes: 36 additions & 11 deletions sylvia-derive/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ pub struct ContractMessageAttr {
pub query_generic_params: Vec<Path>,
pub variant: Ident,
pub has_custom_msg: bool,
pub has_custom_query: bool,
}

#[cfg(not(tarpaulin_include))]
Expand All @@ -262,6 +263,35 @@ fn parse_generics(content: &ParseBuffer) -> Result<Vec<Path>> {
Ok(params)
}

fn interface_has_custom(content: ParseStream) -> Result<(bool, bool)> {
let mut has_custom_msg = false;
let mut has_custom_query = false;

let _: Token![:] = content.parse()?;
let attr: Ident = content.parse()?;
if attr != "custom" {
return Ok((has_custom_msg, has_custom_query));
}

let custom_content;
parenthesized!(custom_content in content);

while !custom_content.is_empty() {
let custom = custom_content.parse::<Path>()?;
match custom.get_ident() {
Some(ident) if ident == "msg" => has_custom_msg = true,
Some(ident) if ident == "query" => has_custom_query = true,
_ => {
return Err(Error::new(
custom.span(),
"Invalid custom attribute, expected one of: `msg`, `query`",
))
}
}
}
Ok((has_custom_msg, has_custom_query))
}

#[cfg(not(tarpaulin_include))]
// False negative. It is being called in closure
impl Parse for ContractMessageAttr {
Expand All @@ -274,7 +304,6 @@ impl Parse for ContractMessageAttr {
let generics_open: Option<Token![:]> = content.parse()?;
let mut exec_generic_params = vec![];
let mut query_generic_params = vec![];
let mut has_custom_msg = false;

if generics_open.is_some() {
loop {
Expand All @@ -300,16 +329,11 @@ impl Parse for ContractMessageAttr {
let _: Token![as] = content.parse()?;
let variant = content.parse()?;

if content.peek(Token![:]) {
let _: Token![:] = content.parse()?;
let attr: Ident = content.parse()?;
if attr == "custom" {
let custom_content;
parenthesized!(custom_content in content);
let custom = custom_content.parse::<Path>()?;
has_custom_msg = custom.is_ident("msg");
}
}
let (has_custom_msg, has_custom_query) = if content.peek(Token![:]) {
interface_has_custom(&content)?
} else {
(false, false)
};

if !content.is_empty() {
return Err(Error::new(
Expand All @@ -324,6 +348,7 @@ impl Parse for ContractMessageAttr {
query_generic_params,
variant,
has_custom_msg,
has_custom_query,
})
}
}
Expand Down
8 changes: 5 additions & 3 deletions sylvia/src/into_deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use cosmwasm_std::{CustomQuery, Deps, DepsMut, Empty, QuerierWrapper};
/// Trait converting `Deps` to one operating on another `Query` type. By default only conversions
/// from any `Deps<Q>` to `Deps<Empty>` are possible, and in general - only converting to `Deps`
/// over simpler query (being a subset of the original one) should be allowed.
trait IntoDeps<'deps, Q>
pub trait IntoDeps<'deps, Q>
where
Q: CustomQuery,
{
Expand Down Expand Up @@ -31,7 +31,7 @@ where
/// conversions from any `DepsMut<Q>` to `DepsMut<Empty>` are possible, and in general - only
/// converting to `DepsMut` over simpler query (being a subset of the original one) should be
/// allowed.
trait IntoDepsMut<'deps, Q>
pub trait IntoDepsMut<'deps, Q>
where
Q: CustomQuery,
{
Expand Down Expand Up @@ -128,6 +128,8 @@ mod tests {
api: &api,
querier,
};
let _: DepsMut<Empty> = deps.into_deps_mut();
// let _: DepsMut<Empty> = deps.into_deps_mut();
let _: DepsMut<Empty> =
<&mut DepsMut<MyQuery> as IntoDepsMut<Empty>>::into_deps_mut(&mut deps);
}
}
38 changes: 38 additions & 0 deletions sylvia/tests/custom_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,48 @@ mod associated_type_interface {
}
}

mod default_query_interface {
use cosmwasm_std::{Response, StdError, StdResult};
use sylvia::types::{ExecCtx, QueryCtx};
use sylvia::{contract, interface};

use crate::SomeResponse;

#[interface]
pub trait DefaultQueryInterface {
type Error: From<StdError>;

#[cfg(not(tarpaulin_include))]
#[msg(query)]
fn associated_query(&self, ctx: QueryCtx) -> StdResult<SomeResponse>;

#[cfg(not(tarpaulin_include))]
#[msg(exec)]
fn associated_exec(&self, ctx: ExecCtx) -> StdResult<Response>;
}

#[contract(module=super)]
#[sv::custom(query=MyQuery)]
impl DefaultQueryInterface for crate::MyContract {
type Error = StdError;

#[msg(query)]
fn associated_query(&self, _ctx: QueryCtx) -> StdResult<SomeResponse> {
Ok(SomeResponse)
}

#[msg(exec)]
fn associated_exec(&self, _ctx: ExecCtx) -> StdResult<Response> {
Ok(Response::default())
}
}
}

#[contract]
#[messages(some_interface as SomeInterface)]
#[messages(associated_type_interface as AssociatedTypeInterface)]
#[messages(interface as Interface)]
#[messages(default_query_interface as DefaultQueryInterface: custom(query))]
#[sv::custom(query=MyQuery)]
impl MyContract {
#[allow(clippy::new_without_default)]
Expand Down

0 comments on commit 0932047

Please sign in to comment.