dcl_rpc/rpc_protocol/
parse.rs1use super::{fill_remote_error, RemoteError, RpcMessageHeader, RpcMessageTypes};
3use prost::Message;
4
5pub fn build_message_identifier(message_type: u32, message_number: u32) -> u32 {
13 ((message_type & 0xf) << 27) | (message_number & 0x07ffffff)
14}
15
16pub fn parse_message_identifier(value: u32) -> (u32, u32) {
20 ((value >> 27) & 0xf, value & 0x07ffffff)
21}
22
23pub fn parse_header(data: &[u8]) -> Option<(RpcMessageTypes, u32)> {
26 let message_header = RpcMessageHeader::decode(data).ok()?;
27 let (message_type, message_number) =
28 parse_message_identifier(message_header.message_identifier);
29 let rpc_message_type = RpcMessageTypes::from_i32(message_type as i32)?;
30 Some((rpc_message_type, message_number))
31}
32
33#[derive(Debug)]
35pub enum ParseErrors {
36 IsARemoteError((u32, RemoteError)),
38 DecodingFailed,
40 NotMessageType,
44 InvalidHeader,
48}
49
50type ParseMessageResult<R> = Result<(u32, u32, R), ParseErrors>;
51
52pub fn parse_protocol_message<R: Message + Default>(data: &[u8]) -> ParseMessageResult<R> {
65 let (message_type, message_number) = match parse_header(data) {
66 Some(header) => header,
67 None => return Err(ParseErrors::InvalidHeader),
68 };
69
70 if matches!(message_type, RpcMessageTypes::RemoteErrorResponse) {
71 match RemoteError::decode(data) {
72 Ok(remote_error) => {
73 return Err(ParseErrors::IsARemoteError((message_number, remote_error)))
74 }
75 Err(_) => {
76 let mut remote_error_default = RemoteError::default();
77 fill_remote_error(&mut remote_error_default, message_number);
78
79 return Err(ParseErrors::IsARemoteError((
80 message_number,
81 remote_error_default,
82 )));
83 }
84 }
85 }
86
87 if matches!(
88 message_type,
89 RpcMessageTypes::Empty | RpcMessageTypes::ServerReady
90 ) {
91 return Err(ParseErrors::NotMessageType);
92 }
93
94 let message = R::decode(data);
95
96 match message {
97 Ok(message) => Ok((message_type as u32, message_number, message)),
98 Err(_) => Err(ParseErrors::DecodingFailed),
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use crate::rpc_protocol::*;
105 use prost::Message;
106
107 use super::{build_message_identifier, parse_protocol_message};
108
109 #[test]
110 fn test_parse_protocol_message() {
111 let port = CreatePort {
112 message_identifier: build_message_identifier(RpcMessageTypes::CreatePort as u32, 1),
113 port_name: "port_name".to_string(),
114 };
115
116 let vec = port.encode_to_vec();
117
118 let parse_back = parse_protocol_message::<CreatePortResponse>(&vec).unwrap();
119
120 assert_eq!(parse_back.0, RpcMessageTypes::CreatePort as u32);
121 assert_eq!(parse_back.2.port_id, 0);
123 }
124
125 #[test]
126 fn test_remote_error_in_parse_protocol_message() {
127 let remote_error = RemoteError {
128 message_identifier: build_message_identifier(
129 RpcMessageTypes::RemoteErrorResponse as u32,
130 1,
131 ),
132 error_code: 400,
133 error_message: "Bad request error".to_string(),
134 };
135 let vec = remote_error.encode_to_vec();
136
137 let parse_back = parse_protocol_message::<CreatePortResponse>(&vec).unwrap_err();
138 match parse_back {
139 parse::ParseErrors::IsARemoteError((message_number, remote_error_produced)) => {
140 assert_eq!(message_number, 1);
141 assert_eq!(remote_error, remote_error_produced);
142 }
143 _ => panic!(),
144 }
145 }
146}