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}