rekt_common/datagrams/
topic_request.rs

1use crate::enums::datagram_type::DatagramType;
2use crate::enums::topic_action::TopicAction;
3use crate::enums::topic_response::TopicResponse;
4use crate::libs::types::{Size, TopicId};
5use crate::libs::utils::{get_bytes_from_slice, get_u16_at_pos, get_u64_at_pos};
6
7//===== Sent to subscribe/unsubscribe to a topic
8pub struct DtgTopicRequest {
9    pub datagram_type: DatagramType, // 1 byte
10    pub flag: TopicAction, // 1 byte
11    pub topic_id: TopicId, // 8 bytes
12}
13
14//===== Sent to subscribe a topic
15impl DtgTopicRequest {
16    pub fn new(action: TopicAction, topic_id: TopicId) -> DtgTopicRequest {
17        DtgTopicRequest {
18            datagram_type: DatagramType::TopicRequest,
19            flag: action,
20            topic_id
21        }
22    }
23
24    pub fn as_bytes(&self) -> Vec<u8>
25    {
26        let mut bytes: Vec<u8> = Vec::with_capacity(10);
27        bytes.push(u8::from(self.datagram_type));
28        bytes.push(u8::from(self.flag));
29        bytes.extend(self.topic_id.to_le_bytes());
30        return bytes;
31    }
32}
33
34impl<'a> TryFrom<&'a [u8]> for DtgTopicRequest{
35    type Error = &'a str;
36
37    fn try_from(buffer: &'a [u8]) -> Result<Self, Self::Error> {
38        if buffer.len() < 10 {
39            return Err("Payload len is to short for a DtgTopicRequest.");
40        }
41        let topic_id = get_u64_at_pos(buffer, 2)?;
42
43        Ok(DtgTopicRequest {
44            datagram_type: DatagramType::from(buffer[0]),
45            flag: TopicAction::from(buffer[1]),
46            topic_id
47        })
48    }
49}
50
51//===== Sent to acknowledge a TOPIC_REQUEST
52pub struct DtgTopicRequestAck {
53    pub datagram_type: DatagramType,
54    pub flag: TopicResponse,
55    pub topic_id: TopicId,
56}
57
58impl DtgTopicRequestAck {
59    pub const fn new(topic_id: TopicId, status: TopicResponse) -> DtgTopicRequestAck {
60        DtgTopicRequestAck {
61            datagram_type: DatagramType::TopicRequestAck,
62            flag: status,
63            topic_id
64        }
65    }
66
67    pub fn as_bytes(&self) -> Vec<u8>
68    {
69        let mut bytes: Vec<u8> = Vec::with_capacity(10);
70        bytes.push(u8::from(self.datagram_type));
71        bytes.push(u8::from(self.flag));
72        bytes.extend(self.topic_id.to_le_bytes());
73        return bytes;
74    }
75}
76
77impl<'a> TryFrom<&'a [u8]> for DtgTopicRequestAck{
78    type Error = &'a str;
79
80    fn try_from(buffer: &'a [u8]) -> Result<Self, Self::Error> {
81        if buffer.len() < 10 {
82            return Err("Payload len is to short for a DtgTopicRequestAck.");
83        }
84        let topic_id = get_u64_at_pos(buffer, 2)?;
85
86        Ok(DtgTopicRequestAck {
87            datagram_type: DatagramType::from(buffer[0]),
88            flag: TopicResponse::from(buffer[1]),
89            topic_id
90        })
91    }
92}
93
94pub struct DtgTopicRequestNack {
95    pub datagram_type: DatagramType,
96    pub flag: TopicResponse,
97    pub size: Size,
98    pub payload: Vec<u8>
99}
100
101impl DtgTopicRequestNack{
102
103    pub fn new(status: TopicResponse, error_message: &str) -> DtgTopicRequestNack {
104        let size = error_message.len() as Size; // string length + 1 for the action
105        DtgTopicRequestNack {
106            datagram_type: DatagramType::TopicRequestNack,
107            flag: status,
108            size,
109            payload: error_message.as_bytes().into()
110        }
111    }
112
113    pub fn as_bytes(&self) -> Vec<u8>
114    {
115        let mut bytes: Vec<u8> = Vec::with_capacity(4 + self.size as usize);
116        bytes.push(u8::from(self.datagram_type));
117        bytes.push(u8::from(self.flag));
118        bytes.extend(self.size.to_le_bytes());
119        bytes.extend(self.payload.iter());
120
121        return bytes;
122    }
123}
124
125impl<'a> TryFrom<&'a [u8]> for DtgTopicRequestNack{
126    type Error = &'a str;
127
128    fn try_from(buffer: &'a [u8]) -> Result<Self, Self::Error> {
129        if buffer.len() < 10 {
130            return Err("Payload len is to short for a DtgTopicRequestNack.");
131        }
132        let size = get_u16_at_pos(buffer, 2)?;
133
134        Ok(DtgTopicRequestNack {
135            datagram_type: DatagramType::from(buffer[0]),
136            flag: TopicResponse::from(buffer[1]),
137            size,
138            payload: get_bytes_from_slice(buffer, 4, (4 + size-1) as usize)
139        })
140    }
141}