memlink_protocol/
response.rs1use alloc::format;
7use alloc::string::ToString;
8use alloc::vec::Vec;
9
10use crate::error::{ProtocolError, Result};
11use crate::header::MessageHeader;
12use crate::magic::MAX_PAYLOAD_SIZE;
13use crate::types::{MethodHash, ModuleId, RequestId, StatusCode};
14
15#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16pub struct Response {
17 pub header: MessageHeader,
18 pub data: Vec<u8>,
19 pub status: StatusCode,
20}
21
22impl Response {
23 pub fn success(request_id: RequestId, data: Vec<u8>) -> Self {
24 let header = MessageHeader::new(
25 crate::types::MessageType::Response,
26 request_id,
27 0,
28 0,
29 data.len() as u32,
30 );
31
32 Self {
33 header,
34 data,
35 status: StatusCode::Success,
36 }
37 }
38
39 pub fn error(request_id: RequestId, status: StatusCode, data: Vec<u8>) -> Self {
40 let header = MessageHeader::new(
41 crate::types::MessageType::Response,
42 request_id,
43 0,
44 0,
45 data.len() as u32,
46 );
47
48 Self {
49 header,
50 data,
51 status,
52 }
53 }
54
55 pub fn with_routing(
56 request_id: RequestId,
57 status: StatusCode,
58 data: Vec<u8>,
59 module_id: ModuleId,
60 method_hash: MethodHash,
61 ) -> Self {
62 let header = MessageHeader::new(
63 crate::types::MessageType::Response,
64 request_id,
65 module_id,
66 method_hash,
67 data.len() as u32,
68 );
69
70 Self {
71 header,
72 data,
73 status,
74 }
75 }
76
77 pub fn request_id(&self) -> RequestId {
78 self.header.request_id()
79 }
80
81 pub fn status(&self) -> StatusCode {
82 self.status
83 }
84
85 pub fn data(&self) -> &[u8] {
86 &self.data
87 }
88
89 pub fn is_success(&self) -> bool {
90 self.status.is_success()
91 }
92
93 pub fn is_error(&self) -> bool {
94 self.status.is_error()
95 }
96
97 pub fn into_bytes(self) -> Result<Vec<u8>> {
98 let mut bytes = Vec::new();
99
100 bytes.push(self.status.as_u8());
101
102 bytes.extend_from_slice(&(self.data.len() as u32).to_le_bytes());
103 bytes.extend_from_slice(&self.data);
104
105 if bytes.len() > MAX_PAYLOAD_SIZE {
106 return Err(ProtocolError::PayloadTooLarge(bytes.len(), MAX_PAYLOAD_SIZE));
107 }
108
109 Ok(bytes)
110 }
111
112 pub fn from_bytes(payload: &[u8], header: MessageHeader) -> Result<Self> {
113 if payload.is_empty() {
114 return Err(ProtocolError::InvalidHeader(
115 "empty payload".to_string(),
116 ));
117 }
118
119 let status_code = payload[0];
120 let status = StatusCode::from_u8(status_code).ok_or_else(|| {
121 ProtocolError::InvalidHeader(format!("unknown status code: {}", status_code))
122 })?;
123
124 if payload.len() < 5 {
125 return Err(ProtocolError::InvalidHeader(
126 "insufficient data for data length".to_string(),
127 ));
128 }
129
130 let data_len =
131 u32::from_le_bytes([payload[1], payload[2], payload[3], payload[4]]) as usize;
132
133 if payload.len() < 5 + data_len {
134 return Err(ProtocolError::InvalidHeader(
135 "insufficient data for data".to_string(),
136 ));
137 }
138
139 let data = payload[5..5 + data_len].to_vec();
140
141 Ok(Self {
142 header,
143 data,
144 status,
145 })
146 }
147}