axol 0.2.0

Axol Web Framework
use crate::{IntoResponse, IntoResponseParts, Result, grpc::StatusMessage};
use axol_http::{Body, header::HeaderMap, response::Response};
use prost::Message;

use super::{AcceptEncoding, Encoding, Grpc, GrpcContentType, Metadata, Status};

#[derive(Default, Debug)]
pub struct GrpcResponse<T: Message + Default> {
    pub content_type: GrpcContentType,
    pub message_encoding: Encoding,
    pub message_accept_encoding: Option<AcceptEncoding>,
    pub header_metadata: Metadata,
    pub body: T,
    pub trailer_metadata: Metadata,
    pub status: Status,
    pub status_message: Option<String>,
}

impl<T: Message + Default> IntoResponse for GrpcResponse<T> {
    fn into_response(self) -> Result<Response> {
        let mut out = Grpc {
            content_type: self.content_type,
            encoding: self.message_encoding,
            body: self.body,
        }
        .into_response()?;
        let Body::Bytes(body) = std::mem::take(&mut out.body) else {
            panic!("Grpc encode did not return a Body::Bytes");
        };
        if let Some(message_accept_encoding) = &self.message_accept_encoding {
            out.headers.insert_typed(message_accept_encoding);
        }
        self.header_metadata
            .into_response_parts(&mut out.parts_mut())?;
        let mut trailers = HeaderMap::new();
        trailers.insert_typed(&self.status);
        out.extensions.insert(self.status);
        let status_message = self.status_message.map(StatusMessage);
        if let Some(status_message) = status_message {
            trailers.insert_typed(&status_message);
            out.extensions.insert(status_message);
        }
        self.trailer_metadata.append_to(&mut trailers)?;
        out.body = Body::bytes_and_trailers(body, trailers);
        Ok(out)
    }
}