rosu_render/websocket/
event.rs1use bytes::Bytes;
2use serde_json::Error as SerdeError;
3
4use crate::model::{
5 CustomSkinProcessUpdate, Event, RenderAdded, RenderDone, RenderFailed, RenderProgress,
6};
7
8#[derive(Clone, Debug, PartialEq, Eq)]
29#[non_exhaustive]
30pub enum RawEvent {
31 RenderAdded(RawRenderAdded),
32 RenderDone(RawRenderDone),
33 RenderFailed(RawRenderFailed),
34 RenderProgress(RawRenderProgress),
35 CustomSkinProcessUpdate(RawCustomSkinProcessUpdate),
36}
37
38impl RawEvent {
39 pub(crate) fn from_bytes(bytes: Bytes) -> Result<Self, crate::WebsocketError> {
40 fn split_bytes(bytes: &[u8]) -> Option<(&[u8], &[u8])> {
41 let comma_idx = bytes.iter().position(|&byte| byte == b',')?;
42
43 let ([b'[', b'"', prefix @ .., b'"'], [_, suffix @ .., b']']) =
44 bytes.split_at(comma_idx)
45 else {
46 return None;
47 };
48
49 Some((prefix, suffix))
50 }
51
52 fn find_render_id(mut bytes: &[u8]) -> Option<u32> {
53 loop {
54 let idx = bytes.iter().position(|&byte| byte == b'r')?;
55
56 let Some(rest) = bytes[idx..].strip_prefix(b"renderID\":") else {
57 bytes = &bytes[idx + 1..];
58
59 continue;
60 };
61
62 rest.first().copied().filter(u8::is_ascii_digit)?;
63
64 let render_id = rest
65 .iter()
66 .copied()
67 .take_while(u8::is_ascii_digit)
68 .fold(0, |num, byte| num * 10 + u32::from(byte & 0xF));
69
70 return Some(render_id);
71 }
72 }
73
74 let Some((event, payload)) = split_bytes(&bytes) else {
75 return Err(crate::WebsocketError::InvalidEvent(bytes));
76 };
77
78 let payload_bytes = bytes.slice_ref(payload);
79
80 match event {
81 b"render_progress_json" => find_render_id(payload)
82 .map(|render_id| {
83 Self::RenderProgress(RawRenderProgress {
84 render_id,
85 bytes: payload_bytes,
86 })
87 })
88 .ok_or(crate::WebsocketError::InvalidEvent(bytes)),
89 b"render_added_json" => Ok(Self::RenderAdded(RawRenderAdded {
90 bytes: payload_bytes,
91 })),
92 b"render_done_json" => find_render_id(payload)
93 .map(|render_id| {
94 Self::RenderDone(RawRenderDone {
95 render_id,
96 bytes: payload_bytes,
97 })
98 })
99 .ok_or(crate::WebsocketError::InvalidEvent(bytes)),
100 b"render_failed_json" => find_render_id(payload)
101 .map(|render_id| {
102 Self::RenderFailed(RawRenderFailed {
103 render_id,
104 bytes: payload_bytes,
105 })
106 })
107 .ok_or(crate::WebsocketError::InvalidEvent(bytes)),
108 b"custom_skin_process_update" => {
109 Ok(Self::CustomSkinProcessUpdate(RawCustomSkinProcessUpdate {
110 bytes: payload_bytes,
111 }))
112 }
113 _ => Err(crate::WebsocketError::InvalidEvent(bytes)),
114 }
115 }
116
117 pub fn deserialize(&self) -> Result<Event, SerdeError> {
119 match self {
120 RawEvent::RenderAdded(event) => event.deserialize().map(Event::RenderAdded),
121 RawEvent::RenderDone(event) => event.deserialize().map(Event::RenderDone),
122 RawEvent::RenderFailed(event) => event.deserialize().map(Event::RenderFailed),
123 RawEvent::RenderProgress(event) => event.deserialize().map(Event::RenderProgress),
124 RawEvent::CustomSkinProcessUpdate(event) => {
125 event.deserialize().map(Event::CustomSkinProcessUpdate)
126 }
127 }
128 }
129}
130
131#[derive(Clone, Debug, PartialEq, Eq)]
133pub struct RawRenderAdded {
134 pub bytes: Bytes,
135}
136
137impl RawRenderAdded {
138 pub fn deserialize(&self) -> Result<RenderAdded, SerdeError> {
140 serde_json::from_slice(&self.bytes)
141 }
142}
143
144#[derive(Clone, Debug, PartialEq, Eq)]
146pub struct RawRenderProgress {
147 pub render_id: u32,
148 pub bytes: Bytes,
149}
150
151impl RawRenderProgress {
152 pub fn deserialize(&self) -> Result<RenderProgress, SerdeError> {
154 serde_json::from_slice(&self.bytes)
155 }
156}
157
158#[derive(Clone, Debug, PartialEq, Eq)]
160pub struct RawRenderFailed {
161 pub render_id: u32,
162 pub bytes: Bytes,
163}
164
165impl RawRenderFailed {
166 pub fn deserialize(&self) -> Result<RenderFailed, SerdeError> {
168 serde_json::from_slice(&self.bytes)
169 }
170}
171
172#[derive(Clone, Debug, PartialEq, Eq)]
174pub struct RawRenderDone {
175 pub render_id: u32,
176 pub bytes: Bytes,
177}
178
179impl RawRenderDone {
180 pub fn deserialize(&self) -> Result<RenderDone, SerdeError> {
182 serde_json::from_slice(&self.bytes)
183 }
184}
185
186#[derive(Clone, Debug, PartialEq, Eq)]
188pub struct RawCustomSkinProcessUpdate {
189 pub bytes: Bytes,
190}
191
192impl RawCustomSkinProcessUpdate {
193 pub fn deserialize(&self) -> Result<CustomSkinProcessUpdate, SerdeError> {
195 serde_json::from_slice(&self.bytes)
196 }
197}