`libtock_platform` Design Story
===============================

Note: At the time of this writing, `libtock_platform` is still a work in
progress that exists largely in @jrvanwhy's head.

`libtock_platform` is a crate that will contain core abstractions that will be
used by `libtock_core`'s drivers. For example, it will contain abstractions for
asynchronous APIs that are lighter weight (in terms of code size and RAM usage)
than Rust's futures.

This document serves as a justification for, and explanation of, the high-level
design of `libtock_platform`. Instead of describing the various components and
how they interact, it starts with a hello world application and extracts some of
the functionality out into a reusable library. As we do so, we see that
`libtock_core`'s [design considerations](DesignConsiderations.md) lead
incrementally to a design for `libtock_platform`.

In order to keep things understandable, this document makes several
simplifications. Error handling logic is omitted, although we still structure
the code so as to allow it. We use `unsafe` in places where we should instead
have an additional, safe, abstraction. We use a simplified form of the Tock 2.0
system calls, which are currently undergoing design revisions.

## Hello World

We start with the following example app. In order to show how `libtock_platform`
will handle asynchronous callbacks, it is written in an asynchronous manner.

```rust
#![no_std]

static GREETING: [u8; 7] = *b"Hello, ";
static NOUN: [u8; 7] = *b"World!\n";
static mut DONE: bool = false;

// Driver, command, allow, and subscription numbers.
const DRIVER: usize = 1;
const WRITE_DONE: usize = 1;
const WRITE_BUFFER: usize = 1;
const START_WRITE: usize = 1;

fn main() {
    libtock_runtime::subscribe(DRIVER, WRITE_DONE, write_complete, 0);
    libtock_runtime::const_allow(DRIVER, WRITE_BUFFER, &GREETING);
    libtock_runtime::command(DRIVER, START_WRITE, GREETING.len(), 0);
    loop {
        libtock_runtime::yieldk();
    }
}

extern "C" fn write_complete(bytes: usize, _: usize, _: usize, _data: usize) {
    // Detect if this write completion is a result of writing NOUN (the
    // second write). If so, return immediately to avoid an infinite loop.
    unsafe {
        if DONE { return; }
        DONE = true;
    }
    // At this point, we just finished writing GREETING and need to write NOUN.
    libtock_runtime::const_allow(DRIVER, WRITE_BUFFER, &NOUN);
    libtock_runtime::command(DRIVER, START_WRITE, NOUN.len(), 0);
}
```

Strictly speaking, in this app, `DONE` could be tracked by passing it as the
`data` argument to `subscribe`. However, most applications will need to track
more than 32 bits of persistent state -- and use more than one callback -- so
they will need to manage persistent state themselves. To make this app
representative of most apps, we keep the state in userspace memory.

This example assumes that the `libtock_runtime` crate exposes system call
implementations that look like the following (these are a simplification of the
Tock 2.0 system calls):

```rust
pub fn subscribe(driver_num: usize,
                 subscription_num: usize,
                 callback: extern "C" fn(usize, usize, usize, usize),
                 data: usize);

pub fn const_allow(driver_num: usize, buffer_num: usize, buffer: &'static [u8]);
pub fn command(driver_num: usize, command_num: usize, arg1: usize, arg2: usize);
pub fn yieldk();
```

What do we already get "right" in this example? Except for the two intentional
inefficiencies explained above (performing the write in two steps rather than 1
and maintaining the `DONE` state in process memory), it is very efficient. It
has only 3 global variables: `GREETING`, `NOUN`, and `DONE`. It has almost zero
bookkeeping overhead; it fairly directly makes 8 system calls (`subscribe`,
`const_allow`, `command`, `yieldk`, `const_allow`, `command`, `yieldk`,
`yieldk`).

What do we want to improve? It calls system calls directly from application code
-- there should be a reusable `console` library that implements the system calls
instead! The application shouldn't need to know what command number starts a
write, it should just tell the console driver to do that for it.

## Adding a Console Library

