I'm using Nickel.rs with MongoDB to build a RESTful api.
I'd like to implement a generic Responder
for the type mongodb::error::Result<Option<bson::Document>>
.
This is the implementation I wrote based on the examples I found for Responder
:
impl<D> Responder<D> for Result<Option<Document>> {
fn respond<'a>(self, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {
response.set(MediaType::Json);
match self {
Ok(Some(doc))=>{
ApiResponse{data: Bson::Document(doc).to_json()}.to_json()
},
Ok(None)=>{
response.set(StatusCode::NotFound);
ApiError{error: "Not found".to_string()}.to_json()
},
Err(e)=>{
response.set(StatusCode::InternalServerError);
ApiError{error: format!("{}",e)}.to_json()
}
}
}
}
and I'm getting the following error:
error: type parameter
D
must be used as the type parameter for some local type (e.g.MyStruct<T>
); only traits defined in the current crate can be implemented for a type parameter [E0210]
I ran rustc --explain E0210
for an explanation and if my understanding is correct, I need to provide a trait D
as a type argument to impl<D>
, but I don't understand which trait to provide.
I tried impl<D: =()>
but that produced the same error.
Based on starblue's answer, I replaced
ApiResponse
andApiError
with a tuple struct and refactored my code as follows:When you implement a trait then either the trait or the type you are implementing it for must be defined in the same crate. In you example that is not the case: the trait
Responder
is defined bynickel
, andResult
is defined bymongodb
.The common way to work around this is to define your own type, by wrapping the desired type into a tuple struct with a single component (the so-called newtype pattern):