feat: add `impl_from` argument to `#[server]` proc_macro (#2335)
* Add `impl_into` argument * Add `impl_into` argument * Revert unneeded changes * Address review comments Rename `impl_into` back to be `impl_from` Rework docstring * Fix typo in docstring
This commit is contained in:
parent
0770b87cb7
commit
aa3700ffb9
|
@ -883,6 +883,11 @@ pub fn slot(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
|||
/// - `"GetCbor"`: `GET` request with URL-encoded arguments and CBOR response
|
||||
/// - `req` and `res` specify the HTTP request and response types to be used on the server (these
|
||||
/// should usually only be necessary if you are integrating with a server other than Actix/Axum)
|
||||
/// - `impl_from`: specifies whether to implement trait `From` for server function's type or not.
|
||||
/// By default, if a server function only has one argument, the macro automatically implements the `From` trait
|
||||
/// to convert from the argument type to the server function type, and vice versa, allowing you to convert
|
||||
/// between them easily. Setting `impl_from` to `false` disables this, which can be necessary for argument types
|
||||
/// for which this would create a conflicting implementation. (defaults to `true`)
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// #[server(
|
||||
|
@ -891,6 +896,7 @@ pub fn slot(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
|||
/// endpoint = "my_fn",
|
||||
/// input = Cbor,
|
||||
/// output = Json
|
||||
/// impl_from = true
|
||||
/// )]
|
||||
/// pub async fn my_wacky_server_fn(input: Vec<String>) -> Result<usize, ServerFnError> {
|
||||
/// todo!()
|
||||
|
|
|
@ -119,6 +119,7 @@ pub fn server_macro_impl(
|
|||
res_ty,
|
||||
client,
|
||||
custom_wrapper,
|
||||
impl_from,
|
||||
} = args;
|
||||
let prefix = prefix.unwrap_or_else(|| Literal::string(default_path));
|
||||
let fn_path = fn_path.unwrap_or_else(|| Literal::string(""));
|
||||
|
@ -206,8 +207,11 @@ pub fn server_macro_impl(
|
|||
FnArg::Receiver(_) => None,
|
||||
FnArg::Typed(t) => Some((&t.pat, &t.ty)),
|
||||
});
|
||||
let from_impl =
|
||||
(body.inputs.len() == 1 && first_field.is_some()).then(|| {
|
||||
let impl_from = impl_from.map(|v| v.value).unwrap_or(true);
|
||||
let from_impl = (body.inputs.len() == 1
|
||||
&& first_field.is_some()
|
||||
&& impl_from)
|
||||
.then(|| {
|
||||
let field = first_field.unwrap();
|
||||
let (name, ty) = field;
|
||||
quote! {
|
||||
|
@ -676,6 +680,7 @@ struct ServerFnArgs {
|
|||
client: Option<Type>,
|
||||
custom_wrapper: Option<Path>,
|
||||
builtin_encoding: bool,
|
||||
impl_from: Option<LitBool>,
|
||||
}
|
||||
|
||||
impl Parse for ServerFnArgs {
|
||||
|
@ -693,6 +698,7 @@ impl Parse for ServerFnArgs {
|
|||
let mut res_ty: Option<Type> = None;
|
||||
let mut client: Option<Type> = None;
|
||||
let mut custom_wrapper: Option<Path> = None;
|
||||
let mut impl_from: Option<LitBool> = None;
|
||||
|
||||
let mut use_key_and_value = false;
|
||||
let mut arg_pos = 0;
|
||||
|
@ -800,6 +806,14 @@ impl Parse for ServerFnArgs {
|
|||
));
|
||||
}
|
||||
custom_wrapper = Some(stream.parse()?);
|
||||
} else if key == "impl_from" {
|
||||
if impl_from.is_some() {
|
||||
return Err(syn::Error::new(
|
||||
key.span(),
|
||||
"keyword argument repeated: `impl_from`",
|
||||
));
|
||||
}
|
||||
impl_from = Some(stream.parse()?);
|
||||
} else {
|
||||
return Err(lookahead.error());
|
||||
}
|
||||
|
@ -895,6 +909,7 @@ impl Parse for ServerFnArgs {
|
|||
res_ty,
|
||||
client,
|
||||
custom_wrapper,
|
||||
impl_from,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue