4

我正在使用 Nickel.rs 和 MongoDB 来构建一个 RESTful api。我想Responder为 type实现一个泛型mongodb::error::Result<Option<bson::Document>>

这是我根据我找到的示例编写的实现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()
            }

        }
    }
}

我收到以下错误:

错误:类型参数D必须用作某些本地类型的类型参数(例如MyStruct<T>);只能为类型参数实现当前 crate 中定义的特征 [E0210]

我跑去rustc --explain E0210解释,如果我的理解是正确的,我需要提供一个特征D作为类型参数impl<D>,但我不明白要提供哪个特征。

我试过impl<D: =()>了,但这产生了同样的错误。

4

2 回答 2

4

当您实现一个 trait时,必须在同一个 crate 中定义该 trait 或您为其实现它的类型。在您的示例中,情况并非如此:特征Responder由 定义nickel,并且Result由 定义mongodb

解决此问题的常用方法是定义您自己的类型,通过将所需类型包装到具有单个组件的元组结构中(所谓的newtype 模式):

struct Result(mongodb::error::Result<Option<Document>>);

impl Responder for Result {
    ...
于 2016-02-12T15:25:18.047 回答
1

根据starblue的回答,我用一个元组结构替换ApiResponseApiError重构了我的代码,如下所示:

struct ApiResponse<T>(T);

impl<D> Responder<D> for ApiResponse<Result<Option<Document>>> {

    fn respond<'a>(self, mut response: Response<'a, D>) -> MiddlewareResult<'a, D> {

        let mut d = BTreeMap::new();
        match self.0 {
            Ok(Some(doc))=>{
                d.insert("data".to_string(),Bson::Document(doc).to_json());
            },
            Ok(None)=>{
                response.set(StatusCode::NotFound);
                d.insert("error".to_string(),"Not Found".to_json());
            },
            Err(e)=>{
                response.set(StatusCode::InternalServerError);
                d.insert("error".to_string(),format!("{}",e).to_json());
            }

        }
        response.set(MediaType::Json);
        response.send(Json::Object(d))
    }
}
于 2016-02-15T15:44:42.717 回答