use actix_web::{HttpResponse, Responder};
use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct ApiResponse<T: Serialize> {
pub success: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<T>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
impl<T: Serialize> ApiResponse<T> {
pub fn ok(data: T) -> Self {
Self {
success: true,
data: Some(data),
error: None,
}
}
pub fn error(msg: impl Into<String>) -> Self {
Self {
success: false,
data: None,
error: Some(msg.into()),
}
}
}
impl<T: Serialize> Responder for ApiResponse<T> {
type Body = actix_web::body::BoxBody;
fn respond_to(self, _req: &actix_web::HttpRequest) -> HttpResponse<Self::Body> {
if self.success {
HttpResponse::Ok().json(self)
} else {
HttpResponse::InternalServerError().json(self)
}
}
}
#[derive(Debug)]
pub struct TypedResponse<T: Serialize> {
status: actix_web::http::StatusCode,
data: T,
}
impl<T: Serialize> TypedResponse<T> {
pub fn new(status: actix_web::http::StatusCode, data: T) -> Self {
Self { status, data }
}
pub fn ok(data: T) -> Self {
Self::new(actix_web::http::StatusCode::OK, data)
}
pub fn created(data: T) -> Self {
Self::new(actix_web::http::StatusCode::CREATED, data)
}
}
impl<T: Serialize> Responder for TypedResponse<T> {
type Body = actix_web::body::BoxBody;
fn respond_to(self, _req: &actix_web::HttpRequest) -> HttpResponse<Self::Body> {
HttpResponse::build(self.status).json(self.data)
}
}