maviola/core/io/
routing.rs1use crate::core::io::ChannelInfo;
2use std::fmt::{Debug, Formatter};
3use std::sync::Arc;
4
5use crate::core::utils::UniqueId;
6use crate::protocol::{Frame, MaybeVersioned};
7
8#[cfg_attr(feature = "specta", derive(specta::Type))]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17#[derive(Copy, Clone, Eq, PartialEq, Hash)]
18pub struct ConnectionId(UniqueId);
19
20#[derive(Copy, Clone, Eq, PartialEq, Hash)]
27pub struct ChannelId {
28 connection: ConnectionId,
29 channel: UniqueId,
30}
31
32#[derive(Clone, Debug)]
34pub struct IncomingFrame<V: MaybeVersioned> {
35 frame: Frame<V>,
36 channel: ChannelInfo,
37}
38
39#[derive(Clone, Debug)]
41pub struct OutgoingFrame<V: MaybeVersioned> {
42 frame: Arc<Frame<V>>,
43 scope: BroadcastScope,
44}
45
46#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
48pub enum BroadcastScope {
49 #[default]
51 All,
52 ExactChannel(ChannelId),
54 ExceptChannel(ChannelId),
56 ExceptChannelWithin(ChannelId),
58 ExactConnection(ConnectionId),
60 ExceptConnection(ConnectionId),
62}
63
64impl ConnectionId {
65 pub(crate) fn new() -> Self {
67 Self(UniqueId::new())
68 }
69
70 #[inline(always)]
72 pub fn contains(&self, channel_id: ChannelId) -> bool {
73 &channel_id.connection == self
74 }
75}
76
77impl ChannelId {
78 pub(crate) fn new(connection_id: ConnectionId) -> Self {
81 Self {
82 connection: connection_id,
83 channel: UniqueId::new(),
84 }
85 }
86
87 pub fn connection_id(&self) -> ConnectionId {
89 self.connection
90 }
91
92 #[inline(always)]
94 pub fn belongs_to(&self, connection_id: ConnectionId) -> bool {
95 connection_id.contains(*self)
96 }
97}
98
99impl Debug for ConnectionId {
100 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
101 f.debug_tuple("ConnectionId").finish()
102 }
103}
104
105impl Debug for ChannelId {
106 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
107 f.debug_tuple("ChannelId").finish()
108 }
109}
110
111impl From<ConnectionId> for ChannelId {
112 fn from(value: ConnectionId) -> Self {
113 Self::new(value)
114 }
115}
116
117impl<V: MaybeVersioned> IncomingFrame<V> {
118 pub fn new(frame: Frame<V>, channel: ChannelInfo) -> Self {
120 Self { frame, channel }
121 }
122}
123
124impl<V: MaybeVersioned> From<IncomingFrame<V>> for (Frame<V>, ChannelInfo) {
125 fn from(value: IncomingFrame<V>) -> Self {
126 (value.frame, value.channel)
127 }
128}
129
130impl<V: MaybeVersioned> OutgoingFrame<V> {
131 pub fn new(frame: Frame<V>) -> Self {
133 Self {
134 frame: Arc::new(frame),
135 scope: BroadcastScope::All,
136 }
137 }
138
139 pub(crate) fn scoped(frame: Frame<V>, scope: BroadcastScope) -> Self {
140 Self {
141 frame: Arc::new(frame),
142 scope,
143 }
144 }
145
146 #[inline]
148 pub fn frame(&self) -> &Frame<V> {
149 self.frame.as_ref()
150 }
151
152 #[inline]
154 pub fn scope(&self) -> BroadcastScope {
155 self.scope
156 }
157
158 #[inline]
160 pub(crate) fn set_scope(&mut self, scope: BroadcastScope) {
161 self.scope = scope;
162 }
163
164 pub(crate) fn matches_connection_reroute(&mut self, connection_id: ConnectionId) -> bool {
175 match self.scope() {
176 BroadcastScope::ExceptConnection(conn_id) if connection_id == conn_id => false,
177 BroadcastScope::ExactConnection(conn_id) if connection_id == conn_id => {
178 self.set_scope(BroadcastScope::All);
179 true
180 }
181 _ => true,
182 }
183 }
184
185 pub(crate) fn should_send_to(&self, channel_id: ChannelId) -> bool {
186 match self.scope {
187 BroadcastScope::All => true,
188 BroadcastScope::ExactChannel(sender_id) => sender_id == channel_id,
189 BroadcastScope::ExceptChannel(sender_id) => sender_id != channel_id,
190 BroadcastScope::ExceptChannelWithin(sender_id) => {
191 channel_id.connection_id().contains(sender_id) && sender_id != channel_id
192 }
193 BroadcastScope::ExactConnection(conn_id) => conn_id.contains(channel_id),
194 BroadcastScope::ExceptConnection(conn_id) => !conn_id.contains(channel_id),
195 }
196 }
197}
198
199impl<V: MaybeVersioned> From<OutgoingFrame<V>> for Frame<V> {
200 fn from(value: OutgoingFrame<V>) -> Self {
201 value.frame.as_ref().clone()
202 }
203}