use std::error::Error;
use std::fmt::{Debug, Display};
use log::error;
use serde::{Serialize,Deserialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct ApiResp {
success: bool,
code: i32,
message: String,
data: Option<serde_json::Value>,
}
impl ApiResp {
pub fn is_success(&self) -> bool { self.success }
pub fn get_code(&self) -> i32 { self.code }
pub fn get_message(&self) -> &String { &self.message }
pub fn get_data(&self) -> &Option<serde_json::Value> { &self.data }
pub fn to_json(&self) -> String {
match serde_json::to_string(&self) {
Ok(json) => json,
Err(e) => {
error!("序列化json字符串时出错!{}", e);
let err_resp = ApiResp::error(-1, "处理响应结果时出错!".to_string());
serde_json::to_string(&err_resp).unwrap()
}
}
}
}
impl ApiResp {
pub fn success(data: serde_json::Value) -> ApiResp {
ApiResp {
success: true,
code: 0,
message: "".to_string(),
data: Some(data),
}
}
pub fn suc() -> ApiResp {
ApiResp {
success: true,
code: 0,
message: "".to_string(),
data: None,
}
}
pub fn error(code: i32, message: String) -> ApiResp {
ApiResp {
success: false,
code,
message,
data: None,
}
}
}
pub type DaoResult = Result<ApiResp, Box<dyn Error>>;
pub trait TransformResult {
fn to_json_str<T>(self, err_log: T) -> String where T: Debug + Display;
}
impl TransformResult for DaoResult {
fn to_json_str<T>(self, err_log: T) -> String where T: Debug + Display {
let ret: ApiResp = match self {
Ok(r) => r,
Err(e) => {
error!("{} {:?}", err_log, e);
ApiResp::error(-1, e.to_string())
}
};
serde_json::to_string(&ret).unwrap()
}
}
#[macro_export]
macro_rules! rollback {
($resp: expr, $tx: expr, $code: expr) => {
if let Err(e) = $resp {
$tx.rollback().await?;
return Ok(ApiResp::error($code, e.to_string()));
}
};
}
#[macro_export]
macro_rules! rollback_for_no_match {
($resp: expr, $tx: expr, $code: expr) => {
match $resp {
Err(e) => {
$tx.rollback().await?;
return Ok(ApiResp::error($code, e.to_string()));
},
Ok(r) if r.rows_affected == 0 => {
$tx.rollback().await?;
return Ok(ApiResp::error($code, "未匹配到目标记录".to_string()));
},
_ => {}
}
};
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
#[derive(Debug, Serialize, Deserialize)]
struct PingPang {
color: String,
weight: f64,
}
#[test]
fn test_resp() {
let suc_json = ApiResp::suc().to_json();
println!("suc_json: {}", suc_json);
let orig_suc: ApiResp = serde_json::from_str(suc_json.as_str()).unwrap();
assert!(orig_suc.is_success());
let vals = vec![
PingPang {color: "white".to_string(), weight: 10.0},
PingPang {color: "yellow".to_string(), weight: 11.5},
];
let suc_data = ApiResp::success(json!(vals)).to_json();
println!("suc_data: {}", suc_data);
let orig_suc_data: ApiResp = serde_json::from_str(suc_data.as_str()).unwrap();
assert!(orig_suc_data.is_success());
let fail_json = ApiResp::error(-1, String::from("交易出错了")).to_json();
println!("fail_json: {}", fail_json);
let orig_fail: ApiResp = serde_json::from_str(fail_json.as_str()).unwrap();
assert!(!orig_fail.is_success());
}
}