naia_shared/messages/channels/senders/
request_sender.rs

1use std::{collections::HashMap, time::Duration};
2
3use naia_derive::MessageRequest;
4use naia_serde::{BitWriter, SerdeInternal};
5
6use crate::messages::request::GlobalRequestId;
7use crate::{KeyGenerator, LocalEntityAndGlobalEntityConverterMut, MessageContainer, MessageKinds};
8
9pub struct RequestSender {
10    local_key_generator: KeyGenerator<LocalRequestId>,
11    local_to_global_ids: HashMap<LocalRequestId, GlobalRequestId>,
12}
13
14impl RequestSender {
15    pub fn new() -> Self {
16        Self {
17            local_key_generator: KeyGenerator::new(Duration::from_secs(60)),
18            local_to_global_ids: HashMap::new(),
19        }
20    }
21
22    pub(crate) fn process_outgoing_request(
23        &mut self,
24        message_kinds: &MessageKinds,
25        converter: &mut dyn LocalEntityAndGlobalEntityConverterMut,
26        global_request_id: GlobalRequestId,
27        request: MessageContainer,
28    ) -> MessageContainer {
29        let local_request_id = self.local_key_generator.generate();
30        self.local_to_global_ids
31            .insert(local_request_id, global_request_id);
32
33        let mut writer = BitWriter::with_max_capacity();
34        request.write(message_kinds, &mut writer, converter);
35        let request_bytes = writer.to_bytes();
36        let request_message = RequestOrResponse::request(local_request_id, request_bytes);
37        MessageContainer::from_write(Box::new(request_message), converter)
38    }
39
40    pub(crate) fn process_outgoing_response(
41        &mut self,
42        message_kinds: &MessageKinds,
43        converter: &mut dyn LocalEntityAndGlobalEntityConverterMut,
44        local_response_id: LocalResponseId,
45        response: MessageContainer,
46    ) -> MessageContainer {
47        let mut writer = BitWriter::with_max_capacity();
48        response.write(message_kinds, &mut writer, converter);
49        let response_bytes = writer.to_bytes();
50        let response_message = RequestOrResponse::response(local_response_id, response_bytes);
51        MessageContainer::from_write(Box::new(response_message), converter)
52    }
53
54    pub(crate) fn process_incoming_response(
55        &mut self,
56        local_request_id: &LocalRequestId,
57    ) -> Option<GlobalRequestId> {
58        self.local_key_generator.recycle_key(local_request_id);
59        self.local_to_global_ids.remove(local_request_id)
60    }
61}
62
63#[derive(MessageRequest)]
64pub struct RequestOrResponse {
65    id: LocalRequestOrResponseId,
66    bytes: Box<[u8]>,
67}
68
69impl RequestOrResponse {
70    pub fn request(id: LocalRequestId, bytes: Box<[u8]>) -> Self {
71        Self {
72            id: id.to_req_res_id(),
73            bytes,
74        }
75    }
76
77    pub fn response(id: LocalResponseId, bytes: Box<[u8]>) -> Self {
78        Self {
79            id: id.to_req_res_id(),
80            bytes,
81        }
82    }
83
84    pub(crate) fn to_id_and_bytes(self) -> (LocalRequestOrResponseId, Box<[u8]>) {
85        (self.id, self.bytes)
86    }
87}
88
89#[derive(Clone, PartialEq, Eq, SerdeInternal)]
90pub enum LocalRequestOrResponseId {
91    Request(LocalRequestId),
92    Response(LocalResponseId),
93}
94
95impl LocalRequestOrResponseId {
96    pub fn is_request(&self) -> bool {
97        match self {
98            LocalRequestOrResponseId::Request(_) => true,
99            LocalRequestOrResponseId::Response(_) => false,
100        }
101    }
102
103    pub fn is_response(&self) -> bool {
104        match self {
105            LocalRequestOrResponseId::Request(_) => false,
106            LocalRequestOrResponseId::Response(_) => true,
107        }
108    }
109
110    pub fn to_request_id(&self) -> LocalRequestId {
111        match self {
112            LocalRequestOrResponseId::Request(id) => *id,
113            LocalRequestOrResponseId::Response(_) => {
114                panic!("LocalRequestOrResponseId is a response")
115            }
116        }
117    }
118
119    pub fn to_response_id(&self) -> LocalResponseId {
120        match self {
121            LocalRequestOrResponseId::Request(_) => panic!("LocalRequestOrResponseId is a request"),
122            LocalRequestOrResponseId::Response(id) => *id,
123        }
124    }
125}
126
127#[derive(Clone, Copy, Eq, Hash, PartialEq, SerdeInternal)]
128pub struct LocalRequestId {
129    id: u8,
130}
131
132impl LocalRequestId {
133    pub fn to_req_res_id(&self) -> LocalRequestOrResponseId {
134        LocalRequestOrResponseId::Request(*self)
135    }
136
137    pub fn receive_from_remote(&self) -> LocalResponseId {
138        LocalResponseId { id: self.id }
139    }
140}
141
142impl From<u16> for LocalRequestId {
143    fn from(id: u16) -> Self {
144        Self { id: id as u8 }
145    }
146}
147
148impl Into<u16> for LocalRequestId {
149    fn into(self) -> u16 {
150        self.id as u16
151    }
152}
153
154#[derive(Clone, Copy, Eq, Hash, PartialEq, SerdeInternal)]
155pub struct LocalResponseId {
156    id: u8,
157}
158
159impl LocalResponseId {
160    pub fn to_req_res_id(&self) -> LocalRequestOrResponseId {
161        LocalRequestOrResponseId::Response(*self)
162    }
163
164    pub fn receive_from_remote(&self) -> LocalRequestId {
165        LocalRequestId { id: self.id }
166    }
167}