//! Module to help converting various types into an ApiOutput, mostly required to support use serde_json::json; use super::{ApiOutput, ApiType}; /// Helper trait to convert a variable into an API output. /// /// If an API method returns a `String`, we want it to be jsonified into `{"data": result}` and /// wrapped in a `http::Response` with a status code of `200`, but if an API method returns a /// `http::Response`, we don't want that, our wrappers produced by the `#[api]` macro simply call /// `output.into_api_output()`, and the trait implementation decides how to proceed. pub trait IntoApiOutput { fn into_api_output(self) -> ApiOutput; } impl IntoApiOutput for T where Body: 'static, T: ApiType + serde::Serialize, Body: From, { /// By default, any serializable type is serialized into a `{"data": output}` json structure, /// and returned as http status 200. fn into_api_output(self) -> ApiOutput { let output = serde_json::to_value(self)?; let res = json!({ "data": output }); let output = serde_json::to_string(&res)?; Ok(http::Response::builder() .status(200) .header("content-type", "application/json") .body(Body::from(output))?) } } /// Methods returning `ApiOutput` (which is a `Result, Error>`) don't need /// anything to happen to the value anymore, return the result as is: impl IntoApiOutput> for ApiOutput { fn into_api_output(self) -> ApiOutput { self } } /// Methods returning a `http::Response` (without the `Result<_, Error>` around it) need to be /// wrapped in a `Result`, as we do apply a `?` operator on our methods. impl IntoApiOutput> for http::Response { fn into_api_output(self) -> ApiOutput { Ok(self) } }