Let's start taking some of the console-specific parts and moving them into a new
crate. The first system call the app makes is to `subscribe` to the write done
callback, so let's add a function to a new `libtock_console` crate that sets a
write callback using `subscribe`:

```rust
#![no_std]

const DRIVER: usize = 1;
const WRITE_DONE: usize = 1;

fn set_write_callback(callback: fn(bytes: usize, data: usize), data: usize) {
    libtock_runtime::subscribe(DRIVER, WRITE_DONE, write_complete, data);
    // We need to store `callback` somewhere -- where to do so?
}

extern "C" fn write_complete(bytes: usize, _: usize, _: usize, data: usize) {
    // Hmm, how do we access the callback?
}
```

You may notice that the code is not quite complete: `set_write_callback` takes a
callback but doesn't store it anywhere. We don't want to store it in a global
variable because doing so would not be zero-cost: the original app didn't need
to store a function pointer, and we want to do this refactoring without bloating
the app. We could pass it through `data`, but what if the client code needs to
use `data` itself? That pattern isn't extensible: if there is another
asynchronous layer about the console (e.g. a virtualization system), it won't
have access to `data` to pass its callbacks through.

Instead, we can pass the callback through the type system. We need a new trait
to represent the callback. This trait won't be specific to `libtock_console`,
and we'll later use it in unit tests -- which run on Linux, not Tock, so we'll
put it in the `libtock_platform` crate:

```rust
pub trait FreeCallback<AsyncResponse> {
    fn call(response: AsyncResponse);
}
```

We call this `FreeCallback` because it represents a free function as opposed to
a method. (This forshadows `MethodCallback`, which we will need later)

The reason why we made this a shared generic trait rather than adding a
`libtock_console::Client` trait as the Tock kernel does will be apparent later.

Using this trait, we can now write `libtock_console::set_write_callback`:

```rust
#![no_std]

use libtock_platform::FreeCallback;

const DRIVER: usize = 1;
const WRITE_DONE: usize = 1;

pub struct WriteCompleted {
    pub bytes: usize,
    pub data: usize,
}

pub fn set_write_callback<Callback: FreeCallback<WriteCompleted>>(data: usize) {
    libtock_runtime::subscribe(DRIVER, WRITE_DONE, write_complete::<Callback>, data);
}

extern "C" fn write_complete<Callback: FreeCallback<WriteCompleted>>(
    bytes: usize, _: usize, _: usize, data: usize)
{
    Callback::call(WriteCompleted { bytes, data });
}
```

To finish `libtock_console`, we also need to add `set_write_buffer` (which calls
`allow`) and `start_write` (which calls `command`), which are much simpler:

```rust
const WRITE_BUFFER: usize = 1;
const START_WRITE: usize = 1;

pub fn set_write_buffer(buffer: &'static [u8]) {
    libtock_runtime::const_allow(DRIVER, WRITE_BUFFER, buffer);
}

pub fn start_write(bytes: usize) {
    libtock_runtime::command(DRIVER, START_WRITE, bytes, 0);
}
```

We can then make use of `libtock_console` in our app as follows:

```rust
#![no_std]

static GREETING: [u8; 7] = *b"Hello, ";
static NOUN: [u8; 7] = *b"World!\n";
static mut DONE: bool = false;

fn main() {
    libtock_console::set_write_callback::<App>(0);
    libtock_console::set_write_buffer(&GREETING);
    libtock_console::start_write(GREETING.len());
    loop {
        libtock_runtime::yieldk();
    }
}

struct App;

impl libtock_platform::FreeCallback<libtock_console::WriteCompleted> for App {
    fn call(_response: WriteCompleted) {
        unsafe {
            if DONE { return; }
            DONE = true;
        }
        libtock_console::set_write_buffer(&NOUN);
        libtock_console::start_write(NOUN.len());
    }
}
```

Now we have a reusable console library! However, we still don't have any unit
tests.

## Adding a Fake Kernel

