firefly_types/serial.rs
1//! Serialization for messages send over USB ("serial port").
2//!
3//! These messages are used for interacting with a running device:
4//! getting runtime stats, executing cheats and admin commands, etc.
5//!
6//! Unlike in multiplayer (which is peer-to-peer), this is asymmetric communication.
7//! Clients (desktop app, CLI, etc) send [`Request`]s
8//! and the runtime (device or emulator) sends back [`Response`]s.
9use crate::encode::Encode;
10use alloc::boxed::Box;
11use alloc::string::String;
12use serde::{Deserialize, Serialize};
13
14/// Messages that clients send into the runtime.
15#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
16pub enum Request {
17 /// Call the `cheat` callback with the given two arguments.
18 ///
19 /// It's up to the app how to handle the passed values,
20 /// but the most common practice is to treat the first value as the command
21 /// to execute (for exmaple, 42 for "noclip") and the second value as
22 /// the command argument (for example, 0 for "disable" and 1 for "enable").
23 Cheat(i32, i32),
24
25 /// Turn on/off collection and sending of runtime stats.
26 Stats(bool),
27
28 /// Get the full ID of the currently running app.
29 AppId,
30
31 /// Take a screenshot.
32 Screenshot,
33
34 /// Launch an app.
35 Launch((String, String)),
36
37 /// Launch the launcher.
38 Exit,
39
40 /// Send buttons input.
41 Buttons(u8),
42
43 /// Send data into the running app.
44 Data(Box<[u8]>),
45}
46
47impl Encode<'_> for Request {}
48
49/// Messages that the runtime sends to connected clients.
50#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
51pub enum Response {
52 /// The value returned by the `cheat` callback.
53 Cheat(i32),
54 /// Instructions executed by a callback.
55 Fuel(Callback, Fuel),
56 /// CPU time spent running code vs sleeping.
57 CPU(CPU),
58 /// Linear memory used by the wasm app.
59 Memory(Memory),
60 /// Log record.
61 Log(String),
62 /// Full ID of the currently running app.
63 AppID((String, String)),
64 /// A generic confirmation response for a request.
65 Ok,
66}
67
68impl Encode<'_> for Response {}
69
70#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
71pub enum Callback {
72 /// The `boot` wasm callback.
73 Boot,
74 /// The `update` wasm callback.
75 Update,
76 /// The `render` wasm callback.
77 Render,
78 /// DEPRECATED: The `render_line` wasm callback.
79 RenderLine,
80 /// The `cheat` wasm callback.
81 Cheat,
82}
83
84/// The fuel consumed (wasm instructions executed) by a callback on the observed interval.
85#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
86pub struct Fuel {
87 /// The least fuel consumed by a single run.
88 pub min: u32,
89
90 /// The most fuel consumed by a single run.
91 pub max: u32,
92
93 /// The average number of instructions executed per run.
94 pub mean: u32,
95
96 /// Squared standard deviation of individual runs from the average.
97 ///
98 /// Lower value means more consistent CPU load. Higher values mean
99 /// that some runs are fast and some runs are slow.
100 ///
101 /// Take square root to get stdev.
102 pub var: f32,
103
104 /// The number of runs of the given callback on the observed interval.
105 pub calls: u32,
106}
107
108#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
109pub struct Memory {
110 /// The number of linear memory pages allocated for the app.
111 ///
112 /// One page size is 64 KB, as defined by the WebAssembly core specification.
113 pub pages: u16,
114
115 /// The address of the last byte that isn't zero.
116 ///
117 /// This roughly corresponds to the actual memory used in the app,
118 /// assuming that the allocator tries to use lower address values
119 /// and that most of data structures in use aren't all zeroes.
120 pub last_one: u32,
121
122 /// The number of read operations.
123 ///
124 /// Currently unused. Reserved for future use.
125 pub reads: u32,
126
127 /// The number of write operations.
128 ///
129 /// Currently unused. Reserved for future use.
130 pub writes: u32,
131
132 /// The maximum memory that can be allocated.
133 ///
134 /// Currently unused. Reserved for future use.
135 pub max: u32,
136}
137
138#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
139pub struct CPU {
140 /// The time taken running the app.
141 ///
142 /// Includes executing wasm callbacks, wasm host functions,
143 /// rendering frame buffer on the screen, syncing network code, etc.
144 /// Basically, everything except when the main thread is sleeping.
145 ///
146 /// Lower is better.
147 pub busy_ns: u32,
148
149 /// The time over expected limit taken by updates.
150 ///
151 /// Lower is better. If this value is not zero, the app will be lagging.
152 pub lag_ns: u32,
153
154 /// The total duration of the observed interval, in nanoseconds.
155 pub total_ns: u32,
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161
162 #[test]
163 fn test_roundtrip_request() {
164 let given = Request::Cheat(3, 4);
165 let mut buf = vec![0; given.size()];
166 let raw = given.encode_buf(&mut buf).unwrap();
167 let actual = Request::decode(raw).unwrap();
168 assert_eq!(given, actual);
169 }
170
171 #[test]
172 fn test_roundtrip_response() {
173 let given = Response::Cheat(13);
174 let mut buf = vec![0; given.size()];
175 let raw = given.encode_buf(&mut buf).unwrap();
176 let actual = Response::decode(raw).unwrap();
177 assert_eq!(given, actual);
178 }
179}