1use serde::{Deserialize, Serialize};
12use serde_json::Value;
13
14pub const MESSAGE_KEY: &str = "message";
17pub const CANVAS_KEY: &str = "canvas";
19pub const APP_KEY: &str = "app";
23pub const ATTACHMENTS_KEY: &str = "attachments";
26
27pub type Attachments = Vec<(String, Vec<u8>)>;
30
31pub trait WorkerProtocol {
39 type Incoming: Serialize + serde::de::DeserializeOwned + 'static;
40 type Outgoing: Serialize + serde::de::DeserializeOwned + Send + Sync + 'static;
41}
42
43pub struct ValueProtocol;
47
48impl WorkerProtocol for ValueProtocol {
49 type Incoming = Value;
50 type Outgoing = Value;
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
54pub enum TouchPhase {
55 Started,
56 Moved,
57 Ended,
58 Cancelled,
59}
60
61#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
65pub struct SelectedEntity {
66 pub id: u32,
68 pub name: String,
70}
71
72#[derive(Clone, Debug, Serialize, Deserialize)]
73pub enum ToWorker {
74 Init {
75 width: f32,
76 height: f32,
77 },
78 Resize {
79 width: f32,
80 height: f32,
81 },
82 PointerMove {
83 x: f32,
84 y: f32,
85 },
86 PointerMotion {
89 dx: f32,
90 dy: f32,
91 },
92 PointerButton {
93 button: u8,
94 pressed: bool,
95 },
96 Wheel {
97 delta: f32,
98 },
99 Touch {
100 id: u64,
101 phase: TouchPhase,
102 x: f32,
103 y: f32,
104 },
105 Key {
106 code: String,
107 pressed: bool,
108 text: Option<String>,
109 },
110 Pick {
111 x: f32,
112 y: f32,
113 },
114}
115
116#[derive(Clone, Debug, Serialize, Deserialize)]
117pub enum FromWorker {
118 Ready { adapter: String },
119 Stats { fps: f32, entity_count: u32 },
120 Selected { detail: Option<SelectedEntity> },
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 fn to_worker_roundtrips(message: ToWorker) {
128 let value = serde_json::to_value(&message).expect("serialize");
129 let back: ToWorker = serde_json::from_value(value).expect("deserialize");
130 assert_eq!(format!("{message:?}"), format!("{back:?}"));
131 }
132
133 #[test]
134 fn to_worker_survives_the_wire() {
135 to_worker_roundtrips(ToWorker::Init {
136 width: 800.0,
137 height: 600.0,
138 });
139 to_worker_roundtrips(ToWorker::PointerButton {
140 button: 2,
141 pressed: true,
142 });
143 to_worker_roundtrips(ToWorker::PointerMotion { dx: -3.5, dy: 1.0 });
144 to_worker_roundtrips(ToWorker::Touch {
145 id: 7,
146 phase: TouchPhase::Moved,
147 x: 1.0,
148 y: 2.0,
149 });
150 to_worker_roundtrips(ToWorker::Key {
151 code: "KeyW".to_string(),
152 pressed: true,
153 text: Some("w".to_string()),
154 });
155 }
156
157 #[test]
158 fn from_worker_survives_the_wire() {
159 let message = FromWorker::Selected {
160 detail: Some(SelectedEntity {
161 id: 3,
162 name: "Cube 3".to_string(),
163 }),
164 };
165 let value = serde_json::to_value(&message).expect("serialize");
166 let back: FromWorker = serde_json::from_value(value).expect("deserialize");
167 assert_eq!(format!("{message:?}"), format!("{back:?}"));
168 }
169}