Skip to main content

memlink_protocol/
response.rs

1//! Response message structure.
2//!
3//! Defines Response struct with header, data payload, and StatusCode.
4//! Includes serialization and deserialization methods.
5
6use 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}