A good unit test for the console driver would test not only the driver's
operation with successful system calls but also also test the driver's
error-handling logic. That is difficult to do if we test using a real Tock
kernel in an emulator -- the real kernel has the goal of avoiding system call
errors! Instead of using a real Tock kernel, driver unit tests should use a
"fake kernel" that simulates the kernel's functionality while allowing errors to
be injected.

To keep this document reasonably short and understandable, we have omitted error
handling, but we can still structure our unit tests in a manner that would allow
a test to inject errors when error handling logic is added.

To allow the console driver to work with both a real kernel and a fake kernel,
we add a `Syscalls` trait to `libtock_platform`. When compiled into a Tock
process binary, `Syscalls` will be implemented by a zero-sized type, which
avoids wasting non-volatile storage space or RAM area. To avoid passing around
references to a `Syscalls` implementation, we can pass the `Syscalls` by value
rather than by reference (i.e. take `self` rather than `&self`). For practical
use, this requires the `Syscalls` implementations to be `Copy`.

```rust
pub trait Syscalls: Copy {
    fn subscribe(self, driver: usize, minor: usize,
                 callback: extern "C" fn(usize, usize, usize, usize),
                 data: usize);

    fn const_allow(self, major: usize, minor: usize, buffer: &'static [u8]);
    fn command(self, major: usize, miner: usize, arg1: usize, arg2: usize);
    fn yieldk(self);
}
```

We then implement `Syscalls` using a real Tock kernel in `libtock_runtime`:

```rust
#[derive(Clone, Copy)]
pub struct TockSyscalls;

impl libtock_platform::Syscalls for TockSyscalls {
    /* Omitted implementation details */
}
```

We adapt `libtock_console` to use an app-provided `Syscalls` implementation
rather than directly calling into `libtock_runtime`:

```rust
pub fn set_write_callback<S: Syscalls, Callback: FreeCallback<WriteCompleted>>(
    syscalls: S, data: usize)
{
    syscalls.subscribe(1, 1, write_complete::<Callback>, data);
}

extern "C" fn write_complete<Callback: FreeCallback<WriteCompleted>>(
    bytes: usize, _: usize, _: usize, data: usize)
{
    Callback::call(WriteCompleted { bytes, data });
}

pub fn set_write_buffer<S: Syscalls>(syscalls: S, buffer: &'static [u8]) {
    syscalls.const_allow(1, 1, buffer);
}

pub fn start_write<S: Syscalls>(syscalls: S, bytes: usize) {
    syscalls.command(1, 1, bytes, 0);
}
```

We'll create a new crate, `libtock_unittest`, which contains test utilities such
as the fake Tock kernel. The fake kernel, unlike
`libtock_runtime::TockSyscalls`, needs to maintain state, so it cannot be a
zero-sized type. Instead of implementing `Syscalls` on the fake kernel directly,
we implement it on a shared reference:

```rust
type RawCallback = extern "C" fn(usize, usize, usize, usize);

pub struct FakeSyscalls {
    callback_pending: core::cell::Cell<Option<usize>>,
    output: core::cell::Cell<Vec<u8>>,
    write_buffer: core::cell::Cell<Option<&'static [u8]>>,
    write_callback: core::cell::Cell<Option<RawCallback>>,
    write_data: core::cell::Cell<usize>,
}

impl FakeSyscalls {
    pub fn new() -> Self {
        FakeSyscalls {
            callback_pending: Cell::new(None),
            output: Cell::new(Vec::new()),
            write_buffer: Cell::new(None),
            write_callback: Cell::new(None),
            write_data: Cell::new(0),
        }
    }

    pub fn read_buffer(&self) -> &'static [u8] {
        self.write_buffer.take().unwrap_or(&[])
    }
}

impl libtock_platform::Syscalls for &FakeSyscalls {
    fn subscribe(self, driver: usize, minor: usize, callback: RawCallback, data: usize) {
        if driver == 1 && minor == 1 {
            self.write_callback.set(Some(callback));
            self.write_data.set(data);
        }
    }

    fn const_allow(self, major: usize, minor: usize, buffer: &'static [u8]) {
        if major == 1 && minor == 1 {
            self.write_buffer.set(Some(buffer));
        }
    }

    fn command(self, major: usize, minor: usize, arg1: usize, _arg2: usize) {
        if major != 1 || minor != 1 { return; }
        if let Some(buffer) = self.write_buffer.get() {
            let mut output = self.output.take();
            let bytes = core::cmp::min(arg1, buffer.len());
            output.extend_from_slice(&buffer[..bytes]);
            self.output.set(output);
            self.callback_pending.set(Some(bytes));
        }
    }

    fn yieldk(self) {
        let bytes = match self.callback_pending.take() {
            Some(bytes) => bytes,
            None => return,
        };
        if let Some(callback) = self.write_callback.get() {
            callback(bytes, 0, 0, self.write_data.get());
        }
    }
}
```

