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