use bytes::Bytes;
use http::HeaderMap;
use http_body_util::BodyExt;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::server::{NgynContext, NgynResponse, Transformer};
#[derive(Serialize, Deserialize)]
pub struct JsonResponse<D: Serialize, E: Serialize> {
data: Option<D>,
error: Option<E>,
}
impl<D: Serialize, E: Serialize> JsonResponse<D, E> {
pub fn new(data: Option<D>, error: Option<E>) -> Self {
Self { data, error }
}
pub fn data(&self) -> Option<&D> {
self.data.as_ref()
}
pub fn error(&self) -> Option<&E> {
self.error.as_ref()
}
}
pub type JsonResult = Result<Value, Value>;
impl<'a> Transformer<'a> for &'a NgynResponse {
fn transform(cx: &'a mut NgynContext) -> Self {
cx.response_mut()
}
}
impl<'a> Transformer<'a> for &'a mut NgynResponse {
fn transform(cx: &'a mut NgynContext) -> Self {
cx.response_mut()
}
}
impl<'a> Transformer<'a> for &'a HeaderMap {
fn transform(cx: &'a mut NgynContext) -> Self {
cx.response_mut().headers()
}
}
impl<'a> Transformer<'a> for &'a mut HeaderMap {
fn transform(cx: &'a mut NgynContext) -> Self {
cx.response_mut().headers_mut()
}
}
pub trait ReadBytes {
#[allow(async_fn_in_trait)]
async fn read_bytes(&mut self) -> Result<Bytes, Box<dyn std::error::Error>>;
}
impl ReadBytes for NgynResponse {
async fn read_bytes(&mut self) -> Result<Bytes, Box<dyn std::error::Error>> {
let frame = self.frame().await;
if let Some(Ok(frame)) = frame {
if let Ok(bytes) = frame.into_data() {
return Ok(bytes);
}
}
Err("No response bytes has been set".into())
}
}
pub trait PeekBytes {
#[allow(async_fn_in_trait)]
async fn peek_bytes(&mut self, f: impl FnMut(&Bytes));
}
impl PeekBytes for NgynResponse {
async fn peek_bytes(&mut self, mut f: impl FnMut(&Bytes)) {
if let Ok(bytes) = self.read_bytes().await {
f(&bytes);
*self.body_mut() = bytes.into();
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let response = JsonResponse::new(Some("data"), Some("error"));
assert_eq!(response.data(), Some(&"data"));
assert_eq!(response.error(), Some(&"error"));
}
#[test]
fn test_data() {
let response: JsonResponse<&str, &str> = JsonResponse::new(Some("data"), None);
assert_eq!(response.data(), Some(&"data"));
assert_eq!(response.error(), None);
}
#[test]
fn test_error() {
let response: JsonResponse<&str, &str> = JsonResponse::new(None, Some("error"));
assert_eq!(response.data(), None);
assert_eq!(response.error(), Some(&"error"));
}
#[tokio::test]
async fn test_peek_bytes() {
let mut response = NgynResponse::default();
let body = Bytes::from("Hello, world!");
*response.body_mut() = body.clone().into();
let mut bytes = Vec::new();
let peek_fn = |data: &Bytes| {
bytes.extend_from_slice(data);
};
response.peek_bytes(peek_fn).await;
assert_eq!(bytes, body);
}
#[tokio::test]
async fn test_read_bytes() {
let mut response = NgynResponse::default();
let body = Bytes::from("Hello, world!");
*response.body_mut() = body.clone().into();
let bytes = response.read_bytes().await.unwrap();
assert_eq!(bytes, body);
}
}