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}