## Adding a Synchronous Adapter

We're still not ready to add unit tests to `libtock_console` yet!
`libtock_console` is asynchronous, which is difficult to work with in a unit
test. `libtock_core` should provide synchronous APIs for apps that do not wish
to be fully asynchronous, so lets go ahead and implement a synchronous API. To
avoid re-implementing synchronous APIs for every driver, let's make it work
generically with all `libtock_core` drivers. This is where we benefit from
making `FreeCallback` a generic trait rather than having a
`libtock_console::Client` trait.

The synchronous adapter will need to store a copy of an `AsyncResponse`, so its
callback cannot be a free function (it needs access to `self`). Therefore, we
add the `MethodCallback` trait to `libtock_platform`:

```rust
pub trait MethodCallback<AsyncResponse> {
    fn call(&self, response: AsyncResponse);
}
```

Using `MethodCallback`, we can now write `SyncAdapter`. We add `SyncAdapter` to
a new crate, `libtock_sync`, as not all Tock apps will want it:

```rust
use libtock_platform::MethodCallback;

pub struct SyncAdapter<AsyncResponse, Syscalls> {
    response: core::cell::Cell<Option<AsyncResponse>>,
    syscalls: Syscalls,
}

impl<AsyncResponse, Syscalls> SyncAdapter<AsyncResponse, Syscalls> {
    pub const fn new(syscalls: Syscalls) -> SyncAdapter<AsyncResponse, Syscalls> {
        SyncAdapter { response: core::cell::Cell::new(None), syscalls }
    }
}

impl<AsyncResponse, Syscalls: libtock_platform::Syscalls> SyncAdapter<AsyncResponse, Syscalls> {
    pub fn wait(&self) -> AsyncResponse {
        loop {
            match self.response.take() {
                Some(response) => return response,
                None => self.syscalls.yieldk(),
            }
        }
    }
}

impl<AsyncResponse, Syscalls: libtock_platform::Syscalls>
MethodCallback<AsyncResponse> for SyncAdapter<AsyncResponse, Syscalls> {
    fn call(&self, response: AsyncResponse) {
        self.response.set(Some(response));
    }
}
```

## Adding a Unit Test

Before we write the test itself, we should add one more utility to
`libtock_unittest`. That utility is the `test_component!` macro, which creates a
thread-local instance of a type and provides `FreeCallback` implementations for
every `MethodCallback` implementation the type has:

```rust
#[macro_export]
macro_rules! test_component {
    [$link:ident, $name:ident: $comp:ty = $init:expr] => {
        let $name = std::boxed::Box::leak(std::boxed::Box::new($init)) as &$comp;
        std::thread_local!(static GLOBAL: std::cell::Cell<Option<&'static $comp>>
                           = std::cell::Cell::new(None));
        GLOBAL.with(|g| g.set(Some($name)));
        struct $link;
        impl<T> libtock_platform::FreeCallback<T> for $link
        where $comp: libtock_platform::MethodCallback<T> {
            fn call(response: T) {
                GLOBAL.with(|g| g.get().unwrap()).call(response);
            }
        }
    };
}
```

We can finally add a unit test to `libtock_console`:

