1use {crate::content_types::APPLICATION_PROTOBUF,
6 axum::{http::{StatusCode,
7 header::CONTENT_TYPE},
8 response::{IntoResponse,
9 Response}},
10 prost::Message};
11
12pub struct ProtobufResponse<T>
34where
35 T: Message, {
36 status: StatusCode,
37 message: T,
38}
39
40impl<T> ProtobufResponse<T>
41where
42 T: Message,
43{
44 pub fn new(status: StatusCode, message: T) -> Self {
46 Self { status, message }
47 }
48
49 pub fn ok(message: T) -> Self {
51 Self::new(StatusCode::OK, message)
52 }
53
54 pub fn created(message: T) -> Self {
56 Self::new(StatusCode::CREATED, message)
57 }
58
59 pub fn accepted(message: T) -> Self {
61 Self::new(StatusCode::ACCEPTED, message)
62 }
63}
64
65impl<T> IntoResponse for ProtobufResponse<T>
66where
67 T: Message,
68{
69 fn into_response(self) -> Response {
70 let bytes = self.message.encode_to_vec();
71
72 (self.status, [(CONTENT_TYPE, APPLICATION_PROTOBUF)], bytes).into_response()
73 }
74}
75
76pub type ProtobufResult<T> = Result<ProtobufResponse<T>, crate::error::JetError>;
78
79pub struct NoContent;
81
82impl IntoResponse for NoContent {
83 fn into_response(self) -> Response {
84 StatusCode::NO_CONTENT.into_response()
85 }
86}
87
88pub enum MaybeProtobuf<T>
90where
91 T: Message, {
92 Some(ProtobufResponse<T>),
94 None,
96}
97
98impl<T> IntoResponse for MaybeProtobuf<T>
99where
100 T: Message,
101{
102 fn into_response(self) -> Response {
103 match self {
104 | MaybeProtobuf::Some(response) => response.into_response(),
105 | MaybeProtobuf::None => StatusCode::NO_CONTENT.into_response(),
106 }
107 }
108}
109
110pub trait IntoProtobufResponse: Message + Sized {
112 fn into_pb_response(self) -> ProtobufResponse<Self> {
114 ProtobufResponse::ok(self)
115 }
116
117 fn into_pb_response_with_status(self, status: StatusCode) -> ProtobufResponse<Self> {
119 ProtobufResponse::new(status, self)
120 }
121}
122
123impl<T: Message> IntoProtobufResponse for T {}