1use crate::{metadata::MetadataMap, Extensions};
2
3#[derive(Debug)]
5pub struct Response<T> {
6 metadata: MetadataMap,
7 message: T,
8 extensions: Extensions,
9}
10
11impl<T> Response<T> {
12 pub fn new(message: T) -> Self {
25 Response {
26 metadata: MetadataMap::new(),
27 message,
28 extensions: Extensions::new(),
29 }
30 }
31
32 pub fn get_ref(&self) -> &T {
34 &self.message
35 }
36
37 pub fn get_mut(&mut self) -> &mut T {
39 &mut self.message
40 }
41
42 pub fn metadata(&self) -> &MetadataMap {
44 &self.metadata
45 }
46
47 pub fn metadata_mut(&mut self) -> &mut MetadataMap {
49 &mut self.metadata
50 }
51
52 pub fn into_inner(self) -> T {
54 self.message
55 }
56
57 pub(crate) fn into_parts(self) -> (MetadataMap, T, Extensions) {
58 (self.metadata, self.message, self.extensions)
59 }
60
61 pub(crate) fn from_parts(metadata: MetadataMap, message: T, extensions: Extensions) -> Self {
62 Self {
63 metadata,
64 message,
65 extensions,
66 }
67 }
68
69 pub(crate) fn from_http(res: http::Response<T>) -> Self {
70 let (head, message) = res.into_parts();
71 Response {
72 metadata: MetadataMap::from_headers(head.headers),
73 message,
74 extensions: Extensions::from_http(head.extensions),
75 }
76 }
77
78 pub(crate) fn into_http(self) -> http::Response<T> {
79 let mut res = http::Response::new(self.message);
80
81 *res.version_mut() = http::Version::HTTP_2;
82 *res.headers_mut() = self.metadata.into_sanitized_headers();
83 *res.extensions_mut() = self.extensions.into_http();
84
85 res
86 }
87
88 #[doc(hidden)]
89 pub fn map<F, U>(self, f: F) -> Response<U>
90 where
91 F: FnOnce(T) -> U,
92 {
93 let message = f(self.message);
94 Response {
95 metadata: self.metadata,
96 message,
97 extensions: self.extensions,
98 }
99 }
100
101 pub fn extensions(&self) -> &Extensions {
103 &self.extensions
104 }
105
106 pub fn extensions_mut(&mut self) -> &mut Extensions {
108 &mut self.extensions
109 }
110
111 #[cfg(feature = "compression")]
120 #[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
121 pub fn disable_compression(&mut self) {
122 self.extensions_mut()
123 .insert(crate::codec::compression::SingleMessageCompressionOverride::Disable);
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use crate::metadata::MetadataValue;
131
132 #[test]
133 fn reserved_headers_are_excluded() {
134 let mut r = Response::new(1);
135
136 for header in &MetadataMap::GRPC_RESERVED_HEADERS {
137 r.metadata_mut()
138 .insert(*header, MetadataValue::from_static("invalid"));
139 }
140
141 let http_response = r.into_http();
142 assert!(http_response.headers().is_empty());
143 }
144}