1use bytes::{BufMut, Bytes, BytesMut};
3use http::status::InvalidStatusCode;
4use prost::Message;
5
6pub trait CodeExt {
7 fn from_u16(code: u16) -> Result<tonic::Code, InvalidStatusCode>;
9 fn from_http(status_code: http::StatusCode) -> tonic::Code;
11}
12
13impl CodeExt for tonic::Code {
14 fn from_u16(code: u16) -> Result<tonic::Code, InvalidStatusCode> {
15 let status_code = http::StatusCode::from_u16(code)?;
16 Ok(tonic::Code::from_http(status_code))
17 }
18
19 fn from_http(status_code: http::StatusCode) -> tonic::Code {
20 match status_code {
21 http::StatusCode::INTERNAL_SERVER_ERROR => tonic::Code::Internal,
22 http::StatusCode::UNPROCESSABLE_ENTITY | http::StatusCode::BAD_REQUEST => {
23 tonic::Code::InvalidArgument
24 }
25 http::StatusCode::UNAUTHORIZED => tonic::Code::Unauthenticated,
26 http::StatusCode::FORBIDDEN => tonic::Code::PermissionDenied,
27 http::StatusCode::NOT_FOUND => tonic::Code::NotFound,
28 http::StatusCode::NOT_IMPLEMENTED => tonic::Code::Unimplemented,
29 http::StatusCode::TOO_MANY_REQUESTS
30 | http::StatusCode::BAD_GATEWAY
31 | http::StatusCode::SERVICE_UNAVAILABLE
32 | http::StatusCode::GATEWAY_TIMEOUT => tonic::Code::Unavailable,
33 http::StatusCode::OK => tonic::Code::Ok,
34 _ => tonic::Code::Unknown,
35 }
36 }
37}
38
39pub trait MessageExt {
40 fn to_bytes(&self) -> Bytes;
42}
43
44impl<T: Message> MessageExt for T {
45 fn to_bytes(&self) -> Bytes {
46 let mut buf = BytesMut::with_capacity(256);
47 buf.reserve(5);
48 unsafe {
49 buf.advance_mut(5);
50 }
51 self.encode(&mut buf).unwrap();
52 {
53 let len = buf.len() - 5;
54 let mut buf = &mut buf[..5];
55 buf.put_u8(0); buf.put_u32(len as u32);
57 }
58 buf.freeze()
59 }
60}