```rust
#[cfg(test)]
mod tests {
    #[test]
    fn write() {
        extern crate std;

        use libtock_platform::MethodCallback;
        use libtock_sync::SyncAdapter;
        use libtock_unittest::FakeSyscalls;
        use std::boxed::Box;
        use std::thread_local;
        use super::{set_write_buffer, set_write_callback, start_write, WriteCompleted};

        let syscalls: &_ = Box::leak(Box::new(FakeSyscalls::new()));
        libtock_unittest::test_component![SyncAdapterLink, sync_adapter: SyncAdapter<WriteCompleted, &'static FakeSyscalls>
                                          = SyncAdapter::new(syscalls)];

        set_write_callback::<_, SyncAdapterLink>(syscalls, 1234);
        set_write_buffer(syscalls, b"Hello");
        start_write(syscalls, 5);
        let response = sync_adapter.wait();
        assert_eq!(response.bytes, 5);
        assert_eq!(response.data, 1234);
        assert_eq!(syscalls.read_buffer(), b"Hello");
    }
}
```

## Adding `static_component!`

We added `libtock_unittest::test_component!` to make it easy to set up
components in unit tests, but we have no equivalent for apps. Our app still uses
`unsafe` to access its `DONE` variable. Instead, lets hide that unsafety behind
a new macro. This macro is only sound in `libtock_runtime`'s single-threaded
environment, so we add it to `libtock_runtime` directly:

```rust
#[macro_export]
macro_rules! static_component {
    [$link:ident, $name:ident: $comp:ty = $init:expr] => {
        static mut COMPONENT: $comp = $init;
        struct $link;
        impl<T> libtock_platform::FreeCallback<T> for $link
        where $comp: libtock_platform::MethodCallback<T> {
            fn call(response: T) {
                unsafe { &COMPONENT }.call(response);
            }
        }
    };
}
```

We can now use `static_component!` in our Hello World app to instantiate the
`App` struct:

```rust
#![no_std]

static GREETING: [u8; 7] = *b"Hello, ";
static NOUN: [u8; 7] = *b"World!\n";

fn main() {
    libtock_console::set_write_callback::<_, AppLink>(0);
    libtock_console::set_write_buffer(&GREETING);
    libtock_console::start_write(GREETING.len());
    loop {
        libtock_runtime::yieldk();
    }
}

struct App {
    done: core::cell::Cell<bool>
}

impl App {
    pub const fn new() -> App {
        App {
            done: core::cell::Cell::new(false)
        }
    }
}

impl MethodCallback<WriteCompleted> for App {
    fn call(&self, _response: WriteCompleted) {
        if self.done.get() { return; }
        self.done.set(true);
        set_write_buffer(TockSyscalls, &NOUN );
        start_write(TockSyscalls, NOUN.len() );
    }
}

libtock_runtime::static_component![AppLink, APP: App = App::new()];
```

Now our app has no more unsafe!

## Recap

We wrote a Hello World application that uses Tock's console system calls and
asynchronous callbacks. We then extracted the console system call interface into
a reusable library, creating the `FreeCallback` trait along the way.

In order to provide unit tests for the console library, we needed to create
several new abstractions. We created `Syscalls` so that we can direct tho
console driver's system calls to a fake kernel. We created the
`libtock_unittest` crate which contains the fake kernel as well as a
`test_component!` helper macro. We created `SyncAdapter` so that the unit test
can be written in a synchronous manner -- although `SyncAdapter` is not
testing-specific! We created `MethodCallback` because `FreeCallback` is not a
powerful-enough abstraction on its own for `SyncAdapter`.

We ended up with six Rust crates:

1. `libtock_console`, which contains the console driver logic and unit test
   code.
2. `libtock_platform`, which provides abstractions that can be shared with other
   drivers.
3. `libtock_runtime`, which contains non-portable system call implementations.
4. `libtock_sync`, which provides a synchronous interface using
   `libtock_platform`'s traits.
5. `libtock_unittest`, which provides a fake Tock kernel and other utilities.
6. The hello world app itself.
