use serde::Serialize;
use crate::profusegw_response::{ProfuseGwCode, ProfuseGwResponse};
const PREFIX: &[u8] = b"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: ";
const SUFFIX: &[u8] = b"\r\nConnection: close\r\n\r\n";
#[doc(hidden)]
pub fn encode_profusegw_http1<Data, Code>(
response: &ProfuseGwResponse<Data, Code>,
) -> Result<Vec<u8>, serde_json::Error>
where
Data: Serialize,
Code: ProfuseGwCode,
{
let body = serde_json::to_vec(response)?;
let length = body.len().to_string();
let mut framed = Vec::with_capacity(PREFIX.len() + length.len() + SUFFIX.len() + body.len());
framed.extend_from_slice(PREFIX);
framed.extend_from_slice(length.as_bytes());
framed.extend_from_slice(SUFFIX);
framed.extend_from_slice(&body);
Ok(framed)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::profusegw_response::{
FailureMessage, ProfuseGwCode, ProfuseGwFailure, ProfuseGwResponse,
};
#[derive(Serialize)]
struct Data {
count: u64,
}
enum Code {
Rejected,
}
impl ProfuseGwCode for Code {
const REGISTERED_CODES: &'static [&'static str] = &["ACCOUNT_REJECTED"];
fn stable_code(&self) -> &'static str {
"ACCOUNT_REJECTED"
}
}
#[test]
fn legal_branches_share_exact_json_http_200_projection() {
let success = ProfuseGwResponse::<_, Code>::success(Data { count: 7 });
assert_eq!(
encode_profusegw_http1(&success).unwrap(),
b"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 35\r\nConnection: close\r\n\r\n{\"success\":true,\"data\":{\"count\":7}}"
);
let failure = ProfuseGwResponse::<Data, _>::failure(ProfuseGwFailure::new(
Code::Rejected,
FailureMessage::new("Account was rejected").unwrap(),
));
assert_eq!(
encode_profusegw_http1(&failure).unwrap(),
b"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 88\r\nConnection: close\r\n\r\n{\"success\":false,\"failure\":{\"code\":\"ACCOUNT_REJECTED\",\"message\":\"Account was rejected\"}}"
);
}
}