Could somebody explain how to fix this and make function accept only serde structs ?
I need to allow function to accept another structs with #[derive(Serialize, Deserialize)]
There is no way to restrict generic types to only structs. It's not something you should care about, either. What is your actual requirement, what are you trying to achieve with this, and why is the Serialize + Deserialize bound not sufficient?
There isn't anything in that code that would indicate to me that it would be an error to pass it something that isn't a struct if it implements your own trait or DeserializeOwned. "You must pass a struct" l'art pour l'art is not a meaningful restriction; if you merely want something that is deserializeable, use the Deserialize bound, and let users pass anything deserializable.
#[async_trait]
pub trait QueryHandler {
type Response;
fn event() -> String;
async fn handle(
sender: &mut WSSender<Compat<TcpStream>>,
receiver: &mut WSReceiver<Compat<TcpStream>>,
request: String
) -> Result<Self::Response, Error> {
sender.send_text(request).await.unwrap();
let mut response = Vec::new();
receiver.receive_data(&mut response).await.unwrap();
let response = String::from_utf8_lossy(&response).to_string();
let result = serde_json::from_str(response.as_str()).unwrap();
Ok(result)
}
}
but for now I got an error on compile:
error[E0277]: the trait bound `<Self as QueryHandler>::Response: Deserialize<'_>` is not satisfied
--> src\types\traits.rs:44:22
|
44 | let result = serde_json::from_str(response.as_str()).unwrap();
| ^^^^^^^^^^^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `<Self as QueryHandler>::Response`
|
note: required by a bound in `serde_json::from_str`
--> C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\serde_json-1.0.86\src\de.rs:2611:8
|
2611 | T: de::Deserialize<'a>,
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `serde_json::from_str`
it's not clear where should I implement Deserialize.
the trait bound `<Self as QueryHandler>::Response: Deserialize<'_>` is not satisfied
meaning you need to add a bound to Response.
type Response: serde::de::DeserializeOwned;
(I made the bound DeserializeOwned instead of Deserialize like suggested in the error message, this basically makes it so you don't have to worry about the lifetime in Deserialize<'_>. You can read more about it at Deserializer lifetimes · Serde)
By the way, there's no need to turn the response into a string before deserializing it, serde_json can deserialize from a byte array: from_slice in serde_json - Rust
You shouldn't. You are trying to use (i.e., depend on) it. So, you should indicate that all types substituted for that particular type parameter should implement Deserialize.
Rust generics are not like C++ templates. The body of a generic function is typechecked once and only once, against the constraints (i.e. trait and lifetime bounds) you explicitly put on the generic parameters. You are not allowed to rely on anything else about the types the generic type parameters stand for.
If you want to deserialize into a value of generic type, you have to put the Deserialize bound on the type parameter. If you want to clone it, you have to apply the Clone bound. If you want to compare it to values of the same type, you have to add the PartialEq bound, and so on.
The reason for this design is that it greatly improves reliability and code robustness. Library writers don't have to worry about their function not compiling when instantiated with unforeseen types. If a generic function typechecks once, it will work with any set of suitable substitutions.