RPC
In this section, we will walk through the protocol
example in Rust. It converts the case of
alphabetic ASCII characters from its request to its response and switches the letters I
and O
(similarly for lower-case the letters i
and o
).
The platform protocol (used to install applets, update the platform, reboot the platform, etc) also
provides a way to call into an applet by sending a request and reading the response. The applet can
define a handler taking a Vec<u8>
request as argument and returning a Vec<u8>
response (which
can reuse the backing storage of the request).
In this example, the handler simply converts all characters of the request, prints how many times it was called, and returns the updated request as its response1.
let mut counter = 0;
let handler = move |mut data: Vec<u8>| {
data.iter_mut().for_each(convert);
counter += 1;
debug!("Converted {counter} lines.");
data
};
A listener can be created and leaked as usual.
rpc::Listener::new(&platform::protocol::RpcProtocol, handler).leak();
The conversion function is straightforward:
fn convert(x: &mut u8) {
if x.is_ascii_alphabetic() {
*x ^= 0x20; // switch case
}
if matches!(*x, b'I' | b'O' | b'i' | b'o') {
*x ^= 0x6; // switch between I and O preserving case
}
}
The final code looks like this:
#![no_std] wasefire::applet!(); use alloc::vec::Vec; fn main() { let mut counter = 0; let handler = move |mut data: Vec<u8>| { data.iter_mut().for_each(convert); counter += 1; debug!("Converted {counter} lines."); data }; rpc::Listener::new(&platform::protocol::RpcProtocol, handler).leak(); } fn convert(x: &mut u8) { if x.is_ascii_alphabetic() { *x ^= 0x20; // switch case } if matches!(*x, b'I' | b'O' | b'i' | b'o') { *x ^= 0x6; // switch between I and O preserving case } }
Testing
You can use the wasefire applet-rpc
command to send an RPC to an applet. By default it reads from
standard input and write to standard output.
% echo HELLO ping | wasefire applet-rpc
helli PONG
Note that we don't need interior mutability here, compared to buttons for example. This is because the RPC handler is not re-entrant. The platform won't send a new request if the previous request was not responded.