[
  {
    "path": ".cargo/config.toml",
    "content": "[alias]\nrriscv32imac = \"run --release --target=riscv32imac-unknown-none-elf --example\"\nrrv32imac = \"rriscv32imac\"\nrriscv32imc = \"run --release --target=riscv32imc-unknown-none-elf --example\"\nrrv32imc = \"rriscv32imc\"\nrthumbv7em = \"run --release --target=thumbv7em-none-eabi --example\"\nrtv7em = \"rthumbv7em\"\n\n# Common settings for all embedded targets\n[target.'cfg(any(target_arch = \"arm\", target_arch = \"riscv32\", target_arch = \"x86\"))']\nrustflags = [\n    \"-C\", \"relocation-model=static\",\n    \"-C\", \"link-arg=-icf=all\",\n]\nrunner = [\"cargo\", \"run\", \"-p\", \"runner\", \"--release\"]\n"
  },
  {
    "path": ".github/workflows/artifacts.yml",
    "content": "name: Artifacts\non:\n  push:\n    branches: [master]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n\n      - name: Install dependencies\n        run: |\n          cargo install elf2tab\n\n      - name: Build LEDs\n        run: |\n          make -j2 EXAMPLE=leds apollo3\n          make -j2 EXAMPLE=leds hail\n          make -j2 EXAMPLE=leds imix\n          make -j2 EXAMPLE=leds nucleo_f429zi\n          make -j2 EXAMPLE=leds nucleo_f446re\n          make -j2 EXAMPLE=leds nrf52840\n          make -j2 EXAMPLE=leds opentitan\n          make -j2 EXAMPLE=leds hifive1\n          make -j2 EXAMPLE=leds nrf52\n\n      - name: Build Low Level Debug\n        run: |\n          make -j2 EXAMPLE=low_level_debug apollo3\n          make -j2 EXAMPLE=low_level_debug hail\n          make -j2 EXAMPLE=low_level_debug imix\n          make -j2 EXAMPLE=low_level_debug nucleo_f429zi\n          make -j2 EXAMPLE=low_level_debug nucleo_f446re\n          make -j2 EXAMPLE=low_level_debug nrf52840\n          make -j2 EXAMPLE=low_level_debug opentitan\n          make -j2 EXAMPLE=low_level_debug hifive1\n          make -j2 EXAMPLE=low_level_debug nrf52\n\n      - name: Archive artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: libtock-rs examples\n          path: target/tbf\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "# This workflow provides automated testing. It builds and runs tests on each PR.\n\nname: ci\n\n# We want to run CI on all pull requests. Additionally, GitHub actions merge\n# queue needs workflows to run on the `merge_queue` trigger to block merges on\n# them.\non:\n  pull_request:\n  merge_group:\n\njobs:\n  ci:\n    # Using ubuntu-latest can cause breakage when ubuntu-latest is updated to\n    # point at a new Ubuntu version. Instead, explicitly specify the version, so\n    # we can update when we need to. This *could* break if we don't update it\n    # until support for this version is dropped, but it is likely we'll have a\n    # reason to update to a newer Ubuntu before then anyway.\n    runs-on: ubuntu-22.04\n\n    steps:\n      # Clones a single commit from the libtock-rs repository. The commit cloned\n      # is a merge commit between the PR's target branch and the PR's source.\n      # Note that we checkout submodules so that we can invoke Tock's CI setup\n      # scripts, but we do not recursively checkout submodules as we need Tock's\n      # makefile to set up the qemu submodule itself.\n      - name: Clone repository\n        uses: actions/checkout@v3\n        with:\n          submodules: true\n\n      # The main test step. We let the makefile do most of the work because the\n      # makefile can be tested locally. We experimentally determined that -j2 is\n      # optimal for the Azure Standard_DS2_v2 VM, which is the VM type used by\n      # GitHub Actions at the time of this writing.\n      #\n      # We have to append the \"-D warnings\" flag to .cargo/config.toml rather\n      # than using the RUSTFLAGS environment variable because if we set\n      # RUSTFLAGS cargo will ignore the rustflags config in .cargo/config,\n      # breaking relocation.\n      - name: Build and Test\n        run: |\n          sudo apt-get install ninja-build\n          cd \"${GITHUB_WORKSPACE}\"\n          echo \"[target.'cfg(all())']\" >> .cargo/config.toml\n          echo 'rustflags = [\"-D\", \"warnings\"]' >> .cargo/config.toml\n          make -j2 setup\n          make -j2 test\n          make demos\n"
  },
  {
    "path": ".github/workflows/mac-os.yml",
    "content": "# This workflow verifies libtock-rs is usable on Mac OS.\n\nname: ci-mac-os\n\n# We run this workflow during pull request review, but not as a required status\n# for GitHub actions merge-queue merges. We can change this if the workflow is\n# reasonably quick and reliable.\non: pull_request\n\njobs:\n  ci-mac-os:\n    runs-on: macos-latest\n\n    steps:\n      # Clones a single commit from the libtock-rs repository. The commit cloned\n      # is a merge commit between the PR's target branch and the PR's source.\n      - name: Clone repository\n        uses: actions/checkout@v3\n\n      - name: Build and Test\n        run: |\n          cd \"${GITHUB_WORKSPACE}\"\n          LIBTOCK_PLATFORM=nrf52 cargo build -p libtock \\\n            --target=thumbv7em-none-eabi\n          LIBTOCK_PLATFORM=hifive1 cargo build -p libtock \\\n            --target=riscv32imac-unknown-none-elf\n"
  },
  {
    "path": ".github/workflows/size-diff.yml",
    "content": "# Calculates the size diffs for the each example binary. Runs when a pull\n# request is created or modified.\n\nname: size-diff\n\n# We want to run this on all pull requests. Additionally, GitHub actions merge\n# queue needs workflows to run on the `merge_queue` trigger to block merges on\n# them.\non:\n  pull_request:\n  merge_group:\n\njobs:\n  size-diff:\n    # Using ubuntu-latest can cause breakage when ubuntu-latest is updated to\n    # point at a new Ubuntu version. Instead, explicitly specify the version, so\n    # we can update when we need to. This *could* break if we don't update it\n    # until support for this version is dropped, but it is likely we'll have a\n    # reason to update to a newer Ubuntu before then anyway.\n    runs-on: ubuntu-22.04\n\n    steps:\n      # Clones a single commit from the libtock-rs repository. The commit cloned\n      # is a merge commit between the PR's target branch and the PR's source.\n      # We'll later add another commit (the pre-merge target branch) to the\n      # repository.\n      - name: Clone repository\n        uses: actions/checkout@v3\n\n      # The main diff script. Stores the sizes of the example binaries for both\n      # the merge commit and the target branch. We display the diff in a\n      # separate step to make it easy to navigate to in the GitHub Actions UI.\n      #\n      # If the build on master doesn't work (`make -j2 examples` fails), we\n      # output a warning message and ignore the error. Ignoring the error\n      # prevents this workflow from blocking PRs that fix a broken build in\n      # master.\n      - name: Compute sizes\n        run: |\n          UPSTREAM_REMOTE_NAME=\"${UPSTREAM_REMOTE_NAME:-origin}\"\n          GITHUB_BASE_REF=\"${GITHUB_BASE_REF:-master}\"\n          cd \"${GITHUB_WORKSPACE}\"\n          make -j2 examples  # The VM this runs on has 2 logical cores.\n          cargo run --release -p print_sizes >'${{runner.temp}}/merge-sizes'\n          git remote set-branches \"${UPSTREAM_REMOTE_NAME}\" \"${GITHUB_BASE_REF}\"\n          git fetch --depth=1 \"${UPSTREAM_REMOTE_NAME}\" \"${GITHUB_BASE_REF}\"\n          git checkout \"${UPSTREAM_REMOTE_NAME}/${GITHUB_BASE_REF}\"\n          make -j2 examples && \\\n            cargo run --release -p print_sizes >'${{runner.temp}}/base-sizes' || \\\n            echo 'Broken build on the master branch.'\n\n      # Computes and displays the size diff. diff returns a nonzero status code\n      # if the files differ, and GitHub interprets a nonzero status code as an\n      # error. To avoid GitHub interpreting a difference as an error, we add\n      # || exit 0 to the command. This also prevents the workflow from failing\n      # if the master build is broken and we didn't generate base-sizes.\n      - name: Size diff\n        run: diff '${{runner.temp}}/base-sizes' '${{runner.temp}}/merge-sizes' || exit 0\n"
  },
  {
    "path": ".gitignore",
    "content": "/Cargo.lock\n/nightly/target\n/target\n/demos/*/target\n/demos/*/*/target\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"tock\"]\n\tpath = tock\n\turl = https://github.com/tock/tock.git\n"
  },
  {
    "path": ".ignore",
    "content": "# Cargo and GitHub Actions keep their configs in hidden directories. Some search\n# tools skip hidden directories by default. This overrides that, and makes them\n# search .cargo and .github.\n!.cargo/\n!.github/\n\n# Tell search tools to ignore the Tock submodule. Usually when someone wants to\n# search this repository they want to search libtock-rs' codebase, not the Tock\n# kernel.\n/tock/\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"editor.formatOnSave\": true,\n  \"rust.all_targets\": true,\n  \"rust.clippy_preference\": \"on\"\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Releases\n\n## 0.2.0 (WIP)\n\n### Comprehensive Changes\n\n- Many functions are asynchronous\n  - To create an `async` main function you can use the attribute `#[libtock::main]`\n  - To retrieve the value of an asynchronous `value`, use `value.await`\n  - This is only possible within an `async fn`, so either\n    - Make the caller `fn` of `.await` an `async fn`\n    - Not recommended: Use `libtock::executor::block_on(value)` to retrieve the `value`\n- Most API functions, including `main()`, return a `Result<T, TockError>`\n- All drivers can exclusively be retrieved by `retrieve_drivers` which returns a `Drivers` singleton. Drivers can be shared between different tasks only if it is safe to do so.\n- The low-level functions have been moved to a new crate called `libtock-core`. This crate is intended to be less experimental and more stable.\n\n### Changed APIs\n\n- The basic APIs have been made consistent. They are initialized via driver factories and no longer require a `WithCallback` object, s.t. the callback subscription is more intuitive. The affected APIs are:\n  - LEDs\n  - Buttons\n  - GPIO\n  - Temperature\n  - ADC (partially)\n- The timer API now supports concurrent sleep operations\n\n### Syscalls\n\n- `syscalls::subscribe` is actually usable\n- `syscalls::yieldk_for` is no longer available\n  - Yielding manually is discouraged as it conflicts with Rust's safety guarantees. If you need to wait for a condition, use `futures::wait_until` and `.await`.\n- `syscalls::yieldk` has become `unsafe` for the same reason\n- `syscalls::command` is no longer `unsafe`\n- The low-level syscalls have been moved to `syscalls::raw`\n  - `syscalls::subscribe_ptr` becomes `syscalls::raw::subscribe`\n  - `syscalls::allow_ptr` becomes `syscalls::raw::allow`\n\n### Miscellaneous\n\n- Flashing examples is no longer restricted to the nRF52 DK board\n  - `./run_example.sh` has been deleted\n  - Instead, use `PLATFORM=<platform> cargo r<arch> <your_app>`. This will build the app for your CPU architecture and platform-specific memory layout and flash it via J-Link to your board\n- Targets without support for atomics can be built\n- The `TockAllocator` is no longer included by default and needs to to be opted-in via `--features=alloc`\n- `hardware_test.rs` is now called `libtock_test.rs` to make clear that the intent is to test the correctness of `libtock-rs`, not the hardware or the kernel\n- The panic handler can now be customized using the `custom_panic_handler` feature\n- The error alloc handler can now be customized using the `custom_alloc_error_handler` feature\n\n## a8bb4fa9be504517d5533511fd8e607ea61f1750 (0.1.0)\n\n- First and highly experimental `libtock-rs` API\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Tests\n\nOur aim is to provide a number of tests to be safe from regression.\n\n## Compilation\n\n`libtock-rs` currently has the following compilation targets\n\n- `riscv32imac-unknown-none-elf`\n- `riscv32imc-unknown-none-elf`\n- `thumbv7em-none-eabi`\n\nYou can trigger a test build of the library and the examples using `make test`.\nYou can run the library's test suite using `make test`.\n\n# PR Review Workflow\n\nOur code review practices are documented in our [Code Review](doc/CodeReview.md)\ndocument.\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\ndescription = \"\"\"Tock Rust userspace library collection. Provides all the \\\n                 tools needed to create a Tock Rust process binary.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nname = \"libtock\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[workspace.package]\n# This must be kept in sync with rust-toolchain.toml; please see that file for\n# more information.\nrust-version = \"1.87\"\n\n[features]\nrust_embedded = [\n    \"embedded-hal\",\n    \"libtock_platform/rust_embedded\",\n    \"libtock_gpio/rust_embedded\",\n]\n\n[dependencies]\nlibtock_adc = { path = \"apis/peripherals/adc\" }\nlibtock_air_quality = { path = \"apis/sensors/air_quality\" }\nlibtock_alarm = { path = \"apis/peripherals/alarm\" }\nlibtock_ambient_light = { path = \"apis/sensors/ambient_light\" }\nlibtock_buttons = { path = \"apis/interface/buttons\" }\nlibtock_buzzer = { path = \"apis/interface/buzzer\" }\nlibtock_console = { path = \"apis/interface/console\" }\nlibtock_debug_panic = { path = \"panic_handlers/debug_panic\" }\nlibtock_gpio = { path = \"apis/peripherals/gpio\" }\nlibtock_i2c_master = { path = \"apis/peripherals/i2c_master\" }\nlibtock_ieee802154 = { path = \"apis/net/ieee802154\" }\nlibtock_i2c_master_slave = { path = \"apis/peripherals/i2c_master_slave\" }\nlibtock_key_value = { path = \"apis/storage/key_value\" }\nlibtock_leds = { path = \"apis/interface/leds\" }\nlibtock_low_level_debug = { path = \"apis/kernel/low_level_debug\" }\nlibtock_ninedof = { path = \"apis/sensors/ninedof\" }\nlibtock_platform = { path = \"platform\" }\nlibtock_proximity = { path = \"apis/sensors/proximity\" }\nlibtock_screen = { path = \"apis/display/screen\" }\nlibtock_rng = { path = \"apis/peripherals/rng\" }\nlibtock_runtime = { path = \"runtime\" }\nlibtock_small_panic = { path = \"panic_handlers/small_panic\" }\nlibtock_sound_pressure = { path = \"apis/sensors/sound_pressure\" }\nlibtock_spi_controller = { path = \"apis/peripherals/spi_controller\" }\nlibtock_temperature = { path = \"apis/sensors/temperature\" }\n\nembedded-hal = { version = \"1.0\", optional = true }\n\n[build-dependencies]\nlibtock_build_scripts = { path = \"build_scripts\" }\n\n[profile.dev]\ndebug = true\nlto = true\npanic = \"abort\"\n\n[profile.release]\ndebug = true\nlto = true\npanic = \"abort\"\nopt-level = \"z\"\ncodegen-units = 1\n\n[workspace]\nexclude = [\"tock\"]\nmembers = [\n    \"apis/interface/buttons\",\n    \"apis/interface/buzzer\",\n    \"apis/interface/console\",\n    \"apis/interface/leds\",\n    \"apis/kernel/low_level_debug\",\n    \"apis/peripherals/adc\",\n    \"apis/peripherals/alarm\",\n    \"apis/peripherals/gpio\",\n    \"apis/peripherals/i2c_master\",\n    \"apis/peripherals/i2c_master_slave\",\n    \"apis/peripherals/rng\",\n    \"apis/sensors/air_quality\",\n    \"apis/sensors/ambient_light\",\n    \"apis/sensors/ninedof\",\n    \"apis/display/screen\",\n    \"apis/sensors/proximity\",\n    \"apis/sensors/temperature\",\n    \"apis/storage/key_value\",\n    \"libraries/embedded_graphics_libtock\",\n    \"panic_handlers/debug_panic\",\n    \"panic_handlers/small_panic\",\n    \"platform\",\n    \"runner\",\n    \"runtime\",\n    \"syscalls_tests\",\n    \"tools/print_sizes\",\n    \"ufmt\",\n    \"unittest\",\n]\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2016 The Tock Project Developers\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "# Make uses /bin/sh by default, which is a different shell on different OSes.\n# Specify Bash instead so we don't have to test against a variety of shells.\nSHELL := /usr/bin/env bash\n\n# By default, let's print out some help\n.PHONY: usage\nusage:\n\t@echo \"$$(tput bold)Welcome to libtock-rs!$$(tput sgr0)\"\n\t@echo\n\t@echo \"First things first, if you haven't yet, check out Tocks's doc/Getting_Started.\"\n\t@echo \"After that read the README from libtock-rs\"\n\t@echo \"You'll need to install a few requirements before we get going.\"\n\t@echo\n\t@echo \"The next step is to choose a board to build Tock for. Mainline\"\n\t@echo \"libtock-rs currently includes support for the following platforms:\"\n\t@echo \" - apollo3\"\n\t@echo \" - clue_nrf52840\"\n\t@echo \" - esp32_c3_devkitm_1\"\n\t@echo \" - hail\"\n\t@echo \" - hifive1\"\n\t@echo \" - imxrt1050\"\n\t@echo \" - microbit_v2\"\n\t@echo \" - nrf52\"\n\t@echo \" - nrf52840\"\n\t@echo \" - nucleo_f429zi\"\n\t@echo \" - nucleo_f446re\"\n\t@echo \" - opentitan\"\n\t@echo \" - qemu_rv32_virt\"\n\t@echo \" - stm32f3discovery\"\n\t@echo \" - stm32f412gdiscovery\"\n\t@echo \" - esp32_c3_devkitm_1\"\n\t@echo \" - clue_nrf52840\"\n\t@echo \" - raspberry_pi_pico\"\n\t@echo \" - pico_explorer_base\"\n\t@echo\n\t@echo \"Run 'make setup' to setup Rust to build libtock-rs.\"\n\t@echo \"Run 'make <board> EXAMPLE=<>' to build EXAMPLE for that board.\"\n\t@echo \"Run 'make flash-<board> EXAMPLE=<>' to flash EXAMPLE to a tockloader-supported board.\"\n\t@echo \"Run 'make qemu-example EXAMPLE=<>' to run EXAMPLE in QEMU\"\n\t@echo \"Run 'make test' to test any local changes you have made\"\n\t@echo \"Run 'make print-sizes' to print size data for the example binaries\"\n\nifdef FEATURES\nfeatures=--features=$(FEATURES)\nendif\n\nifndef DEBUG\nrelease=--release\nartifact_dir=release\nelse\nartifact_dir=debug\nendif\n\n# Rustup currently lacks the locking needed for concurrent use:\n# https://github.com/rust-lang/rustup/issues/988. In particular, running\n# concurrent cargo commands with a missing toolchain results in parallel rustup\n# instances installing the same toolchain, corrupting that toolchain. To\n# mitigate that issue, every target that uses the main (MSRV) toolchain should\n# depend transitively on the `toolchain` target, so that the toolchain is\n# installed before it is invoked concurrently. Note that we don't need to do\n# this for the nightly toolchain because the nightly toolchain is only used by\n# the `test` target, so this Makefile won't invoke it concurrently.\n.PHONY: toolchain\ntoolchain:\n\tcargo -V\n\n.PHONY: setup\nsetup: setup-qemu toolchain\n\tcargo install elf2tab\n\n# Sets up QEMU in the tock/ directory. We use Tock's QEMU which may contain\n# patches to better support boards that Tock supports.\n.PHONY: setup-qemu\nsetup-qemu:\n\tCI=true $(MAKE) -C tock ci-setup-qemu\n\n# Builds a Tock 2.0 kernel for the HiFive board for use by QEMU tests.\n.PHONY: kernel-hifive\nkernel-hifive:\n\t$(MAKE) -C tock/boards/hifive1 \\\n\t\t$(CURDIR)/tock/target/riscv32imac-unknown-none-elf/release/hifive1.elf\n\n# Builds a Tock kernel for the OpenTitan board on the cw310 FPGA for use by QEMU\n# tests.\n.PHONY: kernel-opentitan\nkernel-opentitan:\n\tCARGO_TARGET_RISCV32IMC_UNKNOWN_NONE_ELF_RUNNER=\"[]\" \\\n\t\t$(MAKE) -C tock/boards/opentitan/earlgrey-cw310 \\\n\t\t$(CURDIR)/tock/target/riscv32imc-unknown-none-elf/release/earlgrey-cw310.elf\n\n# Prints out the sizes of the example binaries.\n.PHONY: print-sizes\nprint-sizes: examples toolchain\n\tcargo run --release -p print_sizes\n\n# Runs a libtock example in QEMU on a simulated HiFive board.\n.PHONY: qemu-example\nqemu-example: kernel-hifive toolchain\n\tLIBTOCK_PLATFORM=\"hifive1\" cargo run --example \"$(EXAMPLE)\" -p libtock \\\n\t\t--release --target=riscv32imac-unknown-none-elf -- --deploy qemu\n\n# Build the examples on both a RISC-V target and an ARM target. We pick\n# opentitan as the RISC-V target because it lacks atomics.\n.PHONY: examples\nexamples: toolchain\n\tLIBTOCK_PLATFORM=nrf52 cargo build --examples --release \\\n\t\t--target=thumbv7em-none-eabi\n\tLIBTOCK_PLATFORM=opentitan cargo build --examples --release \\\n\t\t--target=riscv32imc-unknown-none-elf\n\n# Arguments to pass to cargo to exclude crates that require a Tock runtime.\n# This is largely libtock_runtime and crates that depend on libtock_runtime.\n# Used when we need to build a crate for the host OS, as libtock_runtime only\n# supports running on Tock.\nEXCLUDE_RUNTIME := --exclude libtock --exclude libtock_runtime \\\n\t--exclude libtock_debug_panic --exclude libtock_small_panic --exclude embedded_graphics_libtock\n\n# Arguments to pass to cargo to exclude crates that cannot be tested by Miri. In\n# addition to excluding libtock_runtime, Miri also cannot test proc macro crates\n# (and in fact will generate broken data that causes cargo test to fail).\nEXCLUDE_MIRI := $(EXCLUDE_RUNTIME) --exclude ufmt-macros\n\n# Arguments to pass to cargo to exclude `std` and crates that depend on it. Used\n# when we build a crate for an embedded target, as those targets lack `std`.\nEXCLUDE_STD := --exclude libtock_unittest --exclude print_sizes \\\n               --exclude runner --exclude syscalls_tests \\\n               --exclude libtock_build_scripts\n\n.PHONY: test\ntest: examples\n\tcargo test $(EXCLUDE_RUNTIME) --workspace\n\tLIBTOCK_PLATFORM=nrf52 cargo fmt --all -- --check\n\tcargo clippy --all-targets $(EXCLUDE_RUNTIME) --workspace\n\tLIBTOCK_PLATFORM=nrf52 cargo clippy $(EXCLUDE_STD) \\\n\t\t--target=thumbv7em-none-eabi --workspace\n\tLIBTOCK_PLATFORM=hifive1 cargo clippy $(EXCLUDE_STD) \\\n\t\t--target=riscv32imac-unknown-none-elf --workspace\n\tcd nightly && \\\n\t\tMIRIFLAGS=\"-Zmiri-strict-provenance -Zmiri-symbolic-alignment-check\" \\\n\t\tcargo miri test $(EXCLUDE_MIRI) --manifest-path=../Cargo.toml \\\n\t\t--target-dir=target --workspace\n\techo '[ SUCCESS ] libtock-rs tests pass'\n\ninclude Targets.mk\n\n$(ELF_TARGETS): toolchain\n\tLIBTOCK_LINKER_FLASH=$(F) LIBTOCK_LINKER_RAM=$(R) cargo build --example $(EXAMPLE) $(features) --target=$(T) $(release)\n\t@mkdir -p target/$(A).$(F).$(R)/\n\t@cp target/$(T)/$(artifact_dir)/examples/$(EXAMPLE) target/$(A).$(F).$(R)/\n\t$(eval ELF_LIST += target/$(A).$(F).$(R)/$(EXAMPLE),$(A).$(F).$(R))\n# This target (`make tab`) is not parallel-safe\n.PHONY: tab\ntab: $(ELF_TARGETS)\n\tmkdir -p target/tab\n\telf2tab --kernel-major 2 --kernel-minor 1 -n $(EXAMPLE) -o target/tab/$(EXAMPLE).tab --stack 1024 --minimum-footer-size 256 $(ELF_LIST)\n\n# Creates the `make <BOARD> EXAMPLE=<EXAMPLE>` targets. Arguments:\n#  1) The name of the platform to build for.\n#  2) The target architecture the platform uses.\n#\n# A different --target-dir is passed for each platform to prevent race\n# conditions between concurrent cargo run invocations. See\n# https://github.com/tock/libtock-rs/issues/366 for more information.\ndefine platform_build\n.PHONY: $(1)\n$(1): toolchain\n\tLIBTOCK_PLATFORM=$(1) cargo run --example $(EXAMPLE) $(features) \\\n\t\t$(release) --target=$(2) --target-dir=target/$(1)\n\tmkdir -p target/tbf/$(1)\n\tcp target/$(1)/$(2)/release/examples/$(EXAMPLE).{tab,tbf} \\\n\t\ttarget/tbf/$(1)\nendef\n\n# Creates the `make flash-<BOARD> EXAMPLE=<EXAMPLE>` targets. Arguments:\n#  1) The name of the platform to flash for.\ndefine platform_flash\n.PHONY: flash-$(1)\nflash-$(1): toolchain\n\tLIBTOCK_PLATFORM=$(1) cargo run --example $(EXAMPLE) $(features) \\\n\t\t$(release) --target=$(2) --target-dir=target/flash-$(1) -- \\\n\t\t--deploy=tockloader\nendef\n\n$(eval $(call platform_build,apollo3,thumbv7em-none-eabi))\n$(eval $(call platform_build,esp32_c3_devkitm_1,riscv32imc-unknown-none-elf))\n$(eval $(call platform_build,hail,thumbv7em-none-eabi))\n$(eval $(call platform_flash,hail,thumbv7em-none-eabi))\n$(eval $(call platform_build,imix,thumbv7em-none-eabi))\n$(eval $(call platform_flash,imix,thumbv7em-none-eabi))\n$(eval $(call platform_build,microbit_v2,thumbv7em-none-eabi))\n$(eval $(call platform_flash,microbit_v2,thumbv7em-none-eabi))\n$(eval $(call platform_build,nucleo_f429zi,thumbv7em-none-eabi))\n$(eval $(call platform_build,nucleo_f446re,thumbv7em-none-eabi))\n$(eval $(call platform_build,nrf52840,thumbv7em-none-eabi))\n$(eval $(call platform_flash,nrf52840,thumbv7em-none-eabi))\n$(eval $(call platform_build,raspberry_pi_pico,thumbv6m-none-eabi))\n$(eval $(call platform_build,pico_explorer_base,thumbv6m-none-eabi))\n$(eval $(call platform_build,nano33ble,thumbv6m-none-eabi))\n$(eval $(call platform_build,nano_rp2040_connect,thumbv6m-none-eabi))\n$(eval $(call platform_build,qemu_rv32_virt,riscv32imac-unknown-none-elf))\n$(eval $(call platform_build,stm32f3discovery,thumbv7em-none-eabi))\n$(eval $(call platform_build,stm32f412gdiscovery,thumbv7em-none-eabi))\n$(eval $(call platform_build,opentitan,riscv32imc-unknown-none-elf))\n$(eval $(call platform_build,hifive1,riscv32imac-unknown-none-elf))\n$(eval $(call platform_build,nrf52,thumbv7em-none-eabi))\n$(eval $(call platform_flash,nrf52,thumbv7em-none-eabi))\n$(eval $(call platform_build,imxrt1050,thumbv7em-none-eabi))\n$(eval $(call platform_build,msp432,thumbv7em-none-eabi))\n$(eval $(call platform_build,clue_nrf52840,thumbv7em-none-eabi))\n$(eval $(call platform_flash,clue_nrf52840,thumbv7em-none-eabi))\n\n.PHONY: demos\ndemos:\n\t$(MAKE) -C demos/embedded_graphics/spin\n\t$(MAKE) -C demos/embedded_graphics/buttons\n\t$(MAKE) -C demos/st7789\n\t$(MAKE) -C demos/st7789-slint\n\n# clean cannot safely be invoked concurrently with other actions, so we don't\n# need to depend on toolchain. We also manually remove the nightly toolchain's\n# target directory, in case the user doesn't want to install the nightly\n# toolchain.\n.PHONY: clean\nclean:\n\tcargo clean\n\trm -fr nightly/target/\n\tcd demos/st7789 && cargo clean\n\t$(MAKE) -C tock clean\n"
  },
  {
    "path": "README.md",
    "content": "![Build Status](https://github.com/tock/libtock-rs/workflows/ci/badge.svg)\n\n# libtock-rs\n\nRust userland library for Tock\n\nGenerally this library was tested with Tock [Release\n2.1.1](https://github.com/tock/tock/releases/tag/release-2.1.1).\n\nThe library should work on all Tock boards, but currently apps must be compiled\nfor the flash and RAM address they are executed at. See [Fix\nrelocation](https://github.com/tock/libtock-rs/issues/28) for more details. You\nmay either compile a process binary especially for your board and use only a\nsingle application written in rust at a time, or use the `make tab` target that\nbuilds examples for a series of likely useful flash and RAM addresses.\n\n## Getting Started\n\n1.  Ensure you have [rustup](https://www.rustup.rs/) installed.\n\n1.  Clone the repository:\n\n    ```shell\n    git clone --recursive https://github.com/tock/libtock-rs\n    cd libtock-rs\n    ```\n\n1.  Install the dependencies:\n\n    ```shell\n    make setup\n    ```\n\n1.  Use `make` to build examples\n\n    ```shell\n    make nrf52 EXAMPLE=console # Builds the console example for the nrf52\n    ```\n\n## Using libtock-rs\n\nThe easiest way to start using libtock-rs is adding an example to the\n`examples/` folder. We recommend starting by copying the `console` example, as\nit is a simple example that shows you how to perform normal debug prints.\n\n### Building for a specific board\n\nTo build your example for your board you can use\n\n```shell\nmake <platform> EXAMPLE=<example>\n```\n\nAn example can be flashed to your board after the build process by running:\n\n```shell\nmake flash-<platform> EXAMPLE=<example>\n```\n\nThis script does the following steps for you:\n\n- cross-compile your program\n- create a TAB (tock application bundle)\n- if you have a J-Link compatible board connected: flash this TAB to your board (using tockloader)\n\n### Enabling rust-embedded support\n\nlibtock-rs can be built to be compatible with the rust-embedded\n[embedded_hal](https://docs.rs/embedded-hal/1.0.0/embedded_hal/index.html) by\nincluding the following when running `make`\n\n```shell\nFEATURES=rust_embedded\n```\n\nIf using libtock-rs or a sub-crate as a cargo dependency the `rust_embedded`\ncan also be enabled via Cargo.\n\n### Building a generic TAB (Tock Application Bundle) file\n\nTo build your example for a variety of boards you can use\n\n```shell\nmake tab EXAMPLE=<example>\n```\n\nTo install the tab use tockloader\n\n```shell\ntockloader install target/tab/<example.tab>\n```\n\nTockloader will determine which compiled version with the correct flash and RAM\naddresses to use.\n\n\n## License\n\nlibtock-rs is licensed under either of\n\n- Apache License, Version 2.0\n  ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n- MIT license\n  ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\nSubmodules, as well as the code in the `ufmt` directory, have their own licenses.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n\nThe contribution guidelines can be found here: [contribution guidelines](CONTRIBUTING.md)\n"
  },
  {
    "path": "Targets.mk",
    "content": "# Helper makefile to define build location targets for many common tock\n# platforms.\n#\n# To use:\n#\n#     include Targets.mk\n\n# Helper functions to define make targets to build for specific (flash, ram,\n# target) compilation tuples.\n#\n# Inspiration from these answers:\n# - https://stackoverflow.com/a/50357925\n# - https://stackoverflow.com/a/9458230\n#\n# To create a compilation target for a specific architecture with specific flash\n# and RAM addresses, use `fixed-target`:\n#\n# ```\n# $(call fixed-target, F=0x00030000 R=0x20008000 T=thumbv7em-none-eabi A=cortex-m4)\n# ```\n#\n# The \"arguments\" if you will are:\n# - F = Flash Address: The address in flash the app is compiled for.\n# - R = RAM Address: The address in RAM the app is compiled for.\n# - T = Target: The cargo target to compile for.\n# - A = Architecture: The Tock architecture name the target corresponds to.\n#\n# This technique uses two make variables internally to keep track of state:\n# - `ELF_TARGETS`: This is the list of unique targets for each compilation\n#   tuple. Each target invokes `cargo build` with the specified settings.\n# - `ELF_LIST`: The is a list of .elf paths of the generated elfs (one per\n#   compilation tuple). This is passed to `elf2tab` to generate the output .tab\n#   file.\n#\n# Internally, what `fixed-target` does is define a new make target named the\n# join of all of the F/R/T/A variables (with the `=` characters removed) and\n# then assigns target variables to that new target to represent the compilation\n# tuple values.\nconcat = $(subst =,,$(subst $(eval ) ,,$1))\nfixed-target = $(foreach A,$1,$(eval $(call concat,$1): $A)) $(eval ELF_TARGETS += $(call concat,$1))\n\n$(call fixed-target, F=0x00030000 R=0x20008000 T=thumbv7em-none-eabi A=cortex-m4)\n$(call fixed-target, F=0x00038000 R=0x20010000 T=thumbv7em-none-eabi A=cortex-m4)\n\n$(call fixed-target, F=0x00040000 R=0x10002000 T=thumbv7em-none-eabi A=cortex-m4)\n$(call fixed-target, F=0x00048000 R=0x1000a000 T=thumbv7em-none-eabi A=cortex-m4)\n\n$(call fixed-target, F=0x00040000 R=0x20008000 T=thumbv7em-none-eabi A=cortex-m4)\n$(call fixed-target, F=0x00042000 R=0x2000a000 T=thumbv7em-none-eabi A=cortex-m4)\n$(call fixed-target, F=0x00048000 R=0x20010000 T=thumbv7em-none-eabi A=cortex-m4)\n\n$(call fixed-target, F=0x00080000 R=0x20006000 T=thumbv7em-none-eabi A=cortex-m4)\n$(call fixed-target, F=0x00088000 R=0x2000e000 T=thumbv7em-none-eabi A=cortex-m4)\n\n$(call fixed-target, F=0x403b0000 R=0x3fca2000 T=riscv32imc-unknown-none-elf A=rv32imc)\n$(call fixed-target, F=0x40440000 R=0x3fcaa000 T=riscv32imc-unknown-none-elf A=rv32imc)\n\n$(call fixed-target, F=0x80100000 R=0x80300000 T=riscv32imac-unknown-none-elf A=rv32imac)\n$(call fixed-target, F=0x80110000 R=0x80310000 T=riscv32imac-unknown-none-elf A=rv32imac)\n$(call fixed-target, F=0x80130000 R=0x80330000 T=riscv32imac-unknown-none-elf A=rv32imac)\n$(call fixed-target, F=0x80180000 R=0x80380000 T=riscv32imac-unknown-none-elf A=rv32imac)\n\n$(call fixed-target, F=0x10020000 R=0x20004000 T=thumbv6m-none-eabi A=cortex-m0)\n$(call fixed-target, F=0x10028000 R=0x2000c000 T=thumbv6m-none-eabi A=cortex-m0)\n\n$(call fixed-target, F=0x10040000 R=0x20020000 T=thumbv8m.main-none-eabi A=cortex-m33)\n$(call fixed-target, F=0x10060000 R=0x20028000 T=thumbv8m.main-none-eabi A=cortex-m33)"
  },
  {
    "path": "apis/display/screen/Cargo.toml",
    "content": "[package]\nname = \"libtock_screen\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock display driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }"
  },
  {
    "path": "apis/display/screen/src/lib.rs",
    "content": "#![no_std]\nuse core::cell::Cell;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock_platform::share;\nuse libtock_platform::subscribe::Subscribe;\nuse libtock_platform::{self as platform, DefaultConfig};\nuse libtock_platform::{ErrorCode, Syscalls};\n\npub struct Screen<S: Syscalls, C: Config = DefaultConfig>(S, C);\n\nimpl<S: Syscalls, C: Config> Screen<S, C> {\n    /// Check if the Screen driver exists\n    pub fn exists() -> Result<(), ErrorCode> {\n        let val = S::command(DRIVER_NUM, command::EXISTS, 0, 0).is_success();\n        if val {\n            Ok(())\n        } else {\n            Err(ErrorCode::Fail)\n        }\n    }\n\n    /// Perform initial screen setup\n    pub fn screen_setup() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, command::SCREEN_SETUP, 0, 0).to_result()\n    }\n\n    /// Turn on Screen power\n    pub fn set_power(value: usize) -> Result<(), ErrorCode> {\n        if value != 0 {\n            S::command(DRIVER_NUM, command::SET_POWER, value as u32, 0).to_result()\n        } else {\n            Err(ErrorCode::Invalid)\n        }\n    }\n\n    /// Set screen brightness, wait for completion via subscribe\n    pub fn set_brightness(value: usize) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(DRIVER_NUM, command::SET_BRIGHTNESS, value as u32, 0)\n                .to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Turn on screen color inversion\n    pub fn set_invert_on() -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(DRIVER_NUM, command::SET_INVERT_ON, 0, 0).to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Turn off screen color inversion\n    pub fn set_invert_off() -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(DRIVER_NUM, command::SET_INVERT_OFF, 0, 0).to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Set inversion using a numeric value (non-zero = on)\n    pub fn set_invert(value: usize) -> Result<(), ErrorCode> {\n        if value != 0 {\n            S::command(DRIVER_NUM, command::SET_INVERT, value as u32, 0).to_result()\n        } else {\n            Err(ErrorCode::Invalid)\n        }\n    }\n\n    /// Get the number of supported resolution modes\n    pub fn get_resolution_modes_count() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_RESOLUTION_MODES_COUNT, 0, 0).to_result()\n    }\n\n    /// Get width and height for a given resolution index\n    pub fn get_resolution_width_height(index: usize) -> Result<(u32, u32), ErrorCode> {\n        S::command(\n            DRIVER_NUM,\n            command::GET_RESOLUTION_WIDTH_HEIGHT,\n            index as u32,\n            0,\n        )\n        .to_result()\n    }\n\n    /// Get the number of supported pixel modes\n    pub fn pixel_modes_count() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, command::PIXEL_MODES_COUNT, 0, 0).to_result()\n    }\n\n    /// Get the pixel format at a specific index\n    pub fn pixel_format(index: usize) -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, command::PIXEL_FORMAT, index as u32, 0).to_result()\n    }\n\n    /// Get the current rotation of the screen\n    pub fn get_rotation() -> Result<u32, ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            let val = S::command(DRIVER_NUM, command::GET_ROTATION, 0, 0).to_result();\n            val?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return val;\n                }\n            }\n        })\n    }\n\n    /// Set the screen rotation\n    pub fn set_rotation(rotation: usize) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(DRIVER_NUM, command::SET_ROTATION, rotation as u32, 0)\n                .to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Get the currently set screen resolution\n    pub fn get_resolution() -> Result<(u32, u32), ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_RESOLUTION, 0, 0).to_result()\n    }\n\n    /// Set the screen resolution\n    pub fn set_resolution(width: usize, height: usize) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(\n                DRIVER_NUM,\n                command::SET_RESOLUTION,\n                width as u32,\n                height as u32,\n            )\n            .to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Get the currently set pixel format\n    pub fn get_pixel_format() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_PIXEL_FORMAT, 0, 0).to_result()\n    }\n\n    /// Set the pixel format\n    pub fn set_pixel_format(format: usize) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(DRIVER_NUM, command::SET_PIXEL_FORMAT, format as u32, 0)\n                .to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Define the region of the screen that will be written to\n    pub fn set_write_frame(x: u32, y: u32, width: u32, height: u32) -> Result<(), ErrorCode> {\n        let data1: u32 = ((x & 0xFFFF) << 16_u8) | (y & 0xFFFF);\n        let data2: u32 = ((width & 0xFFFF) << 16_u8) | (height & 0xFFFF);\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(DRIVER_NUM, command::SET_WRITE_FRAME, data1, data2).to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Write data to the screen using the given buffer\n    pub fn write(s: &[u8]) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::WRITE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_ro, subscribe) = handle.split();\n            S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>(allow_ro, s)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n            S::command(DRIVER_NUM, command::WRITE, s.len() as u32, 0).to_result::<(), _>()?;\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Fill the screen\n    pub fn fill(s: &mut [u8], color: u16) -> Result<(), ErrorCode> {\n        if s.len() >= 2 {\n            s[0] = ((color >> 8) & 0xFF) as u8;\n            s[1] = (color & 0xFF) as u8;\n\n            let called: Cell<Option<(u32,)>> = Cell::new(None);\n            share::scope::<\n                (\n                    AllowRo<_, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>,\n                    Subscribe<_, DRIVER_NUM, { subscribe::WRITE }>,\n                ),\n                _,\n                _,\n            >(|handle| {\n                let (allow_ro, subscribe) = handle.split();\n                S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE_BUFFER_ID }>(allow_ro, s)?;\n                S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n                S::command(DRIVER_NUM, command::FILL, 0, 0).to_result::<(), _>()?;\n                loop {\n                    S::yield_wait();\n                    if let Some((_,)) = called.get() {\n                        return Ok(());\n                    }\n                }\n            })\n        } else {\n            Err(ErrorCode::Fail)\n        }\n    }\n}\n\npub trait Config:\n    platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config\n{\n}\n\nimpl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>\n    Config for T\n{\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x90001;\n\n// Command IDs\n#[allow(unused)]\nmod command {\n    pub const EXISTS: u32 = 0;\n    pub const SCREEN_SETUP: u32 = 1;\n    pub const SET_POWER: u32 = 2;\n    pub const SET_BRIGHTNESS: u32 = 3;\n    pub const SET_INVERT_ON: u32 = 4;\n    pub const SET_INVERT_OFF: u32 = 5;\n    pub const SET_INVERT: u32 = 6;\n    pub const GET_RESOLUTION_MODES_COUNT: u32 = 11;\n    pub const GET_RESOLUTION_WIDTH_HEIGHT: u32 = 12;\n    pub const PIXEL_MODES_COUNT: u32 = 13;\n    pub const PIXEL_FORMAT: u32 = 14;\n    pub const GET_ROTATION: u32 = 21;\n    pub const SET_ROTATION: u32 = 22;\n    pub const GET_RESOLUTION: u32 = 23;\n    pub const SET_RESOLUTION: u32 = 24;\n    pub const GET_PIXEL_FORMAT: u32 = 25;\n    pub const SET_PIXEL_FORMAT: u32 = 26;\n    pub const SET_WRITE_FRAME: u32 = 100;\n    pub const WRITE: u32 = 200;\n    pub const FILL: u32 = 300;\n}\n\n// Subscribe ID used for callbacks\nmod subscribe {\n    pub const WRITE: u32 = 0;\n}\n\n// Allow-readonly buffer ID\nmod allow_ro {\n    pub const WRITE_BUFFER_ID: u32 = 0;\n}\n"
  },
  {
    "path": "apis/display/screen/src/tests.rs",
    "content": "use libtock_platform::ErrorCode;\nuse libtock_unittest::{fake, ExpectedSyscall};\n\ntype Screen = super::Screen<fake::Syscalls>;\n\n#[test]\n// Test fails when no screen driver is registered.\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Screen::exists(), Err(ErrorCode::Fail))\n}\n#[test]\n// Test passes when screen driver is present.\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::exists(), Ok(()));\n}\n\n#[test]\n// Tests basic screen setup returns expected value (3).\nfn screen_setup() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::screen_setup(), Ok(3));\n}\n\n#[test]\n// Tests setting screen power to ON.\nfn set_power() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::set_power(1), Ok(()));\n}\n\n#[test]\n// Tests setting brightness.\nfn set_brightness() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_brightness(90), Ok(()));\n}\n\n#[test]\n// Turns inversion ON.\nfn set_invert_on() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_invert_on(), Ok(()));\n}\n\n#[test]\n// Turns inversion OFF.\nfn set_invert_off() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_invert_off(), Ok(()));\n}\n\n#[test]\n// Tests invert value.\nfn set_invert() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::set_invert(2), Ok(()));\n}\n\n#[test]\n// Checks number of supported resolution modes.\nfn get_resolution_modes_count() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::get_resolution_modes_count(), Ok(2));\n}\n\n#[test]\n// Tests fetching resolutions for indices 0-2.\nfn get_resolution_width_height() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::get_resolution_width_height(0), Ok((1920, 1080)));\n    assert_eq!(Screen::get_resolution_width_height(1), Ok((2560, 1440)));\n    assert_eq!(Screen::get_resolution_width_height(2), Ok((1280, 720)));\n}\n#[test]\n// Invalid resolution index returns error.\nfn get_resolution_width_height_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(\n        Screen::get_resolution_width_height(3),\n        Err(ErrorCode::Invalid)\n    );\n}\n#[test]\n// Checks total available pixel modes.\nfn pixel_modes_count() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::pixel_modes_count(), Ok(5));\n}\n\n#[test]\n// Gets pixel format for valid indices.\nfn get_screen_pixel_format_success() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::pixel_format(0), Ok(332));\n    assert_eq!(Screen::pixel_format(1), Ok(565));\n}\n\n#[test]\n// Invalid index returns error.\nfn get_screen_pixel_format_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::pixel_format(8), Err(ErrorCode::Invalid));\n}\n\n#[test]\n// Sets screen rotation.\nfn set_rotation_success() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_rotation(30), Ok(()));\n}\n\n#[test]\n// Invalid rotation (>=360 degrees) fails.\nfn set_rotation_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::set_rotation(360), Err(ErrorCode::Invalid));\n}\n\n#[test]\n// Sets and then reads rotation.\nfn get_rotation_success() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_rotation(30), Ok(()));\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::get_rotation(), Ok(30));\n}\n\n#[test]\n// Gets default rotation (0) without prior set.\nfn get_rotation_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::get_rotation(), Ok(0));\n}\n\n#[test]\n// Sets resolution to custom dimensions.\nfn set_resolution() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_resolution(360, 720), Ok(()));\n}\n\n#[test]\n// Verifies resolution was correctly set and retrieved.\nfn get_resolution_sucess() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_resolution(360, 720), Ok(()));\n    assert_eq!(Screen::get_resolution(), Ok((360, 720)));\n}\n\n#[test]\n// Returns (0,0) when no resolution was set.\nfn get_resolution_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::get_resolution(), Ok((0, 0)));\n}\n\n#[test]\n// Sets pixel format.\nfn set_pixel_format() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_pixel_format(2), Ok(()));\n}\n\n#[test]\n// Retrieves the pixel format that was previously set.\nfn get_pixel_format_success() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n    assert_eq!(Screen::set_pixel_format(2), Ok(()));\n    assert_eq!(Screen::get_pixel_format(), Ok(2));\n}\n\n#[test]\n// Returns 0 if format was never set.\nfn get_pixel_format_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::get_pixel_format(), Ok(0));\n}\n\n#[test]\n// Sets the region of screen to write pixels to.\nfn set_write_frame() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Screen::set_write_frame(10, 20, 30, 30), Ok(()));\n}\n\n#[test]\n// Writes pixel data to screen using a buffer.\nfn write_buffer() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    let _ = Screen::set_pixel_format(2);\n    let buffer = [0u8; 4];\n\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: 0x90001,\n        buffer_num: 0,\n        return_error: None,\n    });\n\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n\n    assert_eq!(Screen::write(&buffer), Ok(()));\n}\n\n#[test]\nfn fill_success() {\n    // Fills buffer with a color and writes to screen.\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    let _ = Screen::set_pixel_format(2);\n    let mut buffer = [0u8; 2];\n    let color = 0xF800;\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: 0x90001,\n        buffer_num: 0,\n        return_error: None,\n    });\n\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n\n    assert_eq!(Screen::fill(&mut buffer, color), Ok(()));\n}\n\n#[test]\nfn fill_fail() {\n    // Buffer too small causes fill failure.\n    let kernel = fake::Kernel::new();\n    let driver = fake::Screen::new();\n    kernel.add_driver(&driver);\n    let _ = Screen::set_pixel_format(2);\n    let mut buffer = [0u8; 1];\n    let color = 0xF800;\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: 0x90001,\n        buffer_num: 0,\n        return_error: None,\n    });\n\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 0x90001,\n        subscribe_num: 0,\n        skip_with_error: None,\n    });\n\n    assert_eq!(Screen::fill(&mut buffer, color), Err(ErrorCode::Fail));\n}\n"
  },
  {
    "path": "apis/interface/buttons/Cargo.toml",
    "content": "[package]\nname = \"libtock_buttons\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2018\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock buttons driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/interface/buttons/src/lib.rs",
    "content": "#![no_std]\n\nuse libtock_platform::{\n    share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\n/// The Buttons driver\n///\n/// # Example\n/// ```ignore\n/// use libtock::Buttons;\n///\n/// // Read button state\n/// Buttons::is_pressed(0);\n///\n/// // Register for events\n///\n/// let listener = ButtonListener(|button, state| {\n///     // make use of the button's state\n/// });\n///\n/// share::scope(|subscribe| {\n///     if let Ok(()) = Buttons::register_listener(&listener, subscribe) {\n///         // yield\n///     }\n/// });\n/// ```\npub struct Buttons<S: Syscalls>(S);\n\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\npub enum ButtonState {\n    Pressed,\n    Released,\n}\n\nimpl From<u32> for ButtonState {\n    fn from(value: u32) -> ButtonState {\n        match value {\n            0 => ButtonState::Released,\n            _ => ButtonState::Pressed,\n        }\n    }\n}\n\nimpl<S: Syscalls> Buttons<S> {\n    /// Run a check against the buttons capsule to ensure it is present.\n    ///\n    /// Returns `Ok(number_of_buttons)` if the driver was present. This does not necessarily mean\n    /// that the driver is working.\n    pub fn count() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, BUTTONS_COUNT, 0, 0).to_result()\n    }\n\n    /// Read the state of a button\n    pub fn read(button: u32) -> Result<ButtonState, ErrorCode> {\n        let button_state: u32 = S::command(DRIVER_NUM, BUTTONS_READ, button, 0).to_result()?;\n        Ok(button_state.into())\n    }\n\n    /// Returns `true` if a button is pressed\n    ///\n    /// This function returns `false` if:\n    /// - the button is released\n    /// - the button number is invalid\n    /// - there is an error\n    pub fn is_pressed(button: u32) -> bool {\n        Self::read(button)\n            .map(|state| state == ButtonState::Pressed)\n            .unwrap_or(false)\n    }\n\n    /// Returns `true` if a button is released\n    ///\n    /// This function returns `false` if:\n    /// - the button is pressed\n    /// - the button number is invalid\n    /// - there is an error\n    pub fn is_released(button: u32) -> bool {\n        Self::read(button)\n            .map(|state| state == ButtonState::Released)\n            .unwrap_or(false)\n    }\n\n    /// Enable events (interrupts) for a button\n    pub fn enable_interrupts(button: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, BUTTONS_ENABLE_INTERRUPTS, button, 0).to_result()\n    }\n\n    /// Disable events (interrupts) for a button\n    pub fn disable_interrupts(button: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, BUTTONS_DISABLE_INTERRUPTS, button, 0).to_result()\n    }\n\n    /// Register an events listener\n    ///\n    /// There can be only one single listener registered at a time.\n    /// Each time this function is used, it will replace the\n    /// previously registered listener.\n    pub fn register_listener<'share, F: Fn(u32, ButtonState)>(\n        listener: &'share ButtonListener<F>,\n        subscribe: Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    ///\n    /// This function may be used even if there was no\n    /// previously registered listener.\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n}\n\n/// A wrapper around a closure to be registered and called when\n/// a button event occurs.\n///\n/// ```ignore\n/// let listener = ButtonListener(|button, state| {\n///     // make use of the button's state\n/// });\n/// ```\npub struct ButtonListener<F: Fn(u32, ButtonState)>(pub F);\n\nimpl<F: Fn(u32, ButtonState)> Upcall<OneId<DRIVER_NUM, 0>> for ButtonListener<F> {\n    fn upcall(&self, button_index: u32, state: u32, _arg2: u32) {\n        self.0(button_index, state.into())\n    }\n}\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x3;\n\n// Command IDs\nconst BUTTONS_COUNT: u32 = 0;\n\nconst BUTTONS_ENABLE_INTERRUPTS: u32 = 1;\nconst BUTTONS_DISABLE_INTERRUPTS: u32 = 2;\n\nconst BUTTONS_READ: u32 = 3;\n"
  },
  {
    "path": "apis/interface/buttons/src/tests.rs",
    "content": "use core::cell::Cell;\n\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\nuse crate::{ButtonListener, ButtonState};\n\ntype Buttons = super::Buttons<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Buttons::count(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn num_buttons() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Buttons::<10>::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Buttons::count(), Ok(10));\n}\n\n#[test]\nfn read() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Buttons::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(driver.set_pressed(0, true), Ok(()));\n    assert_eq!(Buttons::read(0), Ok(ButtonState::Pressed));\n\n    assert_eq!(driver.set_pressed(0, false), Ok(()));\n    assert_eq!(Buttons::read(0), Ok(ButtonState::Released));\n\n    assert_eq!(Buttons::read(11), Err(ErrorCode::Invalid));\n}\n\n#[test]\nfn interrupts() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Buttons::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Buttons::enable_interrupts(0), Ok(()));\n    assert!(driver.get_button_state(0).unwrap().interrupt_enabled);\n\n    assert_eq!(Buttons::disable_interrupts(0), Ok(()));\n    assert!(!driver.get_button_state(0).unwrap().interrupt_enabled);\n\n    assert_eq!(Buttons::enable_interrupts(11), Err(ErrorCode::Invalid));\n    assert_eq!(Buttons::disable_interrupts(11), Err(ErrorCode::Invalid));\n}\n\n#[test]\nfn subscribe() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Buttons::<10>::new();\n    kernel.add_driver(&driver);\n\n    let pressed_interrupt_count: Cell<bool> = Cell::new(false);\n    let listener = ButtonListener(|button, state| {\n        assert_eq!(button, 0);\n        assert_eq!(state, ButtonState::Pressed);\n        pressed_interrupt_count.set(true);\n    });\n    assert_eq!(Buttons::enable_interrupts(0), Ok(()));\n    share::scope(|subscribe| {\n        assert_eq!(Buttons::register_listener(&listener, subscribe), Ok(()));\n        assert_eq!(driver.set_pressed(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    });\n    assert!(pressed_interrupt_count.get());\n\n    let pressed_interrupt_count: Cell<u32> = Cell::new(0);\n    let expected_button_state: Cell<ButtonState> = Cell::new(ButtonState::Released);\n    let listener = ButtonListener(|button, state| {\n        assert_eq!(button, 1);\n        assert_eq!(state, expected_button_state.get());\n        pressed_interrupt_count.set(pressed_interrupt_count.get() + 1);\n    });\n    share::scope(|subscribe| {\n        assert_eq!(Buttons::enable_interrupts(1), Ok(()));\n        assert_eq!(Buttons::register_listener(&listener, subscribe), Ok(()));\n        expected_button_state.set(ButtonState::Pressed);\n        assert_eq!(driver.set_pressed(1, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(driver.set_pressed(1, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        expected_button_state.set(ButtonState::Released);\n        assert_eq!(driver.set_pressed(1, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(driver.set_pressed(1, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(Buttons::disable_interrupts(1), Ok(()));\n        assert_eq!(driver.set_pressed(1, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(driver.set_pressed(1, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n    assert_eq!(pressed_interrupt_count.get(), 2);\n\n    let pressed_interrupt_count: Cell<bool> = Cell::new(false);\n    let listener = ButtonListener(|_, _| {\n        pressed_interrupt_count.set(true);\n    });\n    share::scope(|subscribe| {\n        assert_eq!(Buttons::enable_interrupts(0), Ok(()));\n        assert_eq!(Buttons::register_listener(&listener, subscribe), Ok(()));\n        Buttons::unregister_listener();\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n    assert!(!pressed_interrupt_count.get());\n}\n"
  },
  {
    "path": "apis/interface/buzzer/Cargo.toml",
    "content": "[package]\nname = \"libtock_buzzer\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock buzzer driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/interface/buzzer/src/lib.rs",
    "content": "//! Implementation started by : https://github.com/teodorobert\n//! Continued and modified by : https://github.com/SheepSeb\n#![no_std]\n\nuse core::cell::Cell;\nuse core::time::Duration;\n\nuse libtock_platform::{\n    share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\npub struct Buzzer<S: Syscalls>(S);\n\nimpl<S: Syscalls> Buzzer<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Initiate a tone\n    pub fn tone(freq: u32, duration: Duration) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, BUZZER_ON, freq, duration.as_millis() as u32).to_result()\n    }\n\n    /// Register an events listener\n    pub fn register_listener<'share, F: Fn(u32)>(\n        listener: &'share BuzzerListener<F>,\n        subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Initiate a synchronous tone\n    /// Returns Ok() if the operation was successful\n    pub fn tone_sync(freq: u32, duration: Duration) -> Result<(), ErrorCode> {\n        let buzzer_cell: Cell<Option<u32>> = Cell::new(None);\n        let listener = BuzzerListener(|buzzer_val| {\n            buzzer_cell.set(Some(buzzer_val));\n        });\n        share::scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            Self::tone(freq, duration)?;\n            while buzzer_cell.get().is_none() {\n                S::yield_wait();\n            }\n            match buzzer_cell.get() {\n                None => Err(ErrorCode::Fail),\n                Some(_) => Ok(()),\n            }\n        })\n    }\n}\n\npub struct BuzzerListener<F: Fn(u32)>(pub F);\nimpl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for BuzzerListener<F> {\n    fn upcall(&self, _arg0: u32, _arg1: u32, _arg2: u32) {\n        (self.0)(_arg0);\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x90000;\n\n// Command IDs\nconst EXISTS: u32 = 0;\nconst BUZZER_ON: u32 = 1;\n\n/// The notes that can be played by the buzzer\n#[allow(unused)]\n#[repr(u32)]\n#[derive(Copy, Clone, Debug)]\npub enum Note {\n    B0 = 31,\n    C1 = 33,\n    CS1 = 35,\n    D1 = 37,\n    DS1 = 39,\n    E1 = 41,\n    F1 = 44,\n    FS1 = 46,\n    G1 = 49,\n    GS1 = 52,\n    A1 = 55,\n    AS1 = 58,\n    B1 = 62,\n    C2 = 65,\n    CS2 = 69,\n    D2 = 73,\n    DS2 = 78,\n    E2 = 82,\n    F2 = 87,\n    FS2 = 93,\n    G2 = 98,\n    GS2 = 104,\n    A2 = 110,\n    AS2 = 117,\n    B2 = 123,\n    C3 = 131,\n    CS3 = 139,\n    D3 = 147,\n    DS3 = 156,\n    E3 = 165,\n    F3 = 175,\n    FS3 = 185,\n    G3 = 196,\n    GS3 = 208,\n    A3 = 220,\n    AS3 = 233,\n    B3 = 247,\n    C4 = 262,\n    CS4 = 277,\n    D4 = 294,\n    DS4 = 311,\n    E4 = 330,\n    F4 = 349,\n    FS4 = 370,\n    G4 = 392,\n    GS4 = 415,\n    A4 = 440,\n    AS4 = 466,\n    B4 = 494,\n    C5 = 523,\n    CS5 = 554,\n    D5 = 587,\n    DS5 = 622,\n    E5 = 659,\n    F5 = 698,\n    FS5 = 740,\n    G5 = 784,\n    GS5 = 831,\n    A5 = 880,\n    AS5 = 932,\n    B5 = 988,\n    C6 = 1047,\n    CS6 = 1109,\n    D6 = 1175,\n    DS6 = 1245,\n    E6 = 1319,\n    F6 = 1397,\n    FS6 = 1480,\n    G6 = 1568,\n    GS6 = 1661,\n    A6 = 1760,\n    AS6 = 1865,\n    B6 = 1976,\n    C7 = 2093,\n    CS7 = 2217,\n    D7 = 2349,\n    DS7 = 2489,\n    E7 = 2637,\n    F7 = 2794,\n    FS7 = 2960,\n    G7 = 3136,\n    GS7 = 3322,\n    A7 = 3520,\n    AS7 = 3729,\n    B7 = 3951,\n    C8 = 4186,\n    CS8 = 4435,\n    D8 = 4699,\n    DS8 = 4978,\n}\n"
  },
  {
    "path": "apis/interface/buzzer/src/tests.rs",
    "content": "use core::time::Duration;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::fake;\n\ntype Buzzer = super::Buzzer<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Buzzer::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Buzzer::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Buzzer::exists(), Ok(()));\n}\n\n#[test]\nfn tone() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Buzzer::new();\n    kernel.add_driver(&driver);\n    let duration = Duration::from_millis(100);\n    assert_eq!(Buzzer::tone(1000, duration), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(Buzzer::tone(1000, duration), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn tone_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Buzzer::new();\n    kernel.add_driver(&driver);\n\n    let duration = Duration::from_millis(100);\n\n    driver.set_tone_sync(1000, 100);\n    assert_eq!(Buzzer::tone_sync(1000, duration), Ok(()));\n}\n"
  },
  {
    "path": "apis/interface/console/Cargo.toml",
    "content": "[package]\nname = \"libtock_console\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n    \"dcz <gihuac.dcz@porcupinefactory.org>\",\n]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock console driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/interface/console/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse core::fmt;\nuse core::marker::PhantomData;\nuse libtock_platform as platform;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock_platform::share;\nuse libtock_platform::subscribe::Subscribe;\nuse libtock_platform::{DefaultConfig, ErrorCode, Syscalls};\n\n/// The console driver.\n///\n/// It allows libraries to pass strings to the kernel's console driver.\n///\n/// # Example\n/// ```ignore\n/// use libtock::Console;\n///\n/// // Writes \"foo\", followed by a newline, to the console\n/// let mut writer = Console::writer();\n/// writeln!(writer, foo).unwrap();\n/// ```\npub struct Console<S: Syscalls, C: Config = DefaultConfig>(S, C);\n\nimpl<S: Syscalls, C: Config> Console<S, C> {\n    /// Run a check against the console capsule to ensure it is present.\n    ///\n    /// Returns `true` if the driver was present. This does not necessarily mean\n    /// that the driver is working, as it may still fail to allocate grant\n    /// memory.\n    #[inline(always)]\n    pub fn exists() -> bool {\n        S::command(DRIVER_NUM, command::EXISTS, 0, 0).is_success()\n    }\n\n    /// Writes bytes.\n    /// This is an alternative to `fmt::Write::write`\n    /// because this can actually return an error code.\n    pub fn write(s: &[u8]) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { allow_ro::WRITE }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::WRITE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_ro, subscribe) = handle.split();\n\n            S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE }>(allow_ro, s)?;\n\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::WRITE }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, command::WRITE, s.len() as u32, 0)\n                .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((_,)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n\n    /// Reads bytes\n    /// Reads from the device and writes to `buf`, starting from index 0.\n    /// No special guarantees about when the read stops.\n    /// Returns count of bytes written to `buf`.\n    pub fn read(buf: &mut [u8]) -> (usize, Result<(), ErrorCode>) {\n        let called: Cell<Option<(u32, u32)>> = Cell::new(None);\n        let mut bytes_received = 0;\n        let r = share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { allow_rw::READ }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::READ }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            let len = buf.len();\n            S::allow_rw::<C, DRIVER_NUM, { allow_rw::READ }>(allow_rw, buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::READ }>(subscribe, &called)?;\n\n            // When this fails, `called` is guaranteed unmodified,\n            // because upcalls are never processed until we call `yield`.\n            S::command(DRIVER_NUM, command::READ, len as u32, 0).to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((status, bytes_pushed_count)) = called.get() {\n                    bytes_received = bytes_pushed_count as usize;\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        });\n        (bytes_received, r)\n    }\n\n    pub fn writer() -> ConsoleWriter<S> {\n        ConsoleWriter {\n            syscalls: Default::default(),\n        }\n    }\n}\n\npub struct ConsoleWriter<S: Syscalls> {\n    syscalls: PhantomData<S>,\n}\n\nimpl<S: Syscalls> fmt::Write for ConsoleWriter<S> {\n    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {\n        Console::<S>::write(s.as_bytes()).map_err(|_e| fmt::Error)\n    }\n}\n\n/// System call configuration trait for `Console`.\npub trait Config:\n    platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config\n{\n}\nimpl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>\n    Config for T\n{\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x1;\n\n// Command IDs\n#[allow(unused)]\nmod command {\n    pub const EXISTS: u32 = 0;\n    pub const WRITE: u32 = 1;\n    pub const READ: u32 = 2;\n    pub const ABORT: u32 = 3;\n}\n\n#[allow(unused)]\nmod subscribe {\n    pub const WRITE: u32 = 1;\n    pub const READ: u32 = 2;\n}\n\nmod allow_ro {\n    pub const WRITE: u32 = 1;\n}\n\nmod allow_rw {\n    pub const READ: u32 = 1;\n}\n"
  },
  {
    "path": "apis/interface/console/src/tests.rs",
    "content": "use super::*;\nuse core::fmt::Write;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::{command_return, fake, ExpectedSyscall};\n\ntype Console = super::Console<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert!(!Console::exists());\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Console::new();\n    kernel.add_driver(&driver);\n\n    assert!(Console::exists());\n    assert_eq!(driver.take_bytes(), &[]);\n}\n\n#[test]\nfn write_bytes() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Console::new();\n    kernel.add_driver(&driver);\n\n    Console::write(b\"foo\").unwrap();\n    Console::write(b\"bar\").unwrap();\n    assert_eq!(driver.take_bytes(), b\"foobar\",);\n}\n\n#[test]\nfn write_str() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Console::new();\n    kernel.add_driver(&driver);\n\n    write!(Console::writer(), \"foo\").unwrap();\n    assert_eq!(driver.take_bytes(), b\"foo\");\n}\n\n#[test]\nfn read_bytes_short() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Console::new_with_input(b\"Hello\");\n    kernel.add_driver(&driver);\n\n    let mut buf = [0; 10];\n\n    let (count, res) = Console::read(&mut buf);\n    res.unwrap();\n    assert_eq!(&buf[..count], b\"Hello\");\n}\n\n#[test]\nfn read_bytes_alot() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Console::new_with_input(b\"Hello Alot!\");\n    kernel.add_driver(&driver);\n\n    let mut buf = [0; 5];\n\n    let (count, res) = Console::read(&mut buf);\n    res.unwrap();\n    assert_eq!(&buf[..count], b\"Hello\");\n\n    let (count, res) = Console::read(&mut buf);\n    res.unwrap();\n    assert_eq!(&buf[..count], b\" Alot\");\n}\n\n#[test]\nfn failed_print() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Console::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::WRITE,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: DRIVER_NUM,\n        subscribe_num: subscribe::WRITE,\n        skip_with_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: command::WRITE,\n        argument0: 5,\n        argument1: 0,\n        override_return: Some(command_return::failure(ErrorCode::Fail)),\n    });\n\n    assert_eq!(Console::write(b\"abcde\"), Err(ErrorCode::Fail));\n    // The fake driver still receives the command even if a fake error is injected.\n    assert_eq!(driver.take_bytes(), b\"abcde\");\n}\n\n#[test]\nfn failed_read() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Console::new_with_input(b\"bugxxxx\");\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRw {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_rw::READ,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: DRIVER_NUM,\n        subscribe_num: subscribe::READ,\n        skip_with_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: command::READ,\n        argument0: 3,\n        argument1: 0,\n        override_return: Some(command_return::failure(ErrorCode::Fail)),\n    });\n\n    let mut buf = [0; 3];\n\n    let (count, res) = Console::read(&mut buf);\n    assert_eq!(res, Err(ErrorCode::Fail));\n    assert_eq!(count, 0);\n}\n"
  },
  {
    "path": "apis/interface/leds/Cargo.toml",
    "content": "[package]\nname = \"libtock_leds\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock leds driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/interface/leds/src/lib.rs",
    "content": "#![no_std]\n\nuse libtock_platform::{ErrorCode, Syscalls};\n\n/// The LEDs driver\n///\n/// # Example\n/// ```ignore\n/// use libtock::Leds;\n///\n/// // Turn on led 0\n/// let _ = Leds::on(0);\n/// ```\npub struct Leds<S: Syscalls>(S);\n\nimpl<S: Syscalls> Leds<S> {\n    /// Run a check against the leds capsule to ensure it is present.\n    ///\n    /// Returns `Ok(number_of_leds)` if the driver was present. This does not necessarily mean\n    /// that the driver is working, as it may still fail to allocate grant\n    /// memory.\n    pub fn count() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, LEDS_COUNT, 0, 0).to_result()\n    }\n\n    pub fn on(led: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, LED_ON, led, 0).to_result()\n    }\n\n    pub fn off(led: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, LED_OFF, led, 0).to_result()\n    }\n\n    pub fn toggle(led: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, LED_TOGGLE, led, 0).to_result()\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x2;\n\n// Command IDs\nconst LEDS_COUNT: u32 = 0;\nconst LED_ON: u32 = 1;\nconst LED_OFF: u32 = 2;\nconst LED_TOGGLE: u32 = 3;\n"
  },
  {
    "path": "apis/interface/leds/src/tests.rs",
    "content": "use libtock_platform::ErrorCode;\nuse libtock_unittest::fake;\n\ntype Leds = super::Leds<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Leds::count(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Leds::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Leds::count(), Ok(10));\n    for led in 0..10 {\n        assert_eq!(driver.get_led(led), Some(false));\n    }\n}\n\n#[test]\nfn num_leds() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Leds::<10>::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Leds::count().unwrap_or_default(), 10);\n}\n\n#[test]\nfn on() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Leds::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Leds::on(0), Ok(()));\n    assert_eq!(driver.get_led(0), Some(true));\n}\n\n#[test]\nfn off() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Leds::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Leds::off(0), Ok(()));\n    assert_eq!(driver.get_led(0), Some(false));\n}\n\n#[test]\nfn toggle() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Leds::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Leds::toggle(0), Ok(()));\n    assert_eq!(driver.get_led(0), Some(true));\n    assert_eq!(Leds::toggle(0), Ok(()));\n    assert_eq!(driver.get_led(0), Some(false));\n}\n\n#[test]\nfn on_off() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Leds::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Leds::on(0), Ok(()));\n    assert_eq!(driver.get_led(0), Some(true));\n    assert_eq!(Leds::off(0), Ok(()));\n    assert_eq!(driver.get_led(0), Some(false));\n}\n\n#[test]\nfn no_led() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Leds::<10>::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Leds::on(11), Err(ErrorCode::Invalid));\n    for led in 0..Leds::count().unwrap_or_default() {\n        assert_eq!(driver.get_led(led), Some(false));\n    }\n}\n"
  },
  {
    "path": "apis/kernel/low_level_debug/Cargo.toml",
    "content": "[package]\nname = \"libtock_low_level_debug\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock low-level debug drivers\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/kernel/low_level_debug/src/lib.rs",
    "content": "#![no_std]\n\nuse libtock_platform::Syscalls;\n\n/// The low-level debug API provides tools to diagnose userspace issues that\n/// make normal debugging workflows (e.g. printing to the console) difficult.\n///\n/// It allows libraries to print alert codes and apps to print numeric\n/// information using only the command system call.\n///\n/// # Example\n/// ```ignore\n/// use libtock::LowLevelDebug;\n///\n/// // Prints 0x45 and the app which called it.\n/// LowLevelDebug::print_1(0x45);\n/// ```\npub struct LowLevelDebug<S: Syscalls>(S);\n\nimpl<S: Syscalls> LowLevelDebug<S> {\n    /// Run a check against the low-level debug capsule to ensure it is present.\n    ///\n    /// Returns `true` if the driver was present. This does not necessarily mean\n    /// that the driver is working, as it may still fail to allocate grant\n    /// memory.\n    #[inline(always)]\n    pub fn exists() -> bool {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).is_success()\n    }\n\n    /// Print one of the predefined alerts in [`AlertCode`].\n    #[inline(always)]\n    pub fn print_alert_code(code: AlertCode) {\n        let _ = S::command(DRIVER_NUM, PRINT_ALERT_CODE, code as u32, 0);\n    }\n\n    /// Print a single number. The number will be printed in hexadecimal.\n    ///\n    /// In general, this should only be added temporarily for debugging and\n    /// should not be called by released library code.\n    #[inline(always)]\n    pub fn print_1(x: u32) {\n        let _ = S::command(DRIVER_NUM, PRINT_1, x, 0);\n    }\n\n    /// Print two numbers. The numbers will be printed in hexadecimal.\n    ///\n    /// Like `print_1`, this is intended for temporary debugging and should not\n    /// be called by released library code. If you want to print multiple\n    /// values, it is often useful to use the first argument to indicate what\n    /// value is being printed.\n    #[inline(always)]\n    pub fn print_2(x: u32, y: u32) {\n        let _ = S::command(DRIVER_NUM, PRINT_2, x, y);\n    }\n}\n\n/// A predefined alert code, for use with [`LowLevelDebug::print_alert_code`].\npub enum AlertCode {\n    /// Application panic (e.g. `panic!()` called in Rust code).\n    Panic = 0x01,\n\n    /// A statically-linked app was not installed in the correct location in\n    /// flash.\n    WrongLocation = 0x02,\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x8;\n\n// Command IDs\nconst EXISTS: u32 = 0;\nconst PRINT_ALERT_CODE: u32 = 1;\nconst PRINT_1: u32 = 2;\nconst PRINT_2: u32 = 3;\n"
  },
  {
    "path": "apis/kernel/low_level_debug/src/tests.rs",
    "content": "use super::*;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::{command_return, fake, ExpectedSyscall};\n\ntype LowLevelDebug = super::LowLevelDebug<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert!(!LowLevelDebug::exists());\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::LowLevelDebug::new();\n    kernel.add_driver(&driver);\n\n    assert!(LowLevelDebug::exists());\n    assert_eq!(driver.take_messages(), []);\n}\n\n#[test]\nfn print_alert_code() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::LowLevelDebug::new();\n    kernel.add_driver(&driver);\n\n    LowLevelDebug::print_alert_code(AlertCode::Panic);\n    LowLevelDebug::print_alert_code(AlertCode::WrongLocation);\n    assert_eq!(\n        driver.take_messages(),\n        [\n            fake::Message::AlertCode(0x01),\n            fake::Message::AlertCode(0x02)\n        ]\n    );\n}\n\n#[test]\nfn print_1() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::LowLevelDebug::new();\n    kernel.add_driver(&driver);\n\n    LowLevelDebug::print_1(42);\n    assert_eq!(driver.take_messages(), [fake::Message::Print1(42)]);\n}\n\n#[test]\nfn print_2() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::LowLevelDebug::new();\n    kernel.add_driver(&driver);\n\n    LowLevelDebug::print_2(42, 27);\n    LowLevelDebug::print_2(29, 43);\n    assert_eq!(\n        driver.take_messages(),\n        [fake::Message::Print2(42, 27), fake::Message::Print2(29, 43)]\n    );\n}\n\n#[test]\nfn failed_print() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::LowLevelDebug::new();\n    kernel.add_driver(&driver);\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: PRINT_1,\n        argument0: 72,\n        argument1: 0,\n        override_return: Some(command_return::failure(ErrorCode::Fail)),\n    });\n\n    // The error is explicitly silenced, and cannot be detected.\n    LowLevelDebug::print_1(72);\n\n    // The fake driver still receives the command even if a fake error is injected.\n    assert_eq!(driver.take_messages(), [fake::Message::Print1(72)]);\n}\n"
  },
  {
    "path": "apis/net/ieee802154/Cargo.toml",
    "content": "[package]\nname = \"libtock_ieee802154\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock raw IEEE 802.15.4 stack driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/net/ieee802154/src/lib.rs",
    "content": "//! The raw IEEE 802.15.4 stack driver.\n\n#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock_platform::share;\nuse libtock_platform::subscribe::Subscribe;\nuse libtock_platform::{DefaultConfig, ErrorCode, Syscalls};\n\n/// The raw IEEE 802.15.4 stack driver.\n///\n/// It allows libraries to pass frames to and from kernel's 802.15.4 driver.\n///\n/// # Example\n/// ```ignore\n/// use libtock::ieee802154::{Ieee802154, RxOperator, RxRingBuffer, RxSingleBufferOperator};\n///\n/// // Configure the radio\n/// let pan: u16 = 0xcafe;\n/// let addr_short: u16 = 0xdead;\n/// let addr_long: u64 = 0xdead_dad;\n/// let tx_power: i8 = -0x42;\n/// let channel: u8 = 0xff;\n///\n/// Ieee802154::set_pan(pan);\n/// Ieee802154::set_address_short(addr_short);\n/// Ieee802154::set_address_long(addr_long);\n/// Ieee802154::set_tx_power(tx_power).unwrap();\n/// Ieee802154::set_channel(channel).unwrap();\n///\n/// // Don't forget to commit the config!\n/// Ieee802154::commit_config();\n///\n/// Ieee802154::radio_on()?;\n///\n/// // Transmit a frame\n/// Ieee802154::transmit_frame(b\"foobar\").unwrap();\n///\n/// // Receive frames\n/// let mut buf = RxRingBuffer::<2>::new();\n/// let mut operator = RxSingleBufferOperator::new(&mut buf);\n///\n/// let frame = operator.receive_frame()?;\n/// // Access frame data here:\n/// let _body_len = frame.payload_len;\n/// let _first_body_byte = frame.body[0];\n///\n/// ```\npub struct Ieee802154<S: Syscalls, C: Config = DefaultConfig>(S, C);\n\n// Existence check\nimpl<S: Syscalls, C: Config> Ieee802154<S, C> {\n    /// Run a check against the console capsule to ensure it is present.\n    ///\n    /// Returns `true` if the driver was present. This does not necessarily mean\n    /// that the driver is working, as it may still fail to allocate grant\n    /// memory.\n    #[inline(always)]\n    pub fn exists() -> bool {\n        S::command(DRIVER_NUM, command::EXISTS, 0, 0).is_success()\n    }\n}\n\n// Power management\nimpl<S: Syscalls, C: Config> Ieee802154<S, C> {\n    #[inline(always)]\n    pub fn is_on() -> bool {\n        S::command(DRIVER_NUM, command::STATUS, 0, 0).is_success()\n    }\n\n    #[inline(always)]\n    pub fn radio_on() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, command::TURN_ON, 0, 0).to_result()\n    }\n\n    #[inline(always)]\n    pub fn radio_off() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, command::TURN_OFF, 0, 0).to_result()\n    }\n}\n\n// Configuration\nimpl<S: Syscalls, C: Config> Ieee802154<S, C> {\n    #[inline(always)]\n    pub fn set_address_short(short_addr: u16) {\n        // Setting short address can't fail, so no need to check the return value.\n        let _ = S::command(\n            DRIVER_NUM,\n            command::SET_SHORT_ADDR,\n            // Driver expects 1 added to make the value positive.\n            short_addr as u32 + 1,\n            0,\n        );\n    }\n\n    #[inline(always)]\n    pub fn set_address_long(long_addr: u64) {\n        // Setting long address can't fail, so no need to check the return value.\n        let addr_lower: u32 = long_addr as u32;\n        let addr_upper: u32 = (long_addr >> 32) as u32;\n        let _ = S::command(DRIVER_NUM, command::SET_LONG_ADDR, addr_lower, addr_upper);\n    }\n\n    #[inline(always)]\n    pub fn set_pan(pan: u16) {\n        // Setting PAN can't fail, so no need to check the return value.\n        let _ = S::command(\n            DRIVER_NUM,\n            command::SET_PAN,\n            pan as u32 + 1, // Driver expects 1 added to make the value positive.\n            0,\n        );\n    }\n\n    #[inline(always)]\n    pub fn set_channel(chan: u8) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, command::SET_CHAN, chan as u32, 0).to_result()\n    }\n\n    #[inline(always)]\n    pub fn set_tx_power(power: i8) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, command::SET_TX_PWR, power as i32 as u32, 0).to_result()\n    }\n\n    #[inline(always)]\n    pub fn commit_config() {\n        // Committing config can't fail, so no need to check the return value.\n        let _ = S::command(DRIVER_NUM, command::COMMIT_CFG, 0, 0);\n    }\n\n    #[inline(always)]\n    pub fn get_address_short() -> Result<u16, ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_SHORT_ADDR, 0, 0)\n            .to_result::<u32, _>()\n            // Driver adds 1 to make the value positive.\n            .map(|addr| addr as u16 - 1)\n    }\n\n    #[inline(always)]\n    pub fn get_address_long() -> Result<u64, ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_LONG_ADDR, 0, 0).to_result()\n    }\n\n    #[inline(always)]\n    pub fn get_pan() -> Result<u16, ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_PAN, 0, 0)\n            .to_result::<u32, _>()\n            // Driver adds 1 to make the value positive.\n            .map(|pan| pan as u16 - 1)\n    }\n\n    #[inline(always)]\n    pub fn get_channel() -> Result<u8, ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_CHAN, 0, 0)\n            .to_result::<u32, _>()\n            .map(|chan| chan as u8)\n    }\n\n    #[inline(always)]\n    pub fn get_tx_power() -> Result<i8, ErrorCode> {\n        S::command(DRIVER_NUM, command::GET_TX_PWR, 0, 0)\n            .to_result::<u32, _>()\n            .map(|power| power as i32 as i8)\n    }\n}\n\n// Transmission\nimpl<S: Syscalls, C: Config> Ieee802154<S, C> {\n    /// Transmit a frame using the IEEE 802.15.4 Phy Driver.\n    pub fn transmit_frame_raw(frame: &[u8]) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { allow_ro::WRITE }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::FRAME_TRANSMITTED }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_ro, subscribe) = handle.split();\n\n            S::allow_ro::<C, DRIVER_NUM, { allow_ro::WRITE }>(allow_ro, frame)?;\n\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::FRAME_TRANSMITTED }>(\n                subscribe, &called,\n            )?;\n\n            S::command(DRIVER_NUM, command::TRANSMIT_RAW, 0, 0).to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if called.get().is_some() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n}\n\nmod rx;\npub use rx::{Frame, RxOperator, RxRingBuffer, RxSingleBufferOperator};\n\n/// System call configuration trait for `Ieee802154`.\npub trait Config:\n    platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config\n{\n}\nimpl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>\n    Config for T\n{\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x30001;\n\n// Command IDs\n/// - `0`: Driver existence check.\n/// - `1`: Return radio status. Ok(())/OFF = on/off.\n/// - `2`: Set short address.\n/// - `4`: Set PAN ID.\n/// - `5`: Set channel.\n/// - `6`: Set transmission power.\n/// - `7`: Commit any configuration changes.\n/// - `8`: Get the short MAC address.\n/// - `10`: Get the PAN ID.\n/// - `11`: Get the channel.\n/// - `12`: Get the transmission power.\n/// - `27`: Transmit a frame. The frame must be stored in the write RO allow\n///   buffer 0. The allowed buffer must be the length of the frame. The\n///   frame includes the PDSU (i.e., the MAC payload) _without_ the MFR\n///   (i.e., CRC) bytes.\n/// - `28`: Set long address.\n/// - `29`: Get the long MAC address.\n/// - `30`: Turn the radio on.\n/// - `31`: Turn the radio off.\nmod command {\n    pub const EXISTS: u32 = 0;\n    pub const STATUS: u32 = 1;\n    pub const SET_SHORT_ADDR: u32 = 2;\n    pub const SET_PAN: u32 = 4;\n    pub const SET_CHAN: u32 = 5;\n    pub const SET_TX_PWR: u32 = 6;\n    pub const COMMIT_CFG: u32 = 7;\n    pub const GET_SHORT_ADDR: u32 = 8;\n    pub const GET_PAN: u32 = 10;\n    pub const GET_CHAN: u32 = 11;\n    pub const GET_TX_PWR: u32 = 12;\n    pub const TRANSMIT_RAW: u32 = 27;\n    pub const SET_LONG_ADDR: u32 = 28;\n    pub const GET_LONG_ADDR: u32 = 29;\n    pub const TURN_ON: u32 = 30;\n    pub const TURN_OFF: u32 = 31;\n}\n\nmod subscribe {\n    /// Frame is received\n    pub const FRAME_RECEIVED: u32 = 0;\n    /// Frame is transmitted\n    pub const FRAME_TRANSMITTED: u32 = 1;\n}\n\n/// Ids for read-only allow buffers\nmod allow_ro {\n    /// Write buffer. Contains the frame payload to be transmitted.\n    pub const WRITE: u32 = 0;\n}\n\n/// Ids for read-write allow buffers\nmod allow_rw {\n    /// Read buffer. Will contain the received frame.\n    pub const READ: u32 = 0;\n}\n"
  },
  {
    "path": "apis/net/ieee802154/src/rx.rs",
    "content": "use core::marker::PhantomData;\n\nuse super::*;\n\n/// Maximum length of a MAC frame.\nconst MAX_MTU: usize = 127;\n\n#[derive(Debug)]\n#[repr(C)]\npub struct Frame {\n    pub header_len: u8,\n    pub payload_len: u8,\n    pub mic_len: u8,\n    pub body: [u8; MAX_MTU],\n}\n\nconst EMPTY_FRAME: Frame = Frame {\n    header_len: 0,\n    payload_len: 0,\n    mic_len: 0,\n    body: [0; MAX_MTU],\n};\n\n/// The ring buffer that is shared with kernel using allow-rw syscall, with kernel acting\n/// as a producer of frames and we acting a consumer.\n///\n/// The `N` parameter specifies the capacity of the buffer in number of frames.\n/// Unfortunately, due to a design flaw of the ring buffer, it can never be fully utilised,\n/// as it's impossible to distinguish an empty buffer from a full one. The kernel code\n/// actually uses up to `N - 1` slots, and then starts overwriting old frames with\n/// new ones. Remember to specify `N` as `F + 1`, where `F` is the maximum expected number\n/// of frames received in short succession.\n///\n/// Given the non-deterministic nature of upcalls, the userprocess must carefully\n/// handle receiving upcalls. There exists a risk of dropping 15.4 packets while\n/// reading from the ring buffer (as the ring buffer is unallowed while reading).\n/// This could be handled by utilizing two ring buffers and alternating which\n/// belongs to the kernel and which is being read from. However, efforts to implement that\n/// failed on Miri level - we couldn't find a sound way to achieve that.\n/// Alternatively, the user can also utilize a single ring buffer if dropped frames may be permissible.\n/// This is done by [RxSingleBufferOperator].\n#[derive(Debug)]\n#[repr(C)]\npub struct RxRingBuffer<const N: usize> {\n    /// From where the next frame will be read by process.\n    /// Updated by process only.\n    read_index: u8,\n    /// Where the next frame will be written by kernel.\n    /// Updated by kernel only.\n    write_index: u8,\n    /// Slots for received frames.\n    frames: [Frame; N],\n}\n\nimpl<const N: usize> Default for RxRingBuffer<N> {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl<const N: usize> RxRingBuffer<N> {\n    /// Creates a new [RxRingBuffer] that can be used to receive frames into.\n    pub const fn new() -> Self {\n        Self {\n            read_index: 0,\n            write_index: 0,\n            frames: [EMPTY_FRAME; N],\n        }\n    }\n\n    fn as_mut_byte_slice(&mut self) -> &mut [u8] {\n        // SAFETY: any byte value is valid for any byte of Self,\n        // as well as for any byte of [u8], so casts back and forth\n        // cannot break the type system.\n        unsafe {\n            core::slice::from_raw_parts_mut(\n                self as *mut Self as *mut u8,\n                core::mem::size_of::<Self>(),\n            )\n        }\n    }\n\n    fn has_frame(&self) -> bool {\n        self.read_index != self.write_index\n    }\n\n    fn next_frame(&mut self) -> &mut Frame {\n        let frame = self.frames.get_mut(self.read_index as usize).unwrap();\n        self.read_index = (self.read_index + 1) % N as u8;\n        frame\n    }\n}\n\npub trait RxOperator {\n    /// Receive one new frame.\n    ///\n    /// Logically pop one frame out of the ring buffer and provide mutable access to it.\n    /// If no frame is ready for reception, yield_wait to kernel until one is available.\n    fn receive_frame(&mut self) -> Result<&mut Frame, ErrorCode>;\n}\n\n/// Safe encapsulation that can receive frames from the kernel using a single ring buffer.\n/// See [RxRingBuffer] for more information.\n///\n/// This operator can lose some frames: if a frame is received in the kernel when\n/// the app is examining its received frames (and hence has its buffer unallowed),\n/// then the frame can be lost. Unfortunately, no alternative at the moment due to\n/// soundness issues in tried implementation.\npub struct RxSingleBufferOperator<'buf, const N: usize, S: Syscalls, C: Config = DefaultConfig> {\n    buf: &'buf mut RxRingBuffer<N>,\n    s: PhantomData<S>,\n    c: PhantomData<C>,\n}\n\nimpl<'buf, const N: usize, S: Syscalls, C: Config> RxSingleBufferOperator<'buf, N, S, C> {\n    /// Creates a new [RxSingleBufferOperator] that can be used to receive frames.\n    pub fn new(buf: &'buf mut RxRingBuffer<N>) -> Self {\n        Self {\n            buf,\n            s: PhantomData,\n            c: PhantomData,\n        }\n    }\n}\nimpl<const N: usize, S: Syscalls, C: Config> RxOperator for RxSingleBufferOperator<'_, N, S, C> {\n    fn receive_frame(&mut self) -> Result<&mut Frame, ErrorCode> {\n        if self.buf.has_frame() {\n            Ok(self.buf.next_frame())\n        } else {\n            // If no frame is there, wait until one comes, then return it.\n\n            Ieee802154::<S, C>::receive_frame_single_buf(self.buf)?;\n\n            // Safety: kernel schedules an upcall iff a new frame becomes available,\n            // i.e. when it increments `read_index`.\n            Ok(self.buf.next_frame())\n        }\n    }\n}\n\n// Reception\nimpl<S: Syscalls, C: Config> Ieee802154<S, C> {\n    fn receive_frame_single_buf<const N: usize>(\n        buf: &mut RxRingBuffer<N>,\n    ) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { allow_rw::READ }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::FRAME_RECEIVED }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { allow_rw::READ }>(allow_rw, buf.as_mut_byte_slice())?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::FRAME_RECEIVED }>(subscribe, &called)?;\n\n            loop {\n                S::yield_wait();\n                if let Some((_lqi,)) = called.get() {\n                    // At least one frame was received.\n                    return Ok(());\n                }\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "apis/net/ieee802154/src/tests.rs",
    "content": "use libtock_platform::{RawSyscalls, Register};\nuse libtock_unittest::fake::{self, ieee802154::Frame as FakeFrame, Ieee802154Phy};\n\n/// The Ieee8021514Phy userspace driver calls yield_wait() immediately after subscribe().\n/// Normally, it would wait for the kernel to receive a frame and then asynchronously\n/// schedule an upcall, but in this testing framework it is required to schedule\n/// an upcall before yield_wait(), because otherwise a panic is raised.\n///\n/// HACK: This wraps around fake::Syscalls to hook subscribe::FRAME_RECEIVED\n/// so that immediately after subscribing for the upcall, frames are received\n/// by the kernel driver and the corresponding upcall is scheduled.\nstruct FakeSyscalls;\n\nunsafe impl RawSyscalls for FakeSyscalls {\n    unsafe fn yield1([r0]: [Register; 1]) {\n        libtock_unittest::fake::Syscalls::yield1([r0])\n    }\n\n    unsafe fn yield2([r0, r1]: [Register; 2]) {\n        libtock_unittest::fake::Syscalls::yield2([r0, r1])\n    }\n\n    unsafe fn syscall1<const CLASS: usize>([r0]: [Register; 1]) -> [Register; 2] {\n        libtock_unittest::fake::Syscalls::syscall1::<CLASS>([r0])\n    }\n\n    unsafe fn syscall2<const CLASS: usize>([r0, r1]: [Register; 2]) -> [Register; 2] {\n        libtock_unittest::fake::Syscalls::syscall2::<CLASS>([r0, r1])\n    }\n\n    unsafe fn syscall4<const CLASS: usize>([r0, r1, r2, r3]: [Register; 4]) -> [Register; 4] {\n        let trigger_rx_upcall = match CLASS {\n            libtock_platform::syscall_class::SUBSCRIBE => {\n                let driver_num: u32 = r0.try_into().unwrap();\n                let subscribe_num: u32 = r1.try_into().unwrap();\n                let len: usize = r3.into();\n                assert_eq!(driver_num, DRIVER_NUM);\n\n                subscribe_num == subscribe::FRAME_RECEIVED && len > 0\n            }\n            _ => false,\n        };\n\n        let ret = libtock_unittest::fake::Syscalls::syscall4::<CLASS>([r0, r1, r2, r3]);\n        if trigger_rx_upcall {\n            if let Some(driver) = Ieee802154Phy::instance() {\n                driver.driver_receive_pending_frames();\n\n                if driver.has_pending_rx_frames() {\n                    driver.trigger_rx_upcall();\n                }\n            }\n        }\n        ret\n    }\n}\n\nuse crate::{subscribe, DRIVER_NUM};\n\nuse super::{RxOperator, RxRingBuffer};\n\ntype Ieee802154 = super::Ieee802154<FakeSyscalls>;\ntype RxSingleBufferOperator<'buf, const N: usize> =\n    super::RxSingleBufferOperator<'buf, N, FakeSyscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert!(!Ieee802154::exists());\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Ieee802154Phy::new();\n    kernel.add_driver(&driver);\n\n    assert!(Ieee802154::exists());\n}\n\n#[test]\nfn configure() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Ieee802154Phy::new();\n    kernel.add_driver(&driver);\n\n    let pan: u16 = 0xcafe;\n    let addr_short: u16 = 0xdead;\n    let addr_long: u64 = 0xdeaddad;\n    let tx_power: i8 = -0x42;\n    let channel: u8 = 0xff;\n\n    Ieee802154::set_pan(pan);\n    Ieee802154::set_address_short(addr_short);\n    Ieee802154::set_address_long(addr_long);\n    Ieee802154::set_tx_power(tx_power).unwrap();\n    Ieee802154::set_channel(channel).unwrap();\n\n    Ieee802154::commit_config();\n\n    assert_eq!(Ieee802154::get_pan().unwrap(), pan);\n    assert_eq!(Ieee802154::get_address_short().unwrap(), addr_short);\n    assert_eq!(Ieee802154::get_address_long().unwrap(), addr_long);\n    assert_eq!(Ieee802154::get_channel().unwrap(), channel);\n    assert_eq!(Ieee802154::get_tx_power().unwrap(), tx_power);\n}\n\n#[test]\nfn transmit_frame() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Ieee802154Phy::new();\n    kernel.add_driver(&driver);\n\n    Ieee802154::transmit_frame_raw(b\"foo\").unwrap();\n    Ieee802154::transmit_frame_raw(b\"bar\").unwrap();\n    assert_eq!(\n        driver.take_transmitted_frames(),\n        &[&b\"foo\"[..], &b\"bar\"[..]],\n    );\n}\n\nmod rx {\n    use super::*;\n    fn test_with_driver(test: impl FnOnce(&Ieee802154Phy)) {\n        let kernel = fake::Kernel::new();\n        let driver = fake::Ieee802154Phy::new();\n        kernel.add_driver(&driver);\n\n        test(&driver)\n    }\n\n    fn test_with_single_buf_operator<const SUPPORTED_FRAMES: usize>(\n        driver: &Ieee802154Phy,\n        test: impl Fn(&Ieee802154Phy, &mut dyn RxOperator),\n    ) {\n        let mut buf = RxRingBuffer::<SUPPORTED_FRAMES>::new();\n        let mut operator = RxSingleBufferOperator::new(&mut buf);\n\n        test(driver, &mut operator)\n    }\n\n    fn no_frame_comes(_driver: &Ieee802154Phy, operator: &mut dyn RxOperator) {\n        // No frame is available, so we expect to panic in tests,\n        // because yield_wait is called without pending upcalls.\n        // THIS PANICS\n        let _ = operator.receive_frame();\n    }\n\n    #[test]\n    #[should_panic = \"yield-wait called with no queued upcall\"]\n    fn no_frame_comes_single_buf() {\n        test_with_driver(|driver| {\n            const SUPPORTED_FRAMES: usize = 2;\n\n            test_with_single_buf_operator::<SUPPORTED_FRAMES>(driver, no_frame_comes);\n        });\n    }\n\n    #[test]\n    fn receive_frame() {\n        test_with_driver(|driver| {\n            const SUPPORTED_FRAMES: usize = 2;\n\n            test_with_single_buf_operator::<SUPPORTED_FRAMES>(driver, |driver, operator| {\n                let frame1 = b\"alamakota\";\n\n                driver.radio_receive_frame(FakeFrame::with_body(frame1));\n                // Now one frame is available.\n\n                let got_frame1 = operator.receive_frame().unwrap();\n                assert_eq!(got_frame1.payload_len as usize, frame1.len());\n                assert_eq!(\n                    &got_frame1.body[..got_frame1.payload_len as usize],\n                    &frame1[..]\n                );\n            });\n        });\n    }\n\n    fn only_one_frame_comes(driver: &Ieee802154Phy, operator: &mut dyn RxOperator) {\n        let frame1 = b\"alamakota\";\n\n        // Now one frame is available.\n        driver.radio_receive_frame(FakeFrame::with_body(frame1));\n        let got_frame1 = operator.receive_frame().unwrap();\n        assert_eq!(got_frame1.payload_len as usize, frame1.len());\n        assert_eq!(&got_frame1.body[..frame1.len()], frame1);\n\n        // But only one!\n        // THIS PANICS\n        let _ = operator.receive_frame();\n    }\n\n    #[test]\n    #[should_panic = \"yield-wait called with no queued upcall\"]\n    fn receive_frame_only_one_single_buf() {\n        test_with_driver(|driver| {\n            const SUPPORTED_FRAMES: usize = 2;\n\n            test_with_single_buf_operator::<SUPPORTED_FRAMES>(driver, only_one_frame_comes);\n        });\n    }\n\n    #[test]\n    fn receive_many_frames() {\n        test_with_driver(|driver| {\n            const SUPPORTED_FRAMES: usize = 3;\n\n            test_with_single_buf_operator::<{ SUPPORTED_FRAMES + 1 }>(\n                driver,\n                |driver, operator| {\n                    for (times, frame) in\n                        [1, 2, 3, 10]\n                            .iter()\n                            .copied()\n                            .zip([&b\"one\"[..], b\"two\", b\"three\", b\"ten\"])\n                    {\n                        for _ in 0..times {\n                            driver.radio_receive_frame(FakeFrame::with_body(frame));\n                        }\n\n                        for _ in 0..core::cmp::min(times, SUPPORTED_FRAMES) {\n                            let got_frame = operator.receive_frame().unwrap();\n                            let expected_frame = frame;\n                            assert_eq!(got_frame.payload_len as usize, expected_frame.len());\n                            assert_eq!(\n                                &got_frame.body[..got_frame.payload_len as usize],\n                                expected_frame\n                            );\n                        }\n                    }\n                },\n            );\n        });\n    }\n\n    #[test]\n    fn receive_various_frames() {\n        test_with_driver(|driver| {\n            const SUPPORTED_FRAMES: usize = 3;\n\n            test_with_single_buf_operator::<{ SUPPORTED_FRAMES + 1 }>(\n                driver,\n                |driver, operator| {\n                    let frame1 = b\"alamakota\";\n                    let frame2 = b\"ewamamewe\";\n                    let frame3 = b\"wojciechmalaptop\";\n                    let frames: [&[u8]; 3] = [frame1, frame2, frame3];\n\n                    let order = [0, 1, 2, 2, 1, 0, 2, 2, 1, 0, 2];\n                    for idx in order {\n                        let times = idx + 1;\n\n                        for _ in 0..times {\n                            driver.radio_receive_frame(FakeFrame::with_body(frames[idx]));\n                        }\n\n                        for _ in 0..core::cmp::min(times, SUPPORTED_FRAMES) {\n                            let got_frame = operator.receive_frame().unwrap();\n                            let expected_frame = frames[idx];\n                            assert_eq!(got_frame.payload_len as usize, expected_frame.len());\n                            assert_eq!(\n                                &got_frame.body[..got_frame.payload_len as usize],\n                                expected_frame\n                            );\n                        }\n                    }\n                },\n            );\n        });\n    }\n}\n"
  },
  {
    "path": "apis/peripherals/adc/Cargo.toml",
    "content": "[package]\nname = \"libtock_adc\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock adc driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/peripherals/adc/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n    share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\npub struct Adc<S: Syscalls>(S);\n\nimpl<S: Syscalls> Adc<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        // TODO(Tock 3.0): The \"exists\" command should return directly return\n        // `Result<(), ErrorCode>` (i.e. with no `.and()` call), but the\n        // current ADC driver in the kernel returns the number of ADC channels\n        // instead of just success. This will be fixed in a future release of\n        // Tock, but for now we workaround this issue.\n        //\n        // https://github.com/tock/tock/issues/3375\n        S::command(DRIVER_NUM, EXISTS, 0, 0)\n            .to_result::<u32, ErrorCode>()\n            .and(Ok(()))\n    }\n\n    // Initiate a sample reading\n    pub fn read_single_sample() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 0).to_result()\n    }\n\n    // Register a listener to be called when the ADC conversion is finished\n    pub fn register_listener<'share, F: Fn(u16)>(\n        listener: &'share ADCListener<F>,\n        subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Initiates a synchronous ADC conversion\n    /// Returns the converted ADC value or an error\n    pub fn read_single_sample_sync() -> Result<u16, ErrorCode> {\n        let sample: Cell<Option<u16>> = Cell::new(None);\n        let listener = ADCListener(|adc_val| {\n            sample.set(Some(adc_val));\n        });\n        share::scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            Self::read_single_sample()?;\n            while sample.get().is_none() {\n                S::yield_wait();\n            }\n\n            match sample.get() {\n                None => Err(ErrorCode::Busy),\n                Some(adc_val) => Ok(adc_val),\n            }\n        })\n    }\n\n    /// Returns the number of ADC resolution bits\n    pub fn get_resolution_bits() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, GET_RES_BITS, 0, 0).to_result()\n    }\n\n    /// Returns the reference voltage in millivolts (mV)\n    pub fn get_reference_voltage_mv() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, GET_VOLTAGE_REF, 0, 0).to_result()\n    }\n}\n\npub struct ADCListener<F: Fn(u16)>(pub F);\n\nimpl<F: Fn(u16)> Upcall<OneId<DRIVER_NUM, 0>> for ADCListener<F> {\n    fn upcall(&self, adc_val: u32, _arg1: u32, _arg2: u32) {\n        self.0(adc_val as u16)\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x5;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst SINGLE_SAMPLE: u32 = 1;\n// const REPEAT_SINGLE_SAMPLE: u32 = 2;\n// const MULTIPLE_SAMPLE: u32 = 3;\n// const CONTINUOUS_BUFF_SAMPLE: u32 = 4;\n// const STOP_SAMPLE: u32 = 5;\nconst GET_RES_BITS: u32 = 101;\nconst GET_VOLTAGE_REF: u32 = 102;\n"
  },
  {
    "path": "apis/peripherals/adc/src/tests.rs",
    "content": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\ntype Adc = super::Adc<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Adc::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Adc::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Adc::exists(), Ok(()));\n}\n\n#[test]\nfn read_single_sample() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Adc::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Adc::read_single_sample(), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(Adc::read_single_sample(), Err(ErrorCode::Busy));\n    assert_eq!(Adc::read_single_sample_sync(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn register_unregister_listener() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Adc::new();\n    kernel.add_driver(&driver);\n\n    let sample: Cell<Option<u16>> = Cell::new(None);\n    let listener = crate::ADCListener(|adc_val| {\n        sample.set(Some(adc_val));\n    });\n    share::scope(|subscribe| {\n        assert_eq!(Adc::read_single_sample(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(Adc::register_listener(&listener, subscribe), Ok(()));\n        assert_eq!(Adc::read_single_sample(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(sample.get(), Some(100));\n\n        Adc::unregister_listener();\n        assert_eq!(Adc::read_single_sample(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n}\n\n#[test]\nfn read_single_sample_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Adc::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(1000);\n    assert_eq!(Adc::read_single_sample_sync(), Ok(1000));\n}\n"
  },
  {
    "path": "apis/peripherals/alarm/Cargo.toml",
    "content": "[package]\nname = \"libtock_alarm\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n    \"dcz <gihuac.dcz@porcupinefactory.org>\",\n]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2018\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock alarm driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/peripherals/alarm/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::share;\nuse libtock_platform::{DefaultConfig, ErrorCode, Syscalls};\n\n/// The alarm driver\n///\n/// # Example\n/// ```ignore\n/// use libtock2::Alarm;\n///\n/// // Wait for timeout\n/// Alarm::sleep(Alarm::Milliseconds(2500));\n/// ```\npub struct Alarm<S: Syscalls, C: platform::subscribe::Config = DefaultConfig>(S, C);\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub struct Hz(pub u32);\n\npub trait Convert {\n    /// Converts a time unit by rounding up.\n    fn to_ticks(self, freq: Hz) -> Ticks;\n}\n\n#[derive(Copy, Clone, Debug)]\npub struct Ticks(pub u32);\n\nimpl Convert for Ticks {\n    fn to_ticks(self, _freq: Hz) -> Ticks {\n        self\n    }\n}\n\n#[derive(Copy, Clone)]\npub struct Milliseconds(pub u32);\n\nimpl Convert for Milliseconds {\n    fn to_ticks(self, freq: Hz) -> Ticks {\n        // Saturating multiplication will top out at about 1 hour at 1MHz.\n        // It's large enough for an alarm, and much simpler than failing\n        // or losing precision for short sleeps.\n\n        /// u32::div_ceil is still unstable.\n        fn div_ceil(a: u32, other: u32) -> u32 {\n            let d = a / other;\n            let m = a % other;\n            if m == 0 {\n                d\n            } else {\n                d + 1\n            }\n        }\n        Ticks(div_ceil(self.0.saturating_mul(freq.0), 1000))\n    }\n}\n\nimpl<S: Syscalls, C: platform::subscribe::Config> Alarm<S, C> {\n    /// Run a check against the console capsule to ensure it is present.\n    #[inline(always)]\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, command::EXISTS, 0, 0).to_result()\n    }\n\n    pub fn get_frequency() -> Result<Hz, ErrorCode> {\n        S::command(DRIVER_NUM, command::FREQUENCY, 0, 0)\n            .to_result()\n            .map(Hz)\n    }\n\n    pub fn get_ticks() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, command::TIME, 0, 0).to_result()\n    }\n\n    pub fn get_milliseconds() -> Result<u64, ErrorCode> {\n        let ticks = Self::get_ticks()? as u64;\n        let freq = (Self::get_frequency()?).0 as u64;\n\n        Ok(ticks.saturating_div(freq / 1000))\n    }\n\n    pub fn sleep_for<T: Convert>(time: T) -> Result<(), ErrorCode> {\n        let freq = Self::get_frequency()?;\n        let ticks = time.to_ticks(freq);\n\n        let called: Cell<Option<(u32, u32)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::CALLBACK }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, command::SET_RELATIVE, ticks.0, 0)\n                .to_result()\n                .map(|_when: u32| ())?;\n\n            loop {\n                S::yield_wait();\n                if let Some((_when, _ref)) = called.get() {\n                    return Ok(());\n                }\n            }\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x0;\n\n// Command IDs\n#[allow(unused)]\nmod command {\n    pub const EXISTS: u32 = 0;\n    pub const FREQUENCY: u32 = 1;\n    pub const TIME: u32 = 2;\n    pub const STOP: u32 = 3;\n\n    pub const SET_RELATIVE: u32 = 5;\n    pub const SET_ABSOLUTE: u32 = 6;\n}\n\n#[allow(unused)]\nmod subscribe {\n    pub const CALLBACK: u32 = 0;\n}\n"
  },
  {
    "path": "apis/peripherals/alarm/src/tests.rs",
    "content": "use libtock_unittest::fake;\n\nuse crate::{Hz, Milliseconds, Ticks};\n\ntype Alarm = crate::Alarm<fake::Syscalls>;\n\n#[test]\nfn get_freq() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Alarm::new(1000);\n    kernel.add_driver(&driver);\n    assert_eq!(Alarm::get_frequency(), Ok(Hz(1000)));\n}\n\n#[test]\nfn sleep() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Alarm::new(1000);\n    kernel.add_driver(&driver);\n\n    assert_eq!(Alarm::sleep_for(Ticks(0)), Ok(()));\n    assert_eq!(Alarm::sleep_for(Ticks(1000)), Ok(()));\n    assert_eq!(Alarm::sleep_for(Milliseconds(1000)), Ok(()));\n}\n"
  },
  {
    "path": "apis/peripherals/gpio/Cargo.toml",
    "content": "[package]\nname = \"libtock_gpio\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2018\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock gpio driver\"\n\n[features]\nrust_embedded = [\"embedded-hal\"]\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\nembedded-hal = { version = \"1.0\", optional = true }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/peripherals/gpio/src/lib.rs",
    "content": "#![no_std]\n\nuse core::marker::PhantomData;\n\nuse libtock_platform::{\n    share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\n/// The GPIO driver.\n///\n/// # Example\n/// ```ignore\n/// use libtock::gpio;\n///\n/// // Set pin to high.\n/// let pin = gpio::Gpio::get_pin(0).unwrap().make_output().unwrap();\n/// let _ = pin.set();\n/// ```\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum GpioState {\n    Low = 0,\n    High = 1,\n}\n\npub enum PinInterruptEdge {\n    Either = 0,\n    Rising = 1,\n    Falling = 2,\n}\n\npub enum Error {\n    Invalid,\n    Failed,\n}\n\npub trait Pull {\n    const MODE: u32;\n}\n\npub struct PullUp;\nimpl Pull for PullUp {\n    const MODE: u32 = 1;\n}\n\npub struct PullDown;\nimpl Pull for PullDown {\n    const MODE: u32 = 2;\n}\n\npub struct PullNone;\nimpl Pull for PullNone {\n    const MODE: u32 = 0;\n}\n\npub struct Gpio<S: Syscalls>(S);\n\nimpl<S: Syscalls> Gpio<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working, as it may still fail to allocate grant\n    /// memory.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    pub fn count() -> Result<u32, ErrorCode> {\n        S::command(DRIVER_NUM, GPIO_COUNT, 0, 0).to_result()\n    }\n\n    pub fn get_pin(pin: u32) -> Result<Pin<S>, ErrorCode> {\n        Self::disable(pin)?;\n        Ok(Pin {\n            pin_number: pin,\n            _syscalls: PhantomData,\n        })\n    }\n\n    /// Register an interrupt listener\n    ///\n    /// There can be only one single listener registered at a time.\n    /// Each time this function is used, it will replace the\n    /// previously registered listener.\n    pub fn register_listener<'share, F: Fn(u32, GpioState)>(\n        listener: &'share GpioInterruptListener<F>,\n        subscribe: Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the interrupt listener\n    ///\n    /// This function may be used even if there was no\n    /// previously registered listener.\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n}\n\n/// A wrapper around a closure to be registered and called when\n/// a gpio interrupt occurs.\n///\n/// ```ignore\n/// let listener = GpioInterruptListener(|gpio, interrupt_edge| {\n///     // make use of the button's state\n/// });\n/// ```\npub struct GpioInterruptListener<F: Fn(u32, GpioState)>(pub F);\n\nimpl<F: Fn(u32, GpioState)> Upcall<OneId<DRIVER_NUM, 0>> for GpioInterruptListener<F> {\n    fn upcall(&self, gpio_index: u32, value: u32, _arg2: u32) {\n        self.0(gpio_index, value.into())\n    }\n}\n\nimpl From<u32> for GpioState {\n    fn from(original: u32) -> GpioState {\n        match original {\n            0 => GpioState::Low,\n            _ => GpioState::High,\n        }\n    }\n}\n\npub struct Pin<S: Syscalls> {\n    pin_number: u32,\n    _syscalls: PhantomData<S>,\n}\n\nimpl<S: Syscalls> Pin<S> {\n    pub fn make_output(&mut self) -> Result<OutputPin<'_, S>, ErrorCode> {\n        Gpio::<S>::enable_gpio_output(self.pin_number)?;\n        Ok(OutputPin { pin: self })\n    }\n\n    pub fn make_input<P: Pull>(&self) -> Result<InputPin<'_, S, P>, ErrorCode> {\n        Gpio::<S>::enable_gpio_input(self.pin_number, P::MODE)?;\n        Ok(InputPin {\n            pin: self,\n            _pull: PhantomData,\n        })\n    }\n}\n\npub struct OutputPin<'a, S: Syscalls> {\n    pin: &'a Pin<S>,\n}\n\nimpl<S: Syscalls> OutputPin<'_, S> {\n    pub fn toggle(&mut self) -> Result<(), ErrorCode> {\n        Gpio::<S>::toggle(self.pin.pin_number)\n    }\n    pub fn set(&mut self) -> Result<(), ErrorCode> {\n        Gpio::<S>::write(self.pin.pin_number, GpioState::High)\n    }\n    pub fn clear(&mut self) -> Result<(), ErrorCode> {\n        Gpio::<S>::write(self.pin.pin_number, GpioState::Low)\n    }\n}\n\npub struct InputPin<'a, S: Syscalls, P: Pull> {\n    pin: &'a Pin<S>,\n    _pull: PhantomData<P>,\n}\n\nimpl<S: Syscalls, P: Pull> InputPin<'_, S, P> {\n    pub fn read(&self) -> Result<GpioState, ErrorCode> {\n        Gpio::<S>::read(self.pin.pin_number)\n    }\n\n    pub fn enable_interrupts(&self, edge: PinInterruptEdge) -> Result<(), ErrorCode> {\n        Gpio::<S>::enable_interrupts(self.pin.pin_number, edge)\n    }\n\n    pub fn disable_interrupts(&self) -> Result<(), ErrorCode> {\n        Gpio::<S>::disable_interrupts(self.pin.pin_number)\n    }\n}\n\nimpl<S: Syscalls> Drop for OutputPin<'_, S> {\n    fn drop(&mut self) {\n        let _ = Gpio::<S>::disable(self.pin.pin_number);\n    }\n}\n\nimpl<S: Syscalls, P: Pull> Drop for InputPin<'_, S, P> {\n    fn drop(&mut self) {\n        let _ = Gpio::<S>::disable(self.pin.pin_number);\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Implementation details below\n// -----------------------------------------------------------------------------\n\nimpl<S: Syscalls> Gpio<S> {\n    fn enable_gpio_output(pin: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, GPIO_ENABLE_OUTPUT, pin, 0).to_result()\n    }\n\n    fn enable_gpio_input(pin: u32, mode: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, GPIO_ENABLE_INPUT, pin, mode).to_result()\n    }\n\n    fn write(pin: u32, state: GpioState) -> Result<(), ErrorCode> {\n        let action = match state {\n            GpioState::Low => GPIO_CLEAR,\n            _ => GPIO_SET,\n        };\n        S::command(DRIVER_NUM, action, pin, 0).to_result()\n    }\n\n    fn read(pin: u32) -> Result<GpioState, ErrorCode> {\n        let pin_state: u32 = S::command(DRIVER_NUM, GPIO_READ_INPUT, pin, 0).to_result()?;\n        Ok(pin_state.into())\n    }\n\n    fn toggle(pin: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, GPIO_TOGGLE, pin, 0).to_result()\n    }\n\n    fn disable(pin: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, GPIO_DISABLE, pin, 0).to_result()\n    }\n\n    fn enable_interrupts(pin: u32, edge: PinInterruptEdge) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, pin, edge as u32).to_result()\n    }\n\n    fn disable_interrupts(pin: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, GPIO_DISABLE_INTERRUPTS, pin, 0).to_result()\n    }\n}\n\n#[cfg(feature = \"rust_embedded\")]\nimpl<S: Syscalls> embedded_hal::digital::ErrorType for OutputPin<'_, S> {\n    type Error = ErrorCode;\n}\n\n#[cfg(feature = \"rust_embedded\")]\nimpl<S: Syscalls> embedded_hal::digital::OutputPin for OutputPin<'_, S> {\n    fn set_low(&mut self) -> Result<(), Self::Error> {\n        self.clear()\n    }\n\n    fn set_high(&mut self) -> Result<(), Self::Error> {\n        self.set()\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x4;\n\n// Command IDs\nconst EXISTS: u32 = 0;\n\nconst GPIO_ENABLE_OUTPUT: u32 = 1;\nconst GPIO_SET: u32 = 2;\nconst GPIO_CLEAR: u32 = 3;\nconst GPIO_TOGGLE: u32 = 4;\n\nconst GPIO_ENABLE_INPUT: u32 = 5;\nconst GPIO_READ_INPUT: u32 = 6;\n\nconst GPIO_ENABLE_INTERRUPTS: u32 = 7;\nconst GPIO_DISABLE_INTERRUPTS: u32 = 8;\n\nconst GPIO_DISABLE: u32 = 9;\n\nconst GPIO_COUNT: u32 = 10;\n"
  },
  {
    "path": "apis/peripherals/gpio/src/tests.rs",
    "content": "use core::cell::Cell;\n\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake::{self, GpioMode, InterruptEdge, PullMode};\n\nuse crate::{GpioInterruptListener, GpioState, PinInterruptEdge, PullDown, PullNone, PullUp};\n\ntype Gpio = super::Gpio<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Gpio::count(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn num_gpio() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Gpio::<10>::new();\n    kernel.add_driver(&driver);\n    assert_eq!(Gpio::count(), Ok(10));\n}\n\n// Tests the OutputPin implementation.\n#[test]\nfn output() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Gpio::<10>::new();\n    driver.set_missing_gpio(1);\n    kernel.add_driver(&driver);\n\n    assert_eq!(Gpio::count(), Ok(10));\n\n    assert!(core::matches!(Gpio::get_pin(11), Err(ErrorCode::Invalid)));\n    assert!(core::matches!(Gpio::get_pin(1), Err(ErrorCode::NoDevice)));\n\n    let pin_0 = Gpio::get_pin(0);\n    assert!(pin_0.is_ok());\n\n    let _ = pin_0.map(|mut pin| {\n        let output_pin = pin.make_output();\n        assert!(output_pin.is_ok());\n        assert_eq!(driver.get_gpio_state(0).unwrap().mode, GpioMode::Output);\n        let _ = output_pin.map(|mut pin| {\n            assert_eq!(pin.set(), Ok(()));\n            assert!(driver.get_gpio_state(0).unwrap().value);\n            assert_eq!(pin.clear(), Ok(()));\n            assert!(!driver.get_gpio_state(0).unwrap().value);\n            assert_eq!(pin.toggle(), Ok(()));\n            assert!(driver.get_gpio_state(0).unwrap().value);\n            assert_eq!(pin.toggle(), Ok(()));\n            assert!(!driver.get_gpio_state(0).unwrap().value);\n        });\n        assert_eq!(driver.get_gpio_state(0).unwrap().mode, GpioMode::Disable);\n    });\n}\n\n// Tests the InputPin implementation\n#[test]\nfn input() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Gpio::<10>::new();\n    driver.set_missing_gpio(1);\n    kernel.add_driver(&driver);\n\n    assert_eq!(Gpio::count(), Ok(10));\n\n    assert!(core::matches!(Gpio::get_pin(11), Err(ErrorCode::Invalid)));\n    assert!(core::matches!(Gpio::get_pin(1), Err(ErrorCode::NoDevice)));\n\n    let pin_0 = Gpio::get_pin(0);\n    assert!(pin_0.is_ok());\n\n    let _ = pin_0.map(|pin| {\n        let input_pin = pin.make_input::<PullNone>();\n        assert!(input_pin.is_ok());\n        assert_eq!(\n            driver.get_gpio_state(0).unwrap().mode,\n            GpioMode::Input(PullMode::PullNone)\n        );\n\n        let input_pin = pin.make_input::<PullUp>();\n        assert!(input_pin.is_ok());\n        assert_eq!(\n            driver.get_gpio_state(0).unwrap().mode,\n            GpioMode::Input(PullMode::PullUp)\n        );\n\n        let input_pin = pin.make_input::<PullDown>();\n        assert!(input_pin.is_ok());\n        assert_eq!(\n            driver.get_gpio_state(0).unwrap().mode,\n            GpioMode::Input(PullMode::PullDown)\n        );\n\n        let _ = input_pin.map(|pin| {\n            assert_eq!(driver.set_value(0, true), Ok(()));\n            assert_eq!(pin.read(), Ok(GpioState::High));\n            assert_eq!(driver.set_value(0, false), Ok(()));\n            assert_eq!(pin.read(), Ok(GpioState::Low));\n        });\n        assert_eq!(driver.get_gpio_state(0).unwrap().mode, GpioMode::Disable);\n    });\n}\n\n// Tests the pin interrupts implementation\n#[test]\nfn interrupts() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Gpio::<10>::new();\n    driver.set_missing_gpio(1);\n    kernel.add_driver(&driver);\n\n    assert_eq!(Gpio::count(), Ok(10));\n\n    let gpio_state = Cell::<Option<GpioState>>::new(None);\n    let listener = GpioInterruptListener(|gpio, state| {\n        assert_eq!(gpio, 0);\n        gpio_state.set(Some(state));\n    });\n\n    assert_eq!(Gpio::enable_interrupts(0, PinInterruptEdge::Either), Ok(()));\n    share::scope(|subscribe| {\n        assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));\n        assert_eq!(driver.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(gpio_state.get(), Some(GpioState::High));\n    });\n\n    assert_eq!(driver.set_value(0, false), Ok(()));\n    assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n    assert!(core::matches!(Gpio::get_pin(11), Err(ErrorCode::Invalid)));\n    assert!(core::matches!(Gpio::get_pin(1), Err(ErrorCode::NoDevice)));\n\n    let pin_0 = Gpio::get_pin(0);\n    assert!(pin_0.is_ok());\n\n    let _ = pin_0.map(|pin| {\n        // Either\n        let input_pin = pin.make_input::<PullNone>();\n        assert!(input_pin.is_ok());\n        assert_eq!(\n            driver.get_gpio_state(0).unwrap().mode,\n            GpioMode::Input(PullMode::PullNone)\n        );\n\n        let _ = input_pin.map(|pin| {\n            assert_eq!(\n                pin.enable_interrupts(crate::PinInterruptEdge::Either),\n                Ok(())\n            );\n            assert_eq!(\n                driver.get_gpio_state(0).unwrap().interrupt_enabled,\n                Some(InterruptEdge::Either)\n            );\n\n            assert_eq!(driver.set_value(0, false), Ok(()));\n\n            let gpio_state = Cell::<Option<GpioState>>::new(None);\n            let listener = GpioInterruptListener(|gpio, state| {\n                assert_eq!(gpio, 0);\n                gpio_state.set(Some(state));\n            });\n\n            share::scope(|subscribe| {\n                assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));\n                assert_eq!(driver.set_value(0, true), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n                assert_eq!(gpio_state.get(), Some(GpioState::High));\n                gpio_state.set(None);\n                assert_eq!(driver.set_value(0, false), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n                assert_eq!(gpio_state.get(), Some(GpioState::Low));\n\n                assert_eq!(pin.disable_interrupts(), Ok(()));\n                assert_eq!(driver.set_value(0, true), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n                assert_eq!(driver.set_value(0, false), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n            });\n        });\n\n        // Rising\n        let input_pin = pin.make_input::<PullNone>();\n        assert!(input_pin.is_ok());\n        assert_eq!(\n            driver.get_gpio_state(0).unwrap().mode,\n            GpioMode::Input(PullMode::PullNone)\n        );\n\n        let _ = input_pin.map(|pin| {\n            assert_eq!(\n                pin.enable_interrupts(crate::PinInterruptEdge::Rising),\n                Ok(())\n            );\n            assert_eq!(\n                driver.get_gpio_state(0).unwrap().interrupt_enabled,\n                Some(InterruptEdge::Rising)\n            );\n\n            assert_eq!(driver.set_value(0, false), Ok(()));\n\n            let gpio_state = Cell::<Option<GpioState>>::new(None);\n            let listener = GpioInterruptListener(|gpio, state| {\n                assert_eq!(gpio, 0);\n                gpio_state.set(Some(state));\n            });\n\n            share::scope(|subscribe| {\n                assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));\n                assert_eq!(driver.set_value(0, true), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n                assert_eq!(gpio_state.get(), Some(GpioState::High));\n                assert_eq!(driver.set_value(0, false), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n                assert_eq!(pin.disable_interrupts(), Ok(()));\n                assert_eq!(driver.set_value(0, true), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n                assert_eq!(driver.set_value(0, false), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n            });\n        });\n\n        // Falling\n        let input_pin = pin.make_input::<PullNone>();\n        assert!(input_pin.is_ok());\n        assert_eq!(\n            driver.get_gpio_state(0).unwrap().mode,\n            GpioMode::Input(PullMode::PullNone)\n        );\n\n        let _ = input_pin.map(|pin| {\n            assert_eq!(\n                pin.enable_interrupts(crate::PinInterruptEdge::Falling),\n                Ok(())\n            );\n            assert_eq!(\n                driver.get_gpio_state(0).unwrap().interrupt_enabled,\n                Some(InterruptEdge::Falling)\n            );\n\n            assert_eq!(driver.set_value(0, false), Ok(()));\n\n            let gpio_state = Cell::<Option<GpioState>>::new(None);\n            let listener = GpioInterruptListener(|gpio, state| {\n                assert_eq!(gpio, 0);\n                gpio_state.set(Some(state));\n            });\n\n            share::scope(|subscribe| {\n                assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));\n                assert_eq!(driver.set_value(0, true), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n                assert_eq!(driver.set_value(0, false), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n                assert_eq!(gpio_state.get(), Some(GpioState::Low));\n\n                assert_eq!(pin.disable_interrupts(), Ok(()));\n                assert_eq!(driver.set_value(0, true), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n                assert_eq!(driver.set_value(0, false), Ok(()));\n                assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n            });\n        });\n    });\n}\n\n// Tests the pin event subcribe implementation\n#[test]\nfn subscribe() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Gpio::<10>::new();\n    driver.set_missing_gpio(1);\n    kernel.add_driver(&driver);\n\n    assert_eq!(Gpio::count(), Ok(10));\n\n    let gpio_state = Cell::<Option<GpioState>>::new(None);\n    let listener = GpioInterruptListener(|gpio, state| {\n        assert_eq!(gpio, 0);\n        gpio_state.set(Some(state));\n    });\n\n    assert_eq!(Gpio::enable_interrupts(0, PinInterruptEdge::Either), Ok(()));\n    share::scope(|subscribe| {\n        assert_eq!(Gpio::register_listener(&listener, subscribe), Ok(()));\n        assert_eq!(driver.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(gpio_state.get(), Some(GpioState::High));\n    });\n\n    assert_eq!(driver.set_value(0, false), Ok(()));\n    assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n}\n"
  },
  {
    "path": "apis/peripherals/i2c_master/Cargo.toml",
    "content": "[package]\nname = \"libtock_i2c_master\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n    \"Alistair Francis <alistair.francis@wdc.com>\",\n]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock I2C master driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n"
  },
  {
    "path": "apis/peripherals/i2c_master/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock_platform::share;\nuse libtock_platform::subscribe::Subscribe;\nuse libtock_platform::{DefaultConfig, ErrorCode, Syscalls};\n\npub struct I2CMaster<S: Syscalls, C: Config = DefaultConfig>(S, C);\n\nimpl<S: Syscalls, C: Config> I2CMaster<S, C> {\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, i2c_master_cmd::EXISTS, 0, 0).to_result()\n    }\n\n    /// # Summary\n    ///\n    /// Perform an I2C write followed by a read.\n    ///\n    /// TODO: Add async support\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address\n    /// * `buf`: Buffer\n    /// * `w_len`: Number of bytes to write from @w_buf\n    /// * `r_len`: Number of bytes to read into @r_buf\n    ///\n    /// # Returns\n    /// On success: Returns Ok(())\n    /// On failure: Err(ErrorCode)\n    pub fn i2c_master_write_read_sync(\n        addr: u16,\n        buf: &mut [u8],\n        w_len: u16,\n        r_len: u16,\n    ) -> Result<(), ErrorCode> {\n        if w_len as usize > buf.len() || r_len as usize > buf.len() {\n            return Err(ErrorCode::NoMem);\n        }\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        let cmd_arg0: u32 = (w_len as u32) << 8 | addr as u32;\n        share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::MASTER }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { rw_allow::MASTER }>(allow_rw, buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_READ_WRITE }>(\n                subscribe, &called,\n            )?;\n\n            S::command(\n                DRIVER_NUM,\n                i2c_master_cmd::MASTER_WRITE,\n                cmd_arg0,\n                r_len.into(),\n            )\n            .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _)) = called.get() {\n                    assert_eq!(r0, 0);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n\n    /// # Summary\n    ///\n    /// Write to an I2C device the data from the buffer pointed by @buf. This function is\n    /// synchronous and returns only when the operation has completed.\n    ///\n    /// TODO: Add async support\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address\n    /// * `buf`: Storage buffer, this should be bigger than @len\n    /// * `len`: Number of bytes to read into @buf\n    ///\n    /// # Returns\n    /// On success: Returns Ok(())\n    /// On failure: Err(ErrorCode)\n    pub fn i2c_master_write_sync(addr: u16, buf: &mut [u8], len: u16) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::MASTER }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { rw_allow::MASTER }>(allow_rw, buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_WRITE }>(subscribe, &called)?;\n\n            S::command(\n                DRIVER_NUM,\n                i2c_master_cmd::MASTER_WRITE,\n                addr.into(),\n                len.into(),\n            )\n            .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _)) = called.get() {\n                    assert_eq!(r0, 0);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n\n    /// # Summary\n    ///\n    /// Read from an I2C device the data to the buffer pointed by @buf. This function is\n    /// synchronous and returns only when the operation has completed.\n    ///\n    /// TODO: Add async support\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address\n    /// * `buf`: Storage buffer, this should be bigger than @len\n    /// * `len`: Number of bytes to read into @buf\n    ///\n    /// # Returns\n    /// On success: Returns Ok(())\n    /// On failure: Err(ErrorCode)\n    pub fn i2c_master_read_sync(addr: u16, buf: &mut [u8], len: u16) -> Result<(), ErrorCode> {\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::MASTER }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::MASTER_READ }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { rw_allow::MASTER }>(allow_rw, buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_READ }>(subscribe, &called)?;\n\n            S::command(\n                DRIVER_NUM,\n                i2c_master_cmd::MASTER_READ,\n                addr.into(),\n                len.into(),\n            )\n            .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _)) = called.get() {\n                    assert_eq!(r0, 0);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n}\n\n/// System call configuration trait for `I2CMaster`.\npub trait Config:\n    platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config\n{\n}\nimpl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>\n    Config for T\n{\n}\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\nconst DRIVER_NUM: u32 = 0x20003;\n\n#[allow(unused)]\nmod subscribe {\n    pub const MASTER_READ: u32 = 0;\n    pub const MASTER_WRITE: u32 = 0;\n    pub const MASTER_READ_WRITE: u32 = 0;\n}\n\n/// Ids for read-write allow buffers\n#[allow(unused)]\nmod rw_allow {\n    pub const MASTER: u32 = 1;\n}\n\n#[allow(unused)]\nmod i2c_master_cmd {\n    pub const EXISTS: u32 = 0;\n    pub const MASTER_WRITE: u32 = 1;\n    pub const MASTER_READ: u32 = 2;\n    pub const MASTER_WRITE_READ: u32 = 3;\n}\n"
  },
  {
    "path": "apis/peripherals/i2c_master_slave/Cargo.toml",
    "content": "[package]\nname = \"libtock_i2c_master_slave\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n    \"Wilfred Mallawa <wilfred.mallawa@wdc.com>\",\n]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock I2C master-slave driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n"
  },
  {
    "path": "apis/peripherals/i2c_master_slave/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock_platform::share;\nuse libtock_platform::subscribe::Subscribe;\nuse libtock_platform::{DefaultConfig, ErrorCode, Syscalls};\n\npub struct I2CMasterSlave<S: Syscalls, C: Config = DefaultConfig>(S, C);\n\nimpl<S: Syscalls, C: Config> I2CMasterSlave<S, C> {\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, i2c_master_slave_cmd::EXISTS, 0, 0).to_result()\n    }\n\n    /// # Summary\n    ///\n    /// Perform an I2C write to the slave device on @addr.\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address\n    /// * `buf`: Storage buffer, this should be bigger than @len\n    /// * `len`: Number of bytes to write from @buf\n    ///\n    /// # Returns\n    /// On success: Returns Ok(()), @len bytes were written from @buf.\n    /// On failure: Err(ErrorCode), with failure ErrorCode.\n    pub fn i2c_master_slave_write_sync(\n        addr: u16,\n        buffer: &[u8],\n        len: u16,\n    ) -> Result<(), ErrorCode> {\n        // We could write just the buffer length, but this may lead to\n        // ambiguities for the caller. So Err out early.\n        if len as usize > buffer.len() {\n            return Err(ErrorCode::NoMem);\n        }\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        // The kernel will split this argument into upper length and lower address.\n        let cmd_arg0: u32 = (len as u32) << 16 | addr as u32;\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { ro_allow::MASTER_TX }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_ro, subscribe) = handle.split();\n\n            S::allow_ro::<C, DRIVER_NUM, { i2c_buffers::MASTER_WRITE }>(allow_ro, buffer)?;\n\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_WRITE }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, i2c_master_slave_cmd::MASTER_WRITE, cmd_arg0, 0)\n                .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _r1)) = called.get() {\n                    // Kernel uses a different cmd number for this...\n                    assert_eq!(r0, 0);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n\n    /// # Summary\n    ///\n    /// Perform an I2C read from the the slave device with the slave address of @addr.\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address\n    /// * `buf`: Storage buffer, this should be bigger than @len\n    /// * `len`: Number of bytes to read into @buf\n    ///\n    /// # Returns\n    /// On success: Returns Ok(()) with @bytes_received valid.\n    /// On failure: Err(ErrorCode), Failure ErrorCode and @bytes_received is invalid.\n    ///\n    /// Note: @bytes_received is the first return tuple index (valid only on success).\n    pub fn i2c_master_slave_read_sync(\n        addr: u16,\n        buf: &mut [u8],\n        len: u16,\n    ) -> (usize, Result<(), ErrorCode>) {\n        if len as usize > buf.len() {\n            return (0, Err(ErrorCode::NoMem));\n        }\n        // This is the total amount of bytes read if the operation was a success.\n        // Otherwise, it is invalid.\n        let mut bytes_received: usize = core::cmp::min(buf.len(), len as usize);\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        // The kernel will split this argument into upper length and lower address.\n        let cmd_arg0: u32 = (len as u32) << 16 | addr as u32;\n        let r = share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::MASTER_RX }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::MASTER_READ }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { i2c_buffers::MASTER_READ }>(allow_rw, buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_READ }>(subscribe, &called)?;\n            // When this fails, `called` is guaranteed unmodified,\n            // because upcalls are never processed until we call `yield`.\n            S::command(DRIVER_NUM, i2c_master_slave_cmd::MASTER_READ, cmd_arg0, 0)\n                .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, _read_len, status)) = called.get() {\n                    // TODO: The kernel I2C api does not currently return the read_len, so this\n                    // will be invalid. We should keep track, likely assume the transfer was\n                    // done if no error. See: tock@capsules/core/src/i2c_master_slave_driver.rs:129\n                    // see: https://github.com/tock/tock/issues/3735\n                    // Kernel uses a different cmd number for this...\n                    assert_eq!(r0, 1);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        });\n        // If the operation failed, make bytes received zero so that the caller isn't confused in case\n        // the error is not handled properly. That is, in case of an error, we cannot guarantee the\n        // number of bytes received.\n        if r.is_err() {\n            bytes_received = 0;\n        }\n        (bytes_received, r)\n    }\n\n    /// # Summary\n    ///\n    /// Perform an I2C write followed by a read.\n    ///\n    /// Note: The kernel uses the TX buffer for both actions, such that if you request a\n    ///       a read that exceeds the buffer length of @w_buf, the read will be\n    ///       limited to the capacity of @w_buf. This API will detect such a case\n    ///       and error to avoid ambiguities until we have a better solution in the kernel.\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address\n    /// * `w_buf`: Write buffer\n    /// * `r_buf`: Read buffer\n    /// * `w_len`: Number of bytes to write from @w_buf\n    /// * `r_len`: Number of bytes to read into @r_buf\n    ///\n    /// # Returns\n    /// On success: Returns Ok(()) with @bytes_received valid.\n    /// On failure: Err(ErrorCode), Failure ErrorCode and @bytes_received is invalid.\n    ///\n    /// Note: @bytes_received is the first return tuple index (valid only on success).\n    pub fn i2c_master_slave_write_read_sync(\n        addr: u16,\n        w_buf: &mut [u8],\n        r_buf: &mut [u8],\n        w_len: u16,\n        r_len: u16,\n    ) -> (usize, Result<(), ErrorCode>) {\n        if w_len as usize > w_buf.len() || r_len as usize > r_buf.len() {\n            return (0, Err(ErrorCode::NoMem));\n        }\n        // TODO: Kernel uses the TX Buffer to perform both RX/TX for a write_read, so if\n        // the @w_buff is smaller than @r_len. The subsequent read will stop prematurely.\n        // So let's error here until that is addressed.\n        if r_len as usize > w_buf.len() {\n            return (0, Err(ErrorCode::NoMem));\n        }\n        // This is the total amount of bytes read if the operation was a success.\n        // Otherwise, it is invalid.\n        let mut bytes_received: usize = core::cmp::min(r_buf.len(), r_len as usize);\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n\n        let cmd_arg0: u32 = (w_len as u32) << 16 | (r_len as u32) << 8 | addr as u32;\n\n        let r = share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::MASTER_RX }>,\n                AllowRo<_, DRIVER_NUM, { ro_allow::MASTER_TX }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::MASTER_WRITE_READ }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, allow_ro, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { i2c_buffers::MASTER_READ }>(allow_rw, r_buf)?;\n            S::allow_ro::<C, DRIVER_NUM, { i2c_buffers::MASTER_WRITE }>(allow_ro, w_buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::MASTER_WRITE_READ }>(\n                subscribe, &called,\n            )?;\n            // When this fails, `called` is guaranteed unmodified,\n            // because upcalls are never processed until we call `yield`.\n            S::command(\n                DRIVER_NUM,\n                i2c_master_slave_cmd::MASTER_WRITE_READ,\n                cmd_arg0,\n                0,\n            )\n            .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, _read_len, status)) = called.get() {\n                    // TODO: The kernel I2C api does not currently return the read_len, so this\n                    // will be invalid. We should keep track, likely assume the transfer was\n                    // done if no error. See: tock@capsules/core/src/i2c_master_slave_driver.rs:129\n                    // see: https://github.com/tock/tock/issues/3735\n                    assert_eq!(r0, i2c_master_slave_cmd::MASTER_WRITE_READ);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        });\n        // If the operation failed, make bytes received zero so that the caller isn't confused in case\n        // the error is not handled properly. That is, in case of an error, we cannot guarantee the\n        // number of bytes received.\n        if r.is_err() {\n            bytes_received = 0;\n        }\n        (bytes_received, r)\n    }\n\n    /// # Summary\n    ///\n    /// Set the slave address for this device for slave mode operation. The IP should respond\n    /// to @addr.\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address to set\n    ///\n    /// # Returns\n    /// On success: Returns Ok(())\n    /// On failure: Err(ErrorCode)\n    pub fn i2c_master_slave_set_slave_address(addr: u8) -> Result<(), ErrorCode> {\n        // We do not count the R/W bit as part of the address, so the\n        // valid range is 0x00-0x7f\n        if addr > 0x7f {\n            return Err(ErrorCode::Invalid);\n        }\n        S::command(\n            DRIVER_NUM,\n            i2c_master_slave_cmd::SLAVE_SET_ADDR,\n            addr as u32,\n            0,\n        )\n        .to_result()\n    }\n\n    /// # Summary\n    ///\n    /// Expect a write from master into the buffer pointed by @buf. This function is\n    /// synchronous and returns only when the operation has completed.\n    ///\n    /// TODO: Add async support\n    ///\n    /// Note: As we do not know the size of data to be sent from a master device,\n    ///       it is suggested to allocated a large buffer to accommodate bigger transfers.\n    ///\n    /// # Parameter\n    ///\n    /// * `buf`: Buffer into which to copy data from master\n    ///\n    /// # Returns\n    /// On success: Returns (bytes_read, Ok(()))\n    /// On failure: (0, Err(ErrorCode))\n    pub fn i2c_master_slave_write_recv_sync(buf: &mut [u8]) -> (usize, Result<(), ErrorCode>) {\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        let mut bytes_recvd_ret: u32 = 0;\n        let r = share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::SLAVE_RX }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::SLAVE_WRITE_RECV }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { rw_allow::SLAVE_RX }>(allow_rw, buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::SLAVE_READ }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, i2c_master_slave_cmd::SLAVE_START_LISTEN, 0, 0)\n                .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, bytes_recvd, status)) = called.get() {\n                    // TODO: Ensure we are returning from the correct upcall and not from an unexpected `read_expect`\n                    //       Everything in this module subscribes to `0`. Which can be problematic from an async context.\n                    assert_eq!(r0, i2c_master_slave_cmd::SLAVE_START_LISTEN);\n                    return match status {\n                        0 => {\n                            bytes_recvd_ret = bytes_recvd;\n                            Ok(())\n                        }\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        });\n        (bytes_recvd_ret as usize, r)\n    }\n\n    /// # Summary\n    ///\n    /// Expect a write from master into the buffer pointed by @buf. This function is\n    /// synchronous and returns only when the operation has completed.\n    ///\n    /// TODO: Add async support\n    ///\n    /// # Parameter\n    ///\n    /// * `buf`: Buffer from which to transfer data from\n    /// * `len`: max number of bytes from buffer to transfer\n    ///\n    /// # Returns\n    /// On success: Returns (bytes_sent, Ok(()))\n    /// On failure: (0, Err(ErrorCode))\n    pub fn i2c_master_slave_read_send_sync(\n        buf: &[u8],\n        len: usize,\n    ) -> (usize, Result<(), ErrorCode>) {\n        if len > buf.len() {\n            return (0, Err(ErrorCode::Invalid));\n        }\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        let mut bytes_sent_ret: u32 = 0;\n        let r = share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { ro_allow::SLAVE_TX }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::SLAVE_READ_SEND }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_ro, subscribe) = handle.split();\n            S::allow_ro::<C, DRIVER_NUM, { ro_allow::SLAVE_TX }>(allow_ro, buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::SLAVE_READ }>(subscribe, &called)?;\n\n            S::command(\n                DRIVER_NUM,\n                i2c_master_slave_cmd::SLAVE_READ_SEND,\n                len as u32,\n                0,\n            )\n            .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, bytes_sent, status)) = called.get() {\n                    // TODO: Ensure we are returning from the correct upcall and not from an unexpected `read_expect`\n                    //       Everything in this module subscribes to `0`. Which can be problematic from an async context.\n                    assert_eq!(r0, i2c_master_slave_cmd::SLAVE_READ_SEND);\n                    return match status {\n                        0 => {\n                            bytes_sent_ret = bytes_sent;\n                            Ok(())\n                        }\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        });\n        (bytes_sent_ret as usize, r)\n    }\n}\n\n/// System call configuration trait for `I2CMaster`.\npub trait Config:\n    platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config\n{\n}\nimpl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>\n    Config for T\n{\n}\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\nconst DRIVER_NUM: u32 = 0x20006;\n\n#[allow(unused)]\nmod subscribe {\n    // TODO: It seems like only 0 is supported by the i2c_master_slave capsule currently\n    //       would be nice to improve this.\n    pub const MASTER_WRITE: u32 = 0;\n    pub const MASTER_WRITE_READ: u32 = 0;\n    pub const MASTER_READ: u32 = 0;\n    pub const SLAVE_READ: u32 = 0;\n    pub const SLAVE_WRITE_RECV: u32 = 0;\n    pub const SLAVE_READ_SEND: u32 = 0;\n}\n\n/// Ids for read-only allow buffers\n#[allow(unused)]\nmod ro_allow {\n    pub const MASTER_TX: u32 = 0;\n    pub const SLAVE_TX: u32 = 2;\n    /// The number of allow buffers the kernel stores for this grant\n    pub const COUNT: u8 = 3;\n}\n\n/// Ids for read-write allow buffers\n#[allow(unused)]\nmod rw_allow {\n    pub const MASTER_RX: u32 = 1;\n    pub const SLAVE_RX: u32 = 3;\n}\n\n#[allow(unused)]\nmod i2c_buffers {\n    pub const MASTER_WRITE: u32 = 0;\n    pub const MASTER_READ: u32 = 1;\n    pub const SLAVE_READ: u32 = 2;\n    pub const SLAVE_WRITE: u32 = 3;\n}\n\n#[allow(unused)]\nmod i2c_master_slave_cmd {\n    pub const EXISTS: u32 = 0;\n    pub const MASTER_WRITE: u32 = 1;\n    pub const MASTER_READ: u32 = 2;\n    pub const SLAVE_START_LISTEN: u32 = 3;\n    pub const SLAVE_READ_SEND: u32 = 4;\n    pub const SLAVE_SET_ADDR: u32 = 6;\n    pub const MASTER_WRITE_READ: u32 = 7;\n}\n"
  },
  {
    "path": "apis/peripherals/rng/Cargo.toml",
    "content": "[package]\nname = \"libtock_rng\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n    \"Cosmin Gabriel Georgescu <cosmingg2013@gmail.com>\",\n]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock rng driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/peripherals/rng/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n    share, subscribe::OneId, AllowRw, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\npub struct Rng<S: Syscalls>(S);\n\nimpl<S: Syscalls> Rng<S> {\n    /// Check if the RNG kernel driver exists\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Request `n` bytes of randomness in an asynchronous way.\n    /// Users must first share a buffer slice with the kernel and register an Rng listener\n    pub fn get_bytes_async(n: u32) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result()\n    }\n\n    /// Share a buffer slice with the kernel.\n    /// Must be used in conjunction with the `share::scope` function\n    pub fn allow_buffer<'share>(\n        buf: &'share mut [u8],\n        allow_rw: share::Handle<AllowRw<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(allow_rw, buf)\n    }\n\n    pub fn unallow_buffer() {\n        S::unallow_rw(DRIVER_NUM, 0)\n    }\n\n    /// Register an Rng listener to be called when an upcall is serviced\n    /// Must be used in conjunction with the `share::scope` function\n    pub fn register_listener<'share, F: Fn(u32)>(\n        listener: &'share RngListener<F>,\n        subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Ask to fill the provided `buf` with `n` random bytes.\n    /// If `n > buf.len()`, it will simply fill the whole buffer.\n    pub fn get_bytes_sync(buf: &mut [u8], n: u32) -> Result<(), ErrorCode> {\n        let called = Cell::new(false);\n        share::scope::<(AllowRw<S, DRIVER_NUM, 0>, Subscribe<S, DRIVER_NUM, 0>), _, _>(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n\n            // Share the provided buffer with the kernel\n            S::allow_rw::<DefaultConfig, DRIVER_NUM, 0>(allow_rw, buf)?;\n\n            // Subscribe for an upcall with the kernel\n            S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &called)?;\n\n            // Send the command to the kernel driver to fill the allowed_readwrite buffer\n            S::command(DRIVER_NUM, GET_BYTES, n, 0).to_result::<(), ErrorCode>()?;\n\n            // Wait for a callback to happen\n            while !called.get() {\n                S::yield_wait();\n            }\n\n            Ok(())\n        })\n    }\n}\n\n/// The provided listener to be called.\n/// Interior function operates on the number of random bytes filled into the buffer\npub struct RngListener<F: Fn(u32)>(pub F);\n\nimpl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for RngListener<F> {\n    fn upcall(&self, _: u32, arg1: u32, _: u32) {\n        (self.0)(arg1)\n    }\n}\n\n// -------------\n// DRIVER NUMBER\n// -------------\nconst DRIVER_NUM: u32 = 0x40001;\n\n// ---------------\n// COMMAND NUMBERS\n// ---------------\nconst EXISTS: u32 = 0;\nconst GET_BYTES: u32 = 1;\n"
  },
  {
    "path": "apis/peripherals/spi_controller/Cargo.toml",
    "content": "[package]\nname = \"libtock_spi_controller\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n    \"Alistair Francis <alistair.francis@wdc.com>\",\n]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock SPI controller driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n"
  },
  {
    "path": "apis/peripherals/spi_controller/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock_platform::share;\nuse libtock_platform::subscribe::Subscribe;\nuse libtock_platform::AllowRo;\nuse libtock_platform::{DefaultConfig, ErrorCode, Syscalls};\n\npub struct SpiController<S: Syscalls, C: Config = DefaultConfig>(S, C);\n\nimpl<S: Syscalls, C: Config> SpiController<S, C> {\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, spi_controller_cmd::EXISTS, 0, 0).to_result()\n    }\n\n    /// # Summary\n    ///\n    /// Perform an I2C write followed by a read.\n    ///\n    /// TODO: Add async support\n    ///\n    /// # Parameter\n    ///\n    /// * `addr`: Slave device address\n    /// * `buf`: Buffer\n    /// * `w_len`: Number of bytes to write from @w_buf\n    /// * `r_len`: Number of bytes to read into @r_buf\n    ///\n    /// # Returns\n    /// On success: Returns Ok(())\n    /// On failure: Err(ErrorCode)\n    pub fn spi_controller_write_read_sync(\n        w_buf: &[u8],\n        r_buf: &mut [u8],\n        len: u32,\n    ) -> Result<(), ErrorCode> {\n        if len as usize > w_buf.len() || len as usize > r_buf.len() {\n            return Err(ErrorCode::NoMem);\n        }\n\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::READ }>,\n                AllowRo<_, DRIVER_NUM, { ro_allow::WRITE }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, allow_ro, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { rw_allow::READ }>(allow_rw, r_buf)?;\n            S::allow_ro::<C, DRIVER_NUM, { ro_allow::WRITE }>(allow_ro, w_buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, spi_controller_cmd::READ_WRITE_BYTES, len, 0)\n                .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _)) = called.get() {\n                    assert_eq!(r0, len);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n\n    pub fn spi_controller_write_sync(w_buf: &[u8], len: u32) -> Result<(), ErrorCode> {\n        if len as usize > w_buf.len() {\n            return Err(ErrorCode::NoMem);\n        }\n\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { ro_allow::WRITE }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_ro, subscribe) = handle.split();\n            S::allow_ro::<C, DRIVER_NUM, { ro_allow::WRITE }>(allow_ro, w_buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, spi_controller_cmd::READ_WRITE_BYTES, len, 0)\n                .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _)) = called.get() {\n                    assert_eq!(r0, len);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n\n    pub fn spi_controller_read_sync(r_buf: &mut [u8], len: u32) -> Result<(), ErrorCode> {\n        if len as usize > r_buf.len() {\n            return Err(ErrorCode::NoMem);\n        }\n\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::READ }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { rw_allow::READ }>(allow_rw, r_buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, spi_controller_cmd::READ_BYTES, len, 0)\n                .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _)) = called.get() {\n                    assert_eq!(r0, len);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n\n    pub fn spi_controller_inplace_write_read_sync(\n        r_buf: &mut [u8],\n        len: u32,\n    ) -> Result<(), ErrorCode> {\n        if len as usize > r_buf.len() {\n            return Err(ErrorCode::NoMem);\n        }\n\n        let called: Cell<Option<(u32, u32, u32)>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRw<_, DRIVER_NUM, { rw_allow::READ }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::COMPLETE }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_rw, subscribe) = handle.split();\n            S::allow_rw::<C, DRIVER_NUM, { rw_allow::READ }>(allow_rw, r_buf)?;\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::COMPLETE }>(subscribe, &called)?;\n\n            S::command(\n                DRIVER_NUM,\n                spi_controller_cmd::INPLACE_READ_WRITE_BYTES,\n                len,\n                0,\n            )\n            .to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some((r0, status, _)) = called.get() {\n                    assert_eq!(r0, len);\n                    return match status {\n                        0 => Ok(()),\n                        e_status => Err(e_status.try_into().unwrap_or(ErrorCode::Fail)),\n                    };\n                }\n            }\n        })\n    }\n}\n\n/// System call configuration trait for `SpiController`.\npub trait Config:\n    platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config\n{\n}\nimpl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>\n    Config for T\n{\n}\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\nconst DRIVER_NUM: u32 = 0x20001;\n\n#[allow(unused)]\nmod subscribe {\n    pub const COMPLETE: u32 = 0;\n}\n\n#[allow(unused)]\nmod ro_allow {\n    pub const WRITE: u32 = 0;\n}\n\n#[allow(unused)]\nmod rw_allow {\n    pub const READ: u32 = 0;\n}\n\n#[allow(unused)]\nmod spi_controller_cmd {\n    pub const EXISTS: u32 = 0;\n    pub const READ_WRITE_BYTES: u32 = 2;\n    pub const SET_BAUD: u32 = 5;\n    pub const GET_BAUD: u32 = 6;\n    pub const SET_PHASE: u32 = 7;\n    pub const GET_PHASE: u32 = 8;\n    pub const SET_POLARITY: u32 = 9;\n    pub const GET_POLARITY: u32 = 10;\n    pub const READ_BYTES: u32 = 11;\n    pub const INPLACE_READ_WRITE_BYTES: u32 = 12;\n}\n"
  },
  {
    "path": "apis/sensors/air_quality/Cargo.toml",
    "content": "[package]\nname = \"libtock_air_quality\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock air quality driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/sensors/air_quality/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::subscribe::OneId;\nuse libtock_platform::{\n    share::scope, share::Handle, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\nuse Value::{Tvoc, CO2};\n\nenum Value {\n    CO2 = READ_CO2 as isize,\n    Tvoc = READ_TVOC as isize,\n}\n\npub struct AirQuality<S: Syscalls>(S);\n\nimpl<S: Syscalls> AirQuality<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Register an events listener\n    pub fn register_listener<'share, F: Fn(u32)>(\n        listener: &'share AirQualityListener<F>,\n        subscribe: Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Initiate a CO2 measurement.\n    ///\n    /// This function is used both for synchronous and asynchronous readings\n    pub fn read_co2() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_CO2, 0, 0).to_result()\n    }\n\n    /// Initiate a TVOC measurement.\n    ///\n    /// This function is used both for synchronous and asynchronous readings\n    pub fn read_tvoc() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_TVOC, 0, 0).to_result()\n    }\n\n    /// Public wrapper for `read_data_sync` for CO2 synchronous measurement\n    pub fn read_co2_sync() -> Result<u32, ErrorCode> {\n        Self::read_data_sync(CO2)\n    }\n\n    /// Public wrapper for `read_data_sync` for TVOC synchronous measurement\n    pub fn read_tvoc_sync() -> Result<u32, ErrorCode> {\n        Self::read_data_sync(Tvoc)\n    }\n\n    /// Read both CO2 and TVOC values synchronously\n    pub fn read_sync() -> Result<(u32, u32), ErrorCode> {\n        match (Self::read_data_sync(CO2), Self::read_data_sync(Tvoc)) {\n            (Ok(co2_value), Ok(tvoc_value)) => Ok((co2_value, tvoc_value)),\n            (Err(co2_error), _) => Err(co2_error),\n            (_, Err(tvoc_error)) => Err(tvoc_error),\n        }\n    }\n\n    /// Initiate a synchronous CO2 or TVOC measurement, based on the `read_type`.\n    /// Returns Ok(value) if the operation was successful\n    fn read_data_sync(read_type: Value) -> Result<u32, ErrorCode> {\n        let data_cell: Cell<Option<u32>> = Cell::new(None);\n        let listener = AirQualityListener(|data_val| {\n            data_cell.set(Some(data_val));\n        });\n\n        scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            match read_type {\n                CO2 => {\n                    Self::read_co2()?;\n                    while data_cell.get().is_none() {\n                        S::yield_wait();\n                    }\n\n                    match data_cell.get() {\n                        None => Err(ErrorCode::Fail),\n                        Some(co2_value) => Ok(co2_value),\n                    }\n                }\n                Tvoc => {\n                    Self::read_tvoc()?;\n                    while data_cell.get().is_none() {\n                        S::yield_wait();\n                    }\n\n                    match data_cell.get() {\n                        None => Err(ErrorCode::Fail),\n                        Some(tvoc_value) => Ok(tvoc_value),\n                    }\n                }\n            }\n        })\n    }\n}\n\npub struct AirQualityListener<F: Fn(u32)>(pub F);\nimpl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for AirQualityListener<F> {\n    fn upcall(&self, data_val: u32, _arg1: u32, _arg2: u32) {\n        self.0(data_val)\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60007;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ_CO2: u32 = 2;\nconst READ_TVOC: u32 = 3;\n"
  },
  {
    "path": "apis/sensors/air_quality/src/tests.rs",
    "content": "use crate::AirQualityListener;\nuse core::cell::Cell;\nuse libtock_platform::{share::scope, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\ntype AirQuality = super::AirQuality<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(AirQuality::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AirQuality::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(AirQuality::exists(), Ok(()));\n}\n\n#[test]\nfn read_co2() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AirQuality::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(AirQuality::read_co2(), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(AirQuality::read_co2(), Err(ErrorCode::Busy));\n    assert_eq!(AirQuality::read_co2_sync(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn read_tvoc() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AirQuality::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(AirQuality::read_tvoc(), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(AirQuality::read_tvoc(), Err(ErrorCode::Busy));\n    assert_eq!(AirQuality::read_tvoc_sync(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn register_unregister_listener() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AirQuality::new();\n    kernel.add_driver(&driver);\n\n    let data_cell: Cell<Option<u32>> = Cell::new(None);\n    let listener = AirQualityListener(|data_val| {\n        data_cell.set(Some(data_val));\n    });\n\n    scope(|subscribe| {\n        assert_eq!(AirQuality::read_co2(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(AirQuality::read_tvoc(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(AirQuality::register_listener(&listener, subscribe), Ok(()));\n\n        assert_eq!(AirQuality::read_co2(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(data_cell.get(), Some(100));\n\n        assert_eq!(AirQuality::read_tvoc(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(data_cell.get(), Some(100));\n\n        AirQuality::unregister_listener();\n        assert_eq!(AirQuality::read_co2(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(AirQuality::read_tvoc(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n}\n\n#[test]\nfn read_co2_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AirQuality::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(100);\n    assert_eq!(AirQuality::read_co2_sync(), Ok(100));\n}\n\n#[test]\nfn read_tvoc_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AirQuality::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(100);\n    assert_eq!(AirQuality::read_tvoc_sync(), Ok(100));\n}\n\n#[test]\nfn read_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AirQuality::new();\n    kernel.add_driver(&driver);\n\n    driver.set_values_sync(100, 200);\n    assert_eq!(AirQuality::read_sync(), Ok((100, 200)))\n}\n"
  },
  {
    "path": "apis/sensors/ambient_light/Cargo.toml",
    "content": "[package]\nname = \"libtock_ambient_light\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock ambient light driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/sensors/ambient_light/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n    share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\npub struct AmbientLight<S: Syscalls>(S);\n\nimpl<S: Syscalls> AmbientLight<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Initiate a light intensity reading.\n    pub fn read_intensity() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_INTENSITY, 0, 0).to_result()\n    }\n\n    /// Register an events listener\n    pub fn register_listener<'share, F: Fn(u32)>(\n        listener: &'share IntensityListener<F>,\n        subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Initiate a synchronous light intensity measurement.\n    /// Returns Ok(intensity_value) if the operation was successful\n    /// intensity_value is returned in lux\n    pub fn read_intensity_sync() -> Result<u32, ErrorCode> {\n        let intensity_cell: Cell<Option<u32>> = Cell::new(None);\n        let listener = IntensityListener(|intensity_val| {\n            intensity_cell.set(Some(intensity_val));\n        });\n\n        share::scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            Self::read_intensity()?;\n            while intensity_cell.get().is_none() {\n                S::yield_wait();\n            }\n\n            match intensity_cell.get() {\n                None => Err(ErrorCode::Busy),\n                Some(intensity_val) => Ok(intensity_val),\n            }\n        })\n    }\n}\n\n/// A wrapper around a closure to be registered and called when\n/// a luminance reading is done.\n///\n/// ```ignore\n/// let listener = IntensityListener(|intensity_val| {\n///     // make use of the intensity value\n/// });\n/// ```\npub struct IntensityListener<F: Fn(u32)>(pub F);\n\nimpl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for IntensityListener<F> {\n    fn upcall(&self, intensity: u32, _arg1: u32, _arg2: u32) {\n        self.0(intensity)\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60002;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ_INTENSITY: u32 = 1;\n"
  },
  {
    "path": "apis/sensors/ambient_light/src/tests.rs",
    "content": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\nuse crate::IntensityListener;\n\ntype AmbientLight = super::AmbientLight<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(AmbientLight::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AmbientLight::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(AmbientLight::exists(), Ok(()));\n}\n\n#[test]\nfn read_temperature() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AmbientLight::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(AmbientLight::read_intensity(), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(AmbientLight::read_intensity(), Err(ErrorCode::Busy));\n    assert_eq!(AmbientLight::read_intensity_sync(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn register_unregister_listener() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AmbientLight::new();\n    kernel.add_driver(&driver);\n\n    let intensity_cell: Cell<Option<u32>> = Cell::new(None);\n    let listener = IntensityListener(|val| {\n        intensity_cell.set(Some(val));\n    });\n    share::scope(|subscribe| {\n        assert_eq!(AmbientLight::read_intensity(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(\n            AmbientLight::register_listener(&listener, subscribe),\n            Ok(())\n        );\n        assert_eq!(AmbientLight::read_intensity(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(intensity_cell.get(), Some(100));\n\n        AmbientLight::unregister_listener();\n        assert_eq!(AmbientLight::read_intensity(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n}\n\n#[test]\nfn read_temperature_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::AmbientLight::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(1000);\n    assert_eq!(AmbientLight::read_intensity_sync(), Ok(1000));\n}\n"
  },
  {
    "path": "apis/sensors/ninedof/Cargo.toml",
    "content": "[package]\nname = \"libtock_ninedof\"\nversion = \"0.1.0\"\nauthors = [ \"Tock Project Developers <tock-dev@googlegroups.com>\" ]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2018\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock nine degrees of freedom driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\nlibm = \"0.2.7\"\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/sensors/ninedof/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n    share, share::Handle, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\npub struct NineDof<S: Syscalls>(S);\n\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\npub struct NineDofData {\n    pub x: i32,\n    pub y: i32,\n    pub z: i32,\n}\n\nimpl<S: Syscalls> NineDof<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Initiate a accelerometer measurement.\n    /// This function is used both for synchronous and asynchronous readings\n    pub fn read_accelerometer() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_ACCELEROMETER, 0, 0).to_result()\n    }\n\n    /// Initiate a magnetometer measurement.\n    /// This function is used both for synchronous and asynchronous readings\n    pub fn read_magnetometer() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_MAGNETOMETER, 0, 0).to_result()\n    }\n\n    /// Initiate a gyroscope measurement.\n    /// This function is used both for synchronous and asynchronous readings\n    pub fn read_gyro() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_GYRO, 0, 0).to_result()\n    }\n\n    /// Unregister an events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Register an events listener\n    pub fn register_listener<'share, F: Fn(NineDofData)>(\n        listener: &'share NineDofListener<F>,\n        subscribe: Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Initiate a synchronous accelerometer measurement.\n    /// Returns Ok(accelerometer_value) if the operation was successful\n    /// Returns Err(ErrorCode) if the operation was unsuccessful\n    pub fn read_accelerometer_sync() -> Result<NineDofData, ErrorCode> {\n        let data_cell: Cell<Option<NineDofData>> = Cell::new(None);\n        let listener = NineDofListener(|data| {\n            data_cell.set(Some(data));\n        });\n        share::scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            Self::read_accelerometer()?;\n            while data_cell.get().is_none() {\n                S::yield_wait();\n            }\n            match data_cell.get() {\n                None => Err(ErrorCode::Fail),\n                Some(data) => Ok(data),\n            }\n        })\n    }\n\n    /// Initiate a synchronous magnetometer measurement.\n    /// Returns Ok(data) if the operation was successful\n    /// Returns Err(ErrorCode) if the operation was unsuccessful\n    pub fn read_magnetometer_sync() -> Result<NineDofData, ErrorCode> {\n        let data_cell: Cell<Option<NineDofData>> = Cell::new(None);\n        let listener = NineDofListener(|data| {\n            data_cell.set(Some(data));\n        });\n        share::scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            Self::read_magnetometer()?;\n            while data_cell.get().is_none() {\n                S::yield_wait();\n            }\n            match data_cell.get() {\n                None => Err(ErrorCode::Fail),\n                Some(data) => Ok(data),\n            }\n        })\n    }\n\n    /// Initiate a synchronous gyroscope measurement.\n    /// Returns Ok(data) as NineDofData if the operation was successful\n    /// Returns Err(ErrorCode) if the operation was unsuccessful\n    pub fn read_gyroscope_sync() -> Result<NineDofData, ErrorCode> {\n        let data_cell: Cell<Option<NineDofData>> = Cell::new(None);\n        let listener = NineDofListener(|data| {\n            data_cell.set(Some(data));\n        });\n        share::scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            Self::read_gyro()?;\n            while data_cell.get().is_none() {\n                S::yield_wait();\n            }\n            match data_cell.get() {\n                None => Err(ErrorCode::Fail),\n                Some(data) => Ok(data),\n            }\n        })\n    }\n\n    /// Calculate the magnitude of the accelerometer reading\n    /// Returns value of magnitude if the operation was successful\n    /// Returns 0.0 if the operation was unsuccessful\n    pub fn read_accelerometer_mag() -> f64 {\n        let data = Self::read_accelerometer_sync();\n\n        match data {\n            Ok(data) => {\n                let x = data.x as f64;\n                let y = data.y as f64;\n                let z = data.z as f64;\n                libm::sqrt(x * x + y * y + z * z)\n            }\n            Err(_) => 0.0,\n        }\n    }\n}\n\npub struct NineDofListener<F: Fn(NineDofData)>(pub F);\n\nimpl<F: Fn(NineDofData)> Upcall<OneId<DRIVER_NUM, 0>> for NineDofListener<F> {\n    fn upcall(&self, arg0: u32, arg1: u32, arg2: u32) {\n        (self.0)(NineDofData {\n            x: arg0 as i32,\n            y: arg1 as i32,\n            z: arg2 as i32,\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60004;\n\n// Command IDs\nconst EXISTS: u32 = 0;\nconst READ_ACCELEROMETER: u32 = 1;\nconst READ_MAGNETOMETER: u32 = 100;\nconst READ_GYRO: u32 = 200;\n"
  },
  {
    "path": "apis/sensors/ninedof/src/tests.rs",
    "content": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\nuse crate::NineDofData;\n\ntype NineDof = super::NineDof<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(NineDof::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(NineDof::exists(), Ok(()));\n}\n\n#[test]\nfn driver_busy() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(NineDof::read_accelerometer(), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(NineDof::read_accelerometer(), Err(ErrorCode::Busy));\n    assert_eq!(NineDof::read_accelerometer_sync(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn read_accelerometer() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    let acceleration_listener: Cell<Option<NineDofData>> = Cell::new(None);\n    let acceleration_listener = crate::NineDofListener(|data| {\n        acceleration_listener.set(Some(data));\n    });\n\n    share::scope(|subscribe| {\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(\n            NineDof::register_listener(&acceleration_listener, subscribe),\n            Ok(())\n        );\n        assert_eq!(NineDof::read_accelerometer(), Ok(()));\n        driver.set_value(fake::NineDofData { x: 1, y: 2, z: 3 });\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    });\n}\n\n#[test]\nfn read_magnetometer() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    let magnetometer_listener: Cell<Option<NineDofData>> = Cell::new(None);\n    let magnetometer_listener = crate::NineDofListener(|data| {\n        magnetometer_listener.set(Some(data));\n    });\n\n    share::scope(|subscribe| {\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(\n            NineDof::register_listener(&magnetometer_listener, subscribe),\n            Ok(())\n        );\n        assert_eq!(NineDof::read_accelerometer(), Ok(()));\n        driver.set_value(fake::NineDofData { x: 1, y: 2, z: 3 });\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    });\n}\n\n#[test]\nfn read_gyro() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    let gyro_listener: Cell<Option<NineDofData>> = Cell::new(None);\n    let gyro_listener = crate::NineDofListener(|data| {\n        gyro_listener.set(Some(data));\n    });\n\n    share::scope(|subscribe| {\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(\n            NineDof::register_listener(&gyro_listener, subscribe),\n            Ok(())\n        );\n        assert_eq!(NineDof::read_accelerometer(), Ok(()));\n        driver.set_value(fake::NineDofData { x: 1, y: 2, z: 3 });\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    });\n}\n\n#[test]\nfn register_unregister_listener() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    let acceleration_listener: Cell<Option<NineDofData>> = Cell::new(None);\n    let acceleration_listener = crate::NineDofListener(|data| {\n        acceleration_listener.set(Some(data));\n    });\n    let magnetometer_listener: Cell<Option<NineDofData>> = Cell::new(None);\n    let magnetometer_listener = crate::NineDofListener(|data| {\n        magnetometer_listener.set(Some(data));\n    });\n    let gyro_listener: Cell<Option<NineDofData>> = Cell::new(None);\n    let gyro_listener = crate::NineDofListener(|data| {\n        gyro_listener.set(Some(data));\n    });\n\n    share::scope(|subscribe| {\n        assert_eq!(NineDof::read_accelerometer(), Ok(()));\n        driver.set_value(fake::NineDofData { x: 1, y: 2, z: 3 });\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(\n            NineDof::register_listener(&acceleration_listener, subscribe),\n            Ok(())\n        );\n\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(NineDof::read_gyro(), Ok(()));\n        driver.set_value(fake::NineDofData { x: 4, y: 5, z: 6 });\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        assert_eq!(\n            NineDof::register_listener(&gyro_listener, subscribe),\n            Ok(())\n        );\n\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(NineDof::read_magnetometer(), Ok(()));\n        driver.set_value(fake::NineDofData { x: 7, y: 8, z: 9 });\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(\n            NineDof::register_listener(&magnetometer_listener, subscribe),\n            Ok(())\n        );\n    })\n}\n\n#[test]\nfn read_accelerometer_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(fake::NineDofData { x: 1, y: 2, z: 3 });\n    let data = NineDof::read_accelerometer_sync();\n    assert_eq!(data, Ok(NineDofData { x: 1, y: 2, z: 3 }));\n}\n\n#[test]\nfn read_magnetometer_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(fake::NineDofData { x: 1, y: 2, z: 3 });\n\n    let data = NineDof::read_magnetometer_sync();\n\n    assert_eq!(data, Ok(NineDofData { x: 1, y: 2, z: 3 }));\n}\n\n#[test]\nfn read_gyro_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::NineDof::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(fake::NineDofData { x: 1, y: 2, z: 3 });\n    let value = NineDof::read_gyroscope_sync();\n    assert_eq!(value, Ok(NineDofData { x: 1, y: 2, z: 3 }));\n}\n"
  },
  {
    "path": "apis/sensors/proximity/Cargo.toml",
    "content": "[package]\nname = \"libtock_proximity\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock proximity driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n\n"
  },
  {
    "path": "apis/sensors/proximity/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\n\nuse libtock_platform::{share, DefaultConfig, ErrorCode, Subscribe, Syscalls};\n\npub struct Proximity<S: Syscalls>(S);\n\nimpl<S: Syscalls> Proximity<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Register an events listener\n    pub fn register_listener<'share>(\n        listener: &'share Cell<Option<(u32,)>>,\n        subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Initiate a proximity measurement\n    pub fn read() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ, 0, 0).to_result()\n    }\n\n    /// Initiate a synchronous proximity measurement.\n    /// Returns Ok(proximity_value) if the operation was successful\n    /// proximity_value is in [0, 255] range,\n    /// where '255' indicates the closest measurable distance and '0' that no object is detected\n    pub fn read_sync() -> Result<u8, ErrorCode> {\n        let listener: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            if let Ok(()) = Self::register_listener(&listener, subscribe) {\n                if let Ok(()) = Self::read() {\n                    S::yield_wait();\n                }\n            }\n        });\n\n        match listener.get() {\n            None => Err(ErrorCode::Busy),\n            Some(proximity) => Ok(proximity.0 as u8),\n        }\n    }\n\n    /// Initiate an on_interrupt proximity measurement\n    /// The sensor reads values continuously and executes the callback only if\n    /// proximity_value < lower or proximity_value > upper\n    /// lower - lower interrupt threshold for sensor --> range is [0,255]\n    /// upper - upper interrupt threshold for sensor --> range is [0,255]\n    /// lower <= upper\n    pub fn read_on_interrupt(lower: u8, upper: u8) -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_ON_INT, lower as u32, upper as u32).to_result()\n    }\n\n    /// Initiate a synchronous on_interrupt proximity measurement.\n    /// Returns Ok(proximity_value) if the operation was successful\n    /// proximity_value is in [0, 255] range,\n    /// where '255' indicates the closest measurable distance and '0' that no object is detected\n    /// Returns only when proximity_value < lower or proximity_value > upper\n    /// lower - lower interrupt threshold for sensor --> range is [0,255]\n    /// upper - upper interrupt threshold for sensor --> range is [0,255]\n    /// lower <= upper\n    pub fn wait_for_value_between(lower: u8, upper: u8) -> Result<u8, ErrorCode> {\n        if lower > upper {\n            return Err(ErrorCode::Invalid);\n        }\n        let listener: Cell<Option<(u32,)>> = Cell::new(None);\n        share::scope(|subscribe| {\n            if let Ok(()) = Self::register_listener(&listener, subscribe) {\n                if let Ok(()) = Self::read_on_interrupt(lower, upper) {\n                    while listener.get().is_none() {\n                        S::yield_wait();\n                    }\n                }\n            }\n        });\n\n        match listener.get() {\n            None => Err(ErrorCode::Busy),\n            Some(proximity) => Ok(proximity.0 as u8),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60005;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ: u32 = 1;\nconst READ_ON_INT: u32 = 2;\n"
  },
  {
    "path": "apis/sensors/proximity/src/tests.rs",
    "content": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\ntype Proximity = super::Proximity<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Proximity::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Proximity::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Proximity::exists(), Ok(()));\n}\n\n#[test]\nfn busy_driver() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Proximity::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Proximity::read(), Ok(()));\n    assert_eq!(Proximity::read(), Err(ErrorCode::Busy));\n    assert_eq!(Proximity::read_on_interrupt(0, 0), Err(ErrorCode::Busy));\n\n    driver.set_value(100);\n\n    assert_eq!(Proximity::read_on_interrupt(0, 0), Ok(()));\n    assert_eq!(Proximity::read(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn async_readings() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Proximity::new();\n    kernel.add_driver(&driver);\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n\n    share::scope(|subscribe| {\n        assert_eq!(Proximity::read(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(Proximity::register_listener(&listener, subscribe), Ok(()));\n        assert_eq!(Proximity::read(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        assert_eq!(Proximity::read_on_interrupt(100, 200), Ok(()));\n        driver.set_value(150);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        driver.set_value(99);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((99,)));\n    })\n}\n\n#[test]\nfn sync_readings() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Proximity::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(100);\n    assert_eq!(Proximity::read_sync(), Ok(100));\n\n    driver.set_value_sync(250);\n    assert_eq!(Proximity::wait_for_value_between(100, 200), Ok(250));\n}\n\n#[test]\nfn bad_arguments() {\n    assert_eq!(\n        Proximity::wait_for_value_between(200, 100),\n        Err(ErrorCode::Invalid)\n    );\n}\n"
  },
  {
    "path": "apis/sensors/sound_pressure/Cargo.toml",
    "content": "[package]\nname = \"libtock_sound_pressure\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2018\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock sound pressure driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/sensors/sound_pressure/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n    share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\npub struct SoundPressure<S: Syscalls>(S);\n\nimpl<S: Syscalls> SoundPressure<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Initiate a pressure measurement.\n    /// This function is used both for synchronous and asynchronous readings\n    pub fn read() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_PRESSURE, 0, 0).to_result()\n    }\n\n    /// Register an events listener\n    pub fn register_listener<'share, F: Fn(u32)>(\n        listener: &'share SoundPressureListener<F>,\n        subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Enable sound pressure measurement\n    pub fn enable() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, 2, 0, 0).to_result()\n    }\n\n    /// Disable sound pressure measurement\n    pub fn disable() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, 3, 0, 0).to_result()\n    }\n\n    /// Initiate a synchronous pressure measurement.\n    /// Returns Ok(pressure_value) if the operation was successful\n    /// pressure_value is between 0 and 255\n    pub fn read_sync() -> Result<u8, ErrorCode> {\n        let pressure_cell: Cell<Option<u32>> = Cell::new(None);\n        let listener = SoundPressureListener(|pressure_val| {\n            pressure_cell.set(Some(pressure_val));\n        });\n        share::scope(|subscribe| {\n            Self::register_listener(&listener, subscribe)?;\n            Self::read()?;\n            while pressure_cell.get().is_none() {\n                S::yield_wait();\n            }\n            match pressure_cell.get() {\n                None => Err(ErrorCode::Fail),\n                Some(pressure_val) => {\n                    if !(0..=256).contains(&pressure_val) {\n                        Err(ErrorCode::Invalid)\n                    } else {\n                        Ok(pressure_val as u8)\n                    }\n                }\n            }\n        })\n    }\n}\n\npub struct SoundPressureListener<F: Fn(u32)>(pub F);\nimpl<F: Fn(u32)> Upcall<OneId<DRIVER_NUM, 0>> for SoundPressureListener<F> {\n    fn upcall(&self, pressure_val: u32, _arg1: u32, _arg2: u32) {\n        (self.0)(pressure_val);\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60006;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ_PRESSURE: u32 = 1;\n"
  },
  {
    "path": "apis/sensors/sound_pressure/src/tests.rs",
    "content": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\ntype SoundPressure = super::SoundPressure<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(SoundPressure::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::SoundPressure::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(SoundPressure::exists(), Ok(()));\n}\n\n#[test]\nfn driver_busy() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::SoundPressure::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(SoundPressure::read(), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(SoundPressure::read(), Err(ErrorCode::Busy));\n    assert_eq!(SoundPressure::read_sync(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn read_pressure() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::SoundPressure::new();\n    kernel.add_driver(&driver);\n\n    let pressure_cell: Cell<Option<u32>> = Cell::new(None);\n    let listener = crate::SoundPressureListener(|pressure_val| {\n        pressure_cell.set(Some(pressure_val));\n    });\n\n    share::scope(|subscribe| {\n        assert_eq!(SoundPressure::read(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(\n            SoundPressure::register_listener(&listener, subscribe),\n            Ok(())\n        );\n        assert_eq!(SoundPressure::read(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(pressure_cell.get(), Some(100));\n\n        SoundPressure::unregister_listener();\n        assert_eq!(SoundPressure::read(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n}\n\n#[test]\nfn read_pressure_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::SoundPressure::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(100);\n    assert_eq!(SoundPressure::read_sync(), Ok(100));\n}\n"
  },
  {
    "path": "apis/sensors/temperature/Cargo.toml",
    "content": "[package]\nname = \"libtock_temperature\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock temperature driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/sensors/temperature/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform::{\n    share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall,\n};\n\npub struct Temperature<S: Syscalls>(S);\n\nimpl<S: Syscalls> Temperature<S> {\n    /// Returns Ok() if the driver was present.This does not necessarily mean\n    /// that the driver is working.\n    pub fn exists() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, EXISTS, 0, 0).to_result()\n    }\n\n    /// Initiate a temperature measurement.\n    ///\n    /// This function is used both for synchronous and asynchronous readings\n    pub fn read_temperature() -> Result<(), ErrorCode> {\n        S::command(DRIVER_NUM, READ_TEMP, 0, 0).to_result()\n    }\n\n    /// Register an events listener\n    pub fn register_listener<'share, F: Fn(i32)>(\n        listener: &'share TemperatureListener<F>,\n        subscribe: share::Handle<Subscribe<'share, S, DRIVER_NUM, 0>>,\n    ) -> Result<(), ErrorCode> {\n        S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener)\n    }\n\n    /// Unregister the events listener\n    pub fn unregister_listener() {\n        S::unsubscribe(DRIVER_NUM, 0)\n    }\n\n    /// Initiate a synchronous temperature measurement.\n    /// Returns Ok(temperature_value) if the operation was successful\n    /// temperature_value is returned in hundreds of centigrades\n    pub fn read_temperature_sync() -> Result<i32, ErrorCode> {\n        let temperature_cell: Cell<Option<i32>> = Cell::new(None);\n        let listener = TemperatureListener(|temp_val| {\n            temperature_cell.set(Some(temp_val));\n        });\n        share::scope(|subscribe| {\n            if let Ok(()) = Self::register_listener(&listener, subscribe) {\n                if let Ok(()) = Self::read_temperature() {\n                    while temperature_cell.get().is_none() {\n                        S::yield_wait();\n                    }\n                }\n            }\n        });\n\n        match temperature_cell.get() {\n            None => Err(ErrorCode::Busy),\n            Some(temp_val) => Ok(temp_val),\n        }\n    }\n}\n\npub struct TemperatureListener<F: Fn(i32)>(pub F);\nimpl<F: Fn(i32)> Upcall<OneId<DRIVER_NUM, 0>> for TemperatureListener<F> {\n    fn upcall(&self, temp_val: u32, _arg1: u32, _arg2: u32) {\n        self.0(temp_val as i32)\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60000;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ_TEMP: u32 = 1;\n"
  },
  {
    "path": "apis/sensors/temperature/src/tests.rs",
    "content": "use core::cell::Cell;\nuse libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::fake;\n\ntype Temperature = super::Temperature<fake::Syscalls>;\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert_eq!(Temperature::exists(), Err(ErrorCode::NoDevice));\n}\n\n#[test]\nfn exists() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Temperature::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Temperature::exists(), Ok(()));\n}\n\n#[test]\nfn read_temperature() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Temperature::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(Temperature::read_temperature(), Ok(()));\n    assert!(driver.is_busy());\n\n    assert_eq!(Temperature::read_temperature(), Err(ErrorCode::Busy));\n    assert_eq!(Temperature::read_temperature_sync(), Err(ErrorCode::Busy));\n}\n\n#[test]\nfn register_unregister_listener() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Temperature::new();\n    kernel.add_driver(&driver);\n\n    let temperature_cell: Cell<Option<i32>> = Cell::new(None);\n    let listener = crate::TemperatureListener(|temp_val| {\n        temperature_cell.set(Some(temp_val));\n    });\n    share::scope(|subscribe| {\n        assert_eq!(Temperature::read_temperature(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(Temperature::register_listener(&listener, subscribe), Ok(()));\n        assert_eq!(Temperature::read_temperature(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(temperature_cell.get(), Some(100));\n\n        Temperature::unregister_listener();\n        assert_eq!(Temperature::read_temperature(), Ok(()));\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n}\n\n#[test]\nfn read_temperature_sync() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Temperature::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(1000);\n    assert_eq!(Temperature::read_temperature_sync(), Ok(1000));\n}\n\n#[test]\nfn negative_value() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::Temperature::new();\n    kernel.add_driver(&driver);\n\n    driver.set_value_sync(-1000);\n    assert_eq!(Temperature::read_temperature_sync(), Ok(-1000));\n}\n"
  },
  {
    "path": "apis/storage/key_value/Cargo.toml",
    "content": "[package]\nname = \"libtock_key_value\"\nversion = \"0.1.0\"\nauthors = [\n    \"Tock Project Developers <tock-dev@googlegroups.com>\",\n]\nlicense = \"MIT/Apache-2.0\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\ndescription = \"libtock key-value driver\"\n\n[dependencies]\nlibtock_platform = { path = \"../../../platform\" }\n\n[dev-dependencies]\nlibtock_unittest = { path = \"../../../unittest\" }\n"
  },
  {
    "path": "apis/storage/key_value/src/lib.rs",
    "content": "#![no_std]\n\nuse core::cell::Cell;\nuse libtock_platform as platform;\nuse libtock_platform::allow_ro::AllowRo;\nuse libtock_platform::allow_rw::AllowRw;\nuse libtock_platform::share;\nuse libtock_platform::subscribe::Subscribe;\nuse libtock_platform::{DefaultConfig, ErrorCode, Syscalls};\n\n/// The key-value driver.\n///\n/// It provides access to a key-value store.\npub struct KeyValue<S: Syscalls, C: Config = DefaultConfig>(S, C);\n\nimpl<S: Syscalls, C: Config> KeyValue<S, C> {\n    /// Run a check against the key-value capsule to ensure it is present.\n    #[inline(always)]\n    pub fn exists() -> bool {\n        S::command(DRIVER_NUM, command::DRIVER_CHECK, 0, 0).is_success()\n    }\n\n    /// Get a key-value object from the `key`.\n    pub fn get(key: &[u8], value: &mut [u8]) -> Result<u32, ErrorCode> {\n        let called: Cell<Option<Result<(u32,), ErrorCode>>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { allow_ro::KEY }>,\n                AllowRw<_, DRIVER_NUM, { allow_rw::VALUE_READ }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::CALLBACK }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_key, allow_value, subscribe) = handle.split();\n\n            S::allow_ro::<C, DRIVER_NUM, { allow_ro::KEY }>(allow_key, key)?;\n            S::allow_rw::<C, DRIVER_NUM, { allow_rw::VALUE_READ }>(allow_value, value)?;\n\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::CALLBACK }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, command::GET, 0, 0).to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some(ret) = called.get() {\n                    return ret.map(|(arg0,)| arg0);\n                }\n            }\n        })\n    }\n\n    /// Set a key-value object for the `key`.\n    fn insert(command_num: u32, key: &[u8], value: &[u8]) -> Result<(), ErrorCode> {\n        let called: Cell<Option<Result<(), ErrorCode>>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { allow_ro::KEY }>,\n                AllowRo<_, DRIVER_NUM, { allow_ro::VALUE_WRITE }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::CALLBACK }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_key, allow_value, subscribe) = handle.split();\n\n            S::allow_ro::<C, DRIVER_NUM, { allow_ro::KEY }>(allow_key, key)?;\n            S::allow_ro::<C, DRIVER_NUM, { allow_ro::VALUE_WRITE }>(allow_value, value)?;\n\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::CALLBACK }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, command_num, 0, 0).to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some(ret) = called.get() {\n                    return ret;\n                }\n            }\n        })\n    }\n\n    /// Set a key-value object for the `key`.\n    pub fn set(key: &[u8], value: &[u8]) -> Result<(), ErrorCode> {\n        Self::insert(command::SET, key, value)\n    }\n\n    /// Set a key-value object for the `key`.\n    pub fn add(key: &[u8], value: &[u8]) -> Result<(), ErrorCode> {\n        Self::insert(command::ADD, key, value)\n    }\n\n    /// Set a key-value object for the `key`.\n    pub fn update(key: &[u8], value: &[u8]) -> Result<(), ErrorCode> {\n        Self::insert(command::UPDATE, key, value)\n    }\n\n    /// Delete a key-value object by `key`.\n    pub fn delete(key: &[u8]) -> Result<(), ErrorCode> {\n        let called: Cell<Option<Result<(), ErrorCode>>> = Cell::new(None);\n        share::scope::<\n            (\n                AllowRo<_, DRIVER_NUM, { allow_ro::KEY }>,\n                Subscribe<_, DRIVER_NUM, { subscribe::CALLBACK }>,\n            ),\n            _,\n            _,\n        >(|handle| {\n            let (allow_key, subscribe) = handle.split();\n\n            S::allow_ro::<C, DRIVER_NUM, { allow_ro::KEY }>(allow_key, key)?;\n\n            S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::CALLBACK }>(subscribe, &called)?;\n\n            S::command(DRIVER_NUM, command::DELETE, 0, 0).to_result::<(), ErrorCode>()?;\n\n            loop {\n                S::yield_wait();\n                if let Some(ret) = called.get() {\n                    return ret;\n                }\n            }\n        })\n    }\n}\n\n/// System call configuration trait for `KeyValue`.\npub trait Config:\n    platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config\n{\n}\nimpl<T: platform::allow_ro::Config + platform::allow_rw::Config + platform::subscribe::Config>\n    Config for T\n{\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x50003;\n\n// Command IDs\n#[allow(unused)]\nmod command {\n    pub const DRIVER_CHECK: u32 = 0;\n    pub const GET: u32 = 1;\n    pub const SET: u32 = 2;\n    pub const DELETE: u32 = 3;\n    pub const ADD: u32 = 4;\n    pub const UPDATE: u32 = 5;\n}\n\n#[allow(unused)]\nmod subscribe {\n    pub const CALLBACK: u32 = 0;\n}\n\nmod allow_ro {\n    pub const KEY: u32 = 0;\n    pub const VALUE_WRITE: u32 = 1;\n}\n\nmod allow_rw {\n    pub const VALUE_READ: u32 = 0;\n}\n"
  },
  {
    "path": "apis/storage/key_value/src/tests.rs",
    "content": "use super::*;\nuse libtock_platform::ErrorCode;\nuse libtock_unittest::{command_return, fake, ExpectedSyscall};\n\ntype Kv = super::KeyValue<fake::Syscalls>;\n\nfn _get(kernel: &fake::Kernel) -> Result<u32, ErrorCode> {\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::KEY,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRw {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_rw::VALUE_READ,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: DRIVER_NUM,\n        subscribe_num: subscribe::CALLBACK,\n        skip_with_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: command::GET,\n        argument0: 0,\n        argument1: 0,\n        override_return: Some(command_return::success()),\n    });\n\n    let mut buf = [0; 3];\n    Kv::get(\"mykey\".as_bytes(), &mut buf)\n}\n\nfn _set(kernel: &fake::Kernel) -> Result<(), ErrorCode> {\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::KEY,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::VALUE_WRITE,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: DRIVER_NUM,\n        subscribe_num: subscribe::CALLBACK,\n        skip_with_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: command::SET,\n        argument0: 0,\n        argument1: 0,\n        override_return: Some(command_return::success()),\n    });\n\n    Kv::set(\"mykey\".as_bytes(), b\"hooray\")\n}\n\nfn _add(kernel: &fake::Kernel) -> Result<(), ErrorCode> {\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::KEY,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::VALUE_WRITE,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: DRIVER_NUM,\n        subscribe_num: subscribe::CALLBACK,\n        skip_with_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: command::ADD,\n        argument0: 0,\n        argument1: 0,\n        override_return: Some(command_return::success()),\n    });\n\n    Kv::add(\"mykey\".as_bytes(), b\"hooray2\")\n}\n\nfn _update(kernel: &fake::Kernel) -> Result<(), ErrorCode> {\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::KEY,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::VALUE_WRITE,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: DRIVER_NUM,\n        subscribe_num: subscribe::CALLBACK,\n        skip_with_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: command::UPDATE,\n        argument0: 0,\n        argument1: 0,\n        override_return: Some(command_return::success()),\n    });\n\n    Kv::update(\"mykey\".as_bytes(), b\"hooray3\")\n}\n\nfn _delete(kernel: &fake::Kernel) -> Result<(), ErrorCode> {\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: DRIVER_NUM,\n        buffer_num: allow_ro::KEY,\n        return_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: DRIVER_NUM,\n        subscribe_num: subscribe::CALLBACK,\n        skip_with_error: None,\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: DRIVER_NUM,\n        command_id: command::DELETE,\n        argument0: 0,\n        argument1: 0,\n        override_return: Some(command_return::success()),\n    });\n\n    Kv::delete(\"mykey\".as_bytes())\n}\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    assert!(!Kv::exists());\n}\n\n#[test]\nfn driver_check() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert!(Kv::exists());\n}\n\n#[test]\nfn get_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_get(&kernel), Err(ErrorCode::NoSupport));\n}\n\n#[test]\nfn set_get() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_set(&kernel), Ok(()));\n    assert_eq!(_get(&kernel), Ok(6));\n}\n\n#[test]\nfn add() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_add(&kernel), Ok(()));\n}\n\n#[test]\nfn add_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_set(&kernel), Ok(()));\n    assert_eq!(_add(&kernel), Err(ErrorCode::NoSupport));\n}\n\n#[test]\nfn update() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_set(&kernel), Ok(()));\n    assert_eq!(_update(&kernel), Ok(()));\n}\n\n#[test]\nfn update_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_update(&kernel), Err(ErrorCode::NoSupport));\n}\n\n#[test]\nfn delete() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_set(&kernel), Ok(()));\n    assert_eq!(_delete(&kernel), Ok(()));\n}\n\n#[test]\nfn delete_fail() {\n    let kernel = fake::Kernel::new();\n    let driver = fake::KeyValue::new();\n    kernel.add_driver(&driver);\n\n    assert_eq!(_delete(&kernel), Err(ErrorCode::NoSupport));\n}\n"
  },
  {
    "path": "build.rs",
    "content": "fn main() {\n    libtock_build_scripts::auto_layout();\n}\n"
  },
  {
    "path": "build_scripts/Cargo.toml",
    "content": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\ndescription = \"\"\"Helper functions for compiling libtock-rs apps.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nname = \"libtock_build_scripts\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n"
  },
  {
    "path": "build_scripts/README.md",
    "content": "Libtock Build Scripts Support Crate\n===================================\n\nThis crate provides helpers for building libtock-rs apps.\n\nUsage\n-----\n\nThere are three general steps to use this crate.\n\n1. This crate should be included as a build dependency in the app's Cargo.toml\n   file:\n\n   ```toml\n   # Cargo.toml\n   ...\n\n   [build-dependencies]\n   libtock_build_scripts = { git = \"https://github.com/tock/libtock-rs\"}\n   ```\n\n   This will ensure the crate and the contained linker scripts are available for\n   the app build.\n\n2. This crate provides a helper function which can used from the libtock-rs\n   app's build.rs file. In the common case, you just call the provided function\n   from the build.rs file in your crate's root:\n\n   ```rs\n   // build.rs\n\n   fn main() {\n       libtock_build_scripts::auto_layout();\n   }\n   ```\n\n   This will allow cargo to setup linker scripts and paths for the linker when\n   your app is built.\n\n3. When calling `cargo build` you need to instruct the build.rs on where in\n   memory to compile your app for. This crate supports two mechanisms to do\n   this. You can only use one.\n\n   1. Set the `LIBTOCK_PLATFORM` environment variable which specifies the name\n      of the linker script in `/layouts` to be used. So for example, if you are\n      using the microbit_v2 you might run:\n\n      ```bash\n      $ LIBTOCK_PLATFORM=microbit_v2 cargo build --target thumbv7em-none-eabi --release\n      ```\n\n   2. Set the `LIBTOCK_LINKER_FLASH` and `LIBTOCK_LINKER_RAM` environment\n      variables which specify the starting addresses of flash and RAM memory,\n      respectively. This allows you to customize where exactly the compiled app\n      must be placed in flash and RAM. For example, to build for common\n      Cortex-M4 platforms you might run:\n\n      ```bash\n      $ LIBTOCK_LINKER_FLASH=0x00040000 LIBTOCK_LINKER_RAM=0x20008000 cargo build --target thumbv7em-none-eabi --release\n      ```\n"
  },
  {
    "path": "build_scripts/libtock_layout.ld",
    "content": "/* Layout file for Tock process binaries that use libtock-rs. This currently\n * implements static linking, because we do not have a working\n * position-independent relocation solution. This layout works for all\n * platforms libtock-rs supports (ARM and RISC-V).\n *\n * This layout should be included by a script that defines the FLASH and RAM\n * regions for the board as well as TBF_HEADER_SIZE. Here is a an example\n * process binary linker script to get started:\n *\n *     TBF_HEADER_SIZE = 0x60;\n *\n *     FLASH_START = 0x10000;\n *     FLASH_LENGTH = 0x10000;\n *\n *     RAM_START = 0x20000;\n *     RAM_LENGTH = 0x10000;\n *\n *     INCLUDE ../libtock-rs/layout.ld\n *\n * FLASH refers to the area the process binary occupies in flash (including the\n * TBF headers, so FLASH_START refers to the TBF load address). RAM refers to\n * the area the process will have access to in memory. STACK_SIZE is the size of\n * the process' stack (this layout file may round the stack size up for\n * alignment purposes).\n *\n * This places the flash sections in the following order:\n *     1. .rt_header -- Constants used by runtime initialization.\n *     2. .text      -- Executable code.\n *     3. .rodata    -- Read-only global data (e.g. most string constants).\n *     4. .data      -- Read-write data, copied to RAM at runtime.\n *\n * This places the RAM sections in the following order:\n *     1. .stack -- The stack grows downward. Putting it first gives us\n *                  MPU-based overflow detection.\n *     2. .data  -- Read-write data, initialized by copying from flash.\n *     3. .bss   -- Zero-initialized read-write global data.\n *     4. Heap   -- The heap (optional) comes after .bss and grows upwards to\n *                  the process break.\n *\n * TBF_HEADER_SIZE is further used internally in the included `layout.ld` file\n * to set the `tbf_protected_region_size` symbol. elf2tab will thus prepend TBF\n * headers and an optional padding such that the final binary matches the\n * intended app load address (0x10000 in the above example).\n */\n\n/* TODO: Should TBF_HEADER_SIZE be configured via a similar mechanism to the\n * stack size? We should see if that is possible.\n */\n\n/* Rust's default linker (llvm-ld) as used with the Rust toolchain versions of\n * at least 2022-06-10, 2023-01-26, and 2023-06-27 can produce broken ELF\n * binaries when the RAM region's start address is not well-aligned to a 4kB\n * boundary. Unfortunately, this behavior is rather tricky to debug: instead of\n * refusing to produce a binary or producing a corrupt output, it generates an\n * ELF file which includes a segment that points to the ELF file's header\n * itself. elf2tab will include this segment in the final binary (as it is set\n * to be loaded), producing broken TBFs. This (overrideable) check is designed\n * to warn users that the linker may be misbehaved under these conditions.\n */\nPROVIDE(LIBTOCKRS_OVERRIDE_RAM_ORIGIN_CHECK = 0);\nASSERT(LIBTOCKRS_OVERRIDE_RAM_ORIGIN_CHECK == 1 || RAM_START % 0x1000 == 0, \"\nStart of RAM region must be well-aligned to a 4kB boundary for LLVM's lld to\nwork. Refer to https://github.com/tock/libtock-rs/pull/477 for more\ninformation. Set LIBTOCKRS_OVERRIDE_RAM_ORIGIN_CHECK = 1 to override this check\n(e.g., when using a different linker).\");\n\nMEMORY {\n  FLASH (X) : ORIGIN = FLASH_START + TBF_HEADER_SIZE, LENGTH = FLASH_LENGTH - TBF_HEADER_SIZE\n  RAM   (W) : ORIGIN = RAM_START                    , LENGTH = RAM_LENGTH\n}\n\n/* GNU LD looks for `start` as an entry point by default, while LLVM's LLD looks\n * for `_start`. To be compatible with both, we manually specify an entry point.\n */\nENTRY(start)\n\nSECTIONS {\n    /* The FLASH memory section is placed at a TBF_HEADER_SIZE offset, to give\n     * elf2tab room to prepend the TBF headers. Communicate this reservation to\n     * elf2tab, such that it fills up the space after the TBF headers (if any)\n     * as part of the protected region trailer:\n     */\n    tbf_protected_region_size = TBF_HEADER_SIZE;\n\n    /* Sections located in FLASH at runtime.\n     */\n\n    /* Runtime header. Contains values the linker knows that the runtime needs\n     * to look up.\n     */\n    . = ALIGN(4);\n    .start : {\n        /* We combine rt_header and _start into a single section. If we don't,\n         * elf2tab does not parse the ELF file correctly for unknown reasons.\n         */\n        rt_header = .;\n        LONG(start & 0xFFFFFFFE);        /* .start w/ Thumb bit unset */\n        LONG(ADDR(.bss) + SIZEOF(.bss)); /* Initial process break */\n        LONG(_stack_top);\n        LONG(SIZEOF(.data));\n        LONG(LOADADDR(.data));\n        LONG(ADDR(.data));\n        LONG(SIZEOF(.bss));\n        LONG(ADDR(.bss));\n\n        *(.start)\n    } > FLASH\n\n    /* Text section -- the application's code. */\n    .text ALIGN(4) : {\n        *(.text.*)\n    } > FLASH\n\n    /* Read-only data section. Contains strings and other global constants. */\n    .rodata ALIGN(4) : {\n        *(.rodata.*)\n\n        /* Generated by GCC in libraries for variables that still have relocations but are constant\n         * at runtime. See https://www.airs.com/blog/archives/189 for background.\n         */\n        *(.data.rel.ro.*)\n    } > FLASH\n\n    /* Sections located in RAM at runtime.\n     */\n\n    /* Reserve space for the stack. Aligned to a multiple of 16 bytes for the\n     * RISC-V calling convention:\n     * https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf\n     */\n    .stack (NOLOAD) : {\n\t/* _sram_origin is used by elf2tab:\n\t * https://github.com/tock/elf2tab/blob/master/src/main.rs#L301\n\t */\n        _sram_origin = .;\n        KEEP(*(.stack_buffer))\n        . = ALIGN(16);\n        _stack_top = .;  /* Used in rt_header */\n    } > RAM AT > FLASH\n\n    /* Read-write data section. This is deployed as part of FLASH but is copied\n     * into RAM at runtime.\n     */\n    .data ALIGN(4) : {\n        data_ram_start = .;\n        /* .sdata is the RISC-V small data section */\n        *(.sdata .data*)\n        /* Pad to word alignment so the relocation loop can use word-sized\n         * copies.\n         */\n        . = ALIGN(4);\n    } > RAM AT > FLASH\n\n    /* BSS section. These are zero-initialized static variables. This section is\n     * not copied from FLASH into RAM but rather directly initialized, and is\n     * mainly put in this linker script so that we get an error if it overflows\n     * the RAM region.\n     */\n    .bss ALIGN(4) (NOLOAD) : {\n        /* .sbss is the RISC-V small data section */\n        *(.sbss .bss.*)\n    } > RAM AT > FLASH\n\n    _heap_start = ADDR(.bss) + SIZEOF(.bss);  /* Used by rt_header */\n\n    /* Sections we do not need. */\n    /DISCARD/ :\n    {\n      *(.ARM.exidx .eh_frame)\n    }\n}\n\n/* Check that the linker thinks our start of flash is page aligned. Now, the\n * linker doesn't actually know the size of pages, and for our purposes we don't\n * necessarily care that these are aligned, but the linker will generate\n * segments which are aligned to what it thinks the page size is. This will\n * cause the linker to insert segments _before_ `FLASH_START`, which is not what\n * we intend. To ensure more valid-looking .elf files, we check that\n * `FLASH_START` is aligned to what the linker thinks is the page size.\n *\n * If this check fails, it is likely the linker is using a page size of 0x10000\n * (based on observations in Aug 2023). The linker argument `-z\n * max-page-size=4096` changes this setting. We recommend adding\n * `println!(\"cargo:rustc-link-arg=-zmax-page-size=4096\");` to your build.rs\n * file to fix this issue.\n */\nASSERT(FLASH_START % CONSTANT(MAXPAGESIZE)==0, \"\nFLASH_START not page aligned according to the linker.\nThis will cause issues with generated .elf segments.\nThe linker is probably assuming too large of a page size.\nAdd `println!('cargo:rustc-link-arg=-zmax-page-size=4096');` to build.rs to fix.\")\n"
  },
  {
    "path": "build_scripts/src/lib.rs",
    "content": "//! Utility functions for implementing build.rs files for libtock-rs apps.\n\n/// List of known `LIBTOCK_PLATFORM` values.\n#[rustfmt::skip]\nconst PLATFORMS: &[(&str, &str, &str, &str, &str)] = &[\n    // Name               | Flash start | Flash len  | RAM start   | RAM length\n    (\"apollo3\"            , \"0x00040000\", \"0x00BE000\", \"0x10004000\", \"0x03000\"),\n    (\"clue_nrf52840\"      , \"0x00080000\", \"512K\"     , \"0x20006000\", \"216K\"   ),\n    (\"esp32_c3_devkitm_1\" , \"0x403B0000\", \"0x0030000\", \"0x3FCA2000\", \"0x2E000\"),\n    (\"hail\"               , \"0x00030000\", \"0x0040000\", \"0x20008000\", \"62K\"    ),\n    (\"hifive1\"            , \"0x20040000\", \"32M\"      , \"0x80003000\", \"0x01000\"),\n    (\"imix\"               , \"0x00040000\", \"0x0040000\", \"0x20008000\", \"62K\"    ),\n    (\"imxrt1050\"          , \"0x63002000\", \"0x1000000\", \"0x20004000\", \"112K\"   ),\n    (\"microbit_v2\"        , \"0x00040000\", \"256K\"     , \"0x20004000\", \"112K\"   ),\n    (\"msp432\"             , \"0x00020000\", \"0x0020000\", \"0x20004000\", \"0x02000\"),\n    (\"nano_rp2040_connect\", \"0x10020000\", \"256K\"     , \"0x20004000\", \"248K\"   ),\n    (\"nrf52\"              , \"0x00030000\", \"0x0060000\", \"0x20004000\", \"62K\"    ),\n    (\"nrf52840\"           , \"0x00040000\", \"768K\"     , \"0x20010000\", \"128k\"    ),\n    (\"nucleo_f429zi\"      , \"0x08040000\", \"255K\"     , \"0x20004000\", \"112K\"   ),\n    (\"nucleo_f446re\"      , \"0x08040000\", \"255K\"     , \"0x20004000\", \"176K\"   ),\n    (\"opentitan\"          , \"0x20030000\", \"32M\"      , \"0x10006000\", \"126K\"   ),\n    (\"pico_explorer_base\" , \"0x10040000\", \"256K\"     , \"0x20012000\", \"192K\"   ),\n    (\"qemu_rv32_virt\"     , \"0x80100000\", \"0x0100000\", \"0x80300000\", \"1024K\"  ),\n    (\"raspberry_pi_pico\"  , \"0x10040000\", \"256K\"     , \"0x20012000\", \"192K\"   ),\n    (\"stm32f3discovery\"   , \"0x08020000\", \"0x0020000\", \"0x20004000\", \"48K\"    ),\n    (\"stm32f412gdiscovery\", \"0x08030000\", \"256K\"     , \"0x20004000\", \"112K\"   ),\n    (\"nano33ble\"          , \"0x00050000\", \"704K\"     , \"0x20005000\", \"240K\"   ),\n];\n\n/// Helper function to configure cargo to use suitable linker scripts for\n/// linking libtock-rs apps.\n///\n/// `auto_layout` function does a few things:\n///\n/// 1. Copies `libtock_layout.ld` into the linker's search path.\n/// 2. Generates a linker script that specifies which flash and RAM addresses\n///    the app should be compiled for. This linker script depends on the\n///    previously-mentioned `libtock_layout.ld`.\n/// 3. Passes the `-T<linker script.ld>` argument to the linker to make it use\n///    the generated linker script.\n///\n/// `auto_layout` supports two mechanisms for specifying the flash and RAM\n/// address ranges:\n///\n/// 1. Passing the `LIBTOCK_PLATFORM` environment variable, specifying one of a\n///    hardcoded list of known platforms. See the `PLATFORMS` variable above for\n///    the list of supported platforms.\n/// 2. Passing the `LIBTOCK_LINKER_FLASH` and `LIBTOCK_LINKER_RAM` environment\n///    variables which specify the starting addresses of flash and RAM memory,\n///    respectively.\n///\n/// Programs passing `LIBTOCK_LINKER_FLASH` and `LIBTOCK_LINKER_RAM` may\n/// additionally pass `LIBTOCK_TBF_HEADER_SIZE`, `LIBTOCK_LINKER_FLASH_LENGTH`,\n/// and/or `LIBTOCK_LINKER_RAM_LENGTH`. If not specified, this function will\n/// assume some default values for those variables.\npub fn auto_layout() {\n    use std::env::var;\n    use std::fs::File;\n    use std::io::Write;\n    use std::ops::Deref;\n    use std::path::PathBuf;\n\n    const LIBTOCK_LAYOUT_NAME: &str = \"libtock_layout.ld\";\n    const LINKER_FLASH_VAR: &str = \"LIBTOCK_LINKER_FLASH\";\n    const LINKER_FLASH_LEN_VAR: &str = \"LIBTOCK_LINKER_FLASH_LENGTH\";\n    const LINKER_RAM_VAR: &str = \"LIBTOCK_LINKER_RAM\";\n    const LINKER_RAM_LEN_VAR: &str = \"LIBTOCK_LINKER_RAM_LENGTH\";\n    const PLATFORM_VAR: &str = \"LIBTOCK_PLATFORM\";\n    const TBF_HEADER_SIZE_VAR: &str = \"LIBTOCK_TBF_HEADER_SIZE\";\n\n    // Note: we need to print these rerun-if commands before using the variable\n    // or file, so that if the build script fails cargo knows when to re-run it.\n    println!(\"cargo:rerun-if-env-changed={LINKER_FLASH_VAR}\");\n    println!(\"cargo:rerun-if-env-changed={LINKER_FLASH_LEN_VAR}\");\n    println!(\"cargo:rerun-if-env-changed={LINKER_RAM_VAR}\");\n    println!(\"cargo:rerun-if-env-changed={LINKER_RAM_LEN_VAR}\");\n    println!(\"cargo:rerun-if-env-changed={PLATFORM_VAR}\");\n    println!(\"cargo:rerun-if-env-changed={TBF_HEADER_SIZE_VAR}\");\n\n    let platform = get_env_var(PLATFORM_VAR);\n    let flash_start = get_env_var(LINKER_FLASH_VAR);\n    let ram_start = get_env_var(LINKER_RAM_VAR);\n    let flash_len;\n    let ram_len;\n    // Determine the flash and RAM address ranges. This detects whether\n    // LIBTOCK_PLATFORM was specified or whether the flash and RAM ranges were\n    // specified directly.\n    let (flash_start, flash_len, ram_start, ram_len) = match (platform, &flash_start, &ram_start) {\n        (None, Some(flash_start), Some(ram_start)) => {\n            // The flash and RAM ranges were specified directly.\n            flash_len = get_env_var(LINKER_FLASH_LEN_VAR);\n            ram_len = get_env_var(LINKER_RAM_LEN_VAR);\n            (\n                flash_start.deref(),\n                flash_len.as_deref().unwrap_or(\"0xD0000\"),\n                ram_start.deref(),\n                ram_len.as_deref().unwrap_or(\"46K\"),\n            )\n        }\n        (Some(platform), None, None) => {\n            // LIBTOCK_PLATFORM was specified.\n            match PLATFORMS\n                .iter()\n                .find(|&&(name, _, _, _, _)| name == platform)\n            {\n                None => panic!(\"Unknown platform: {platform}\"),\n                Some(&(_, flash_start, flash_len, ram_start, ram_len)) => {\n                    (flash_start, flash_len, ram_start, ram_len)\n                }\n            }\n        }\n        _ => panic!(\n            \"Must specify either {PLATFORM_VAR} or both {LINKER_FLASH_VAR} and {LINKER_RAM_VAR}; please see \\\n                     libtock_build_scripts' documentation for more information.\"\n        ),\n    };\n    let tbf_header_size;\n    let tbf_header_size = match get_env_var(TBF_HEADER_SIZE_VAR) {\n        None => \"0x80\",\n        Some(value) => {\n            tbf_header_size = value;\n            &tbf_header_size\n        }\n    };\n\n    // Note: cargo fails if run in a path that is not valid Unicode, so this\n    // script doesn't need to handle non-Unicode paths. Also, OUT_DIR cannot be\n    // in a location with a newline in it, or we have no way to pass\n    // rustc-link-search to cargo.\n    let out_dir = &*var(\"OUT_DIR\").expect(\"Unable to read OUT_DIR\");\n    assert!(\n        !out_dir.contains('\\n'),\n        \"Build path contains a newline, which is unsupported\"\n    );\n\n    // Create a valid linker file with the specified flash and ram locations.\n    //\n    // ```\n    // TBF_HEADER_SIZE = 0x80;\n    // FLASH_START = 0x00040000;\n    // FLASH_LENGTH = 0x00040000;\n    // RAM_START = 0x20008000;\n    // RAM_LENGTH = 62K;\n    // INCLUDE libtock_layout.ld\n    // ```\n    let layout_name = format!(\"{flash_start}.{flash_len}.{ram_start}.{ram_len}.ld\");\n    let layout_path: PathBuf = [out_dir, &layout_name].iter().collect();\n    let mut layout_file =\n        File::create(&layout_path).unwrap_or_else(|e| panic!(\"Could not open layout file: {e}\"));\n    writeln!(\n        layout_file,\n        \"\\\n        TBF_HEADER_SIZE = {tbf_header_size};\\n\\\n        FLASH_START = {flash_start};\\n\\\n        FLASH_LENGTH = {flash_len};\\n\\\n        RAM_START = {ram_start};\\n\\\n        RAM_LENGTH = {ram_len};\\n\\\n        INCLUDE {LIBTOCK_LAYOUT_NAME};\"\n    )\n    .expect(\"Failed to write layout file\");\n    drop(layout_file);\n\n    // Compile the contents of `libtock_layout.ld` into this library as a\n    // string, and copy those contents into out_dir at runtime.\n    let libtock_layout_path: PathBuf = [out_dir, LIBTOCK_LAYOUT_NAME].iter().collect();\n    let mut libtock_layout_file = File::create(libtock_layout_path)\n        .unwrap_or_else(|e| panic!(\"Could not open {LIBTOCK_LAYOUT_NAME}: {e}\"));\n    write!(\n        libtock_layout_file,\n        \"{}\",\n        include_str!(\"../libtock_layout.ld\")\n    )\n    .expect(\"Failed to write libtock_layout.ld\");\n    drop(libtock_layout_file);\n\n    // Tell rustc which linker script to use and where to find it.\n    println!(\"cargo:rustc-link-arg=-T{}\", layout_path.display());\n    println!(\"cargo:rustc-link-search={out_dir}\");\n\n    // Configure the alignment size for the linker. This prevents the linker\n    // from assuming very large pages (i.e. 65536 bytes) and unnecessarily\n    // inserting additional padding into the output ELF.\n    println!(\"cargo:rustc-link-arg=-zmax-page-size=4096\");\n}\n\n// Retrieves an environment variable as a String. Returns None if the variable\n// is not specified and panics if the variable is not valid Unicode.\nfn get_env_var(name: &str) -> Option<String> {\n    use std::env::{var, VarError};\n    match var(name) {\n        Ok(value) => Some(value),\n        Err(VarError::NotPresent) => None,\n        Err(VarError::NotUnicode(value)) => panic!(\"Non-Unicode value in {name}: {value:?}\"),\n    }\n}\n"
  },
  {
    "path": "demos/embedded_graphics/buttons/Cargo.toml",
    "content": "[package]\nname = \"buttons\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version = \"1.87\"\ndescription = \"libtock-rs button app with embedded graphics\"\n\n[dependencies]\nembedded-graphics = \"0.8.1\"\nlibm = \"0.2.15\"\n\nlibtock = { path = \"../../../\", version = \"0.1.0\" }\nlibtock_platform = { path = \"../../../platform\" }\nembedded_graphics_libtock = { path = \"../../../libraries/embedded_graphics_libtock\", version = \"0.1.0\" }\n\n[build-dependencies]\nlibtock_build_scripts = { path = \"../../../build_scripts\" }\n\n[workspace]\n"
  },
  {
    "path": "demos/embedded_graphics/buttons/Makefile",
    "content": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := buttons\n\nall: tab\n\ninclude ../../../Targets.mk\n\n$(ELF_TARGETS):\n\tLIBTOCK_LINKER_FLASH=$(F) LIBTOCK_LINKER_RAM=$(R) cargo build --target=$(T) --release\n\t@mkdir -p target/$(A).$(F).$(R)/\n\t@cp target/$(T)/release/$(DEMO) target/$(A).$(F).$(R)/\n\t$(eval ELF_LIST += target/$(A).$(F).$(R)/$(DEMO),$(A).$(F).$(R))\n\n# This target (`make tab`) is not parallel-safe\n.PHONY: tab\ntab: $(ELF_TARGETS)\n\t@mkdir -p target/tab\n\telf2tab --kernel-major 2 --kernel-minor 1 -n $(DEMO) -o target/tab/$(DEMO).tab --stack 1024 --minimum-footer-size 256 $(ELF_LIST)\n"
  },
  {
    "path": "demos/embedded_graphics/buttons/README.md",
    "content": "Buttons Demo Using Embedded Graphics\n====================================\n\nDraws buttons as circles on the screen. When a button is pressed the\ncorresponding circle is filled in.\n"
  },
  {
    "path": "demos/embedded_graphics/buttons/build.rs",
    "content": "fn main() {\n    libtock_build_scripts::auto_layout();\n}\n"
  },
  {
    "path": "demos/embedded_graphics/buttons/src/main.rs",
    "content": "#![no_main]\n#![no_std]\nuse core::cell::Cell;\nuse core::fmt::Write;\nuse libtock::buttons::{ButtonListener, ButtonState, Buttons};\nuse libtock::console::Console;\nuse libtock::runtime::{set_main, stack_size, TockSyscalls};\nuse libtock_platform::share;\nuse libtock_platform::ErrorCode;\nuse libtock_platform::Syscalls;\n\nuse embedded_graphics_libtock::tock_screen::TockMonochrome8BitPage128x64Screen;\n\nuse embedded_graphics::pixelcolor::BinaryColor;\nuse embedded_graphics::prelude::Point;\nuse embedded_graphics::prelude::Primitive;\nuse embedded_graphics::primitives::{Circle, PrimitiveStyle};\nuse embedded_graphics::Drawable;\n\nset_main! {main}\nstack_size! {4000}\n\nfn run() -> Result<(), ErrorCode> {\n    let mut screen = TockMonochrome8BitPage128x64Screen::new();\n\n    let width = screen.get_width();\n    let height = screen.get_height();\n\n    let button_count = Buttons::count()?;\n    writeln!(Console::writer(), \"[BUTTONS] Count: {}\", button_count).unwrap();\n\n    // Calculate where the buttons should be drawn.\n    let button_padding_px = (button_count - 1) * 2;\n    let max_x = (width - button_padding_px) / button_count;\n    let max_y = height - 2;\n    let diameter = core::cmp::min(max_x, max_y);\n    let buttons_width = (diameter * button_count) + button_padding_px;\n    let padding_left_px = (width - buttons_width) / 2;\n    let y = (height / 2) - (diameter / 2);\n\n    // Draw the initial button outlines.\n    for i in 0..button_count {\n        let x = padding_left_px + ((diameter + 2) * i);\n\n        let _ = Circle::new(Point::new(x as i32, y as i32), diameter)\n            .into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))\n            .draw(&mut screen);\n    }\n    let _ = screen.flush();\n\n    // Now wait for button presses. Record what happened in the upcall.\n    let buttons: [Cell<ButtonState>; 10] = [const { Cell::new(ButtonState::Released) }; 10];\n    let changed: Cell<bool> = Cell::new(false);\n\n    let listener = ButtonListener(|button, state| {\n        // If the button state changed, record it.\n        if buttons[button as usize].get() != state {\n            buttons[button as usize].set(state);\n            changed.set(true);\n        }\n    });\n    share::scope(|subscribe| {\n        // Subscribe to the button callback.\n        Buttons::register_listener(&listener, subscribe).unwrap();\n\n        // Enable interrupts for each button press.\n        for i in 0..button_count {\n            Buttons::enable_interrupts(i).unwrap();\n        }\n\n        // Wait for buttons to be pressed.\n        loop {\n            TockSyscalls::yield_wait();\n\n            // If a button state changed, re-draw the buttons.\n            if changed.get() {\n                changed.set(false);\n\n                let mut screen = TockMonochrome8BitPage128x64Screen::new();\n\n                // Draw Circles\n                for i in 0..button_count {\n                    let x = padding_left_px + ((diameter + 2) * i);\n\n                    // Draw outer circle\n                    let _ = Circle::new(Point::new(x as i32, y as i32), diameter)\n                        .into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))\n                        .draw(&mut screen);\n\n                    match buttons[i as usize].get() {\n                        ButtonState::Pressed => {\n                            let _ =\n                                Circle::new(Point::new(x as i32 + 1, y as i32 + 1), diameter - 2)\n                                    .into_styled(PrimitiveStyle::with_fill(BinaryColor::On))\n                                    .draw(&mut screen);\n                        }\n                        ButtonState::Released => {\n                            let _ =\n                                Circle::new(Point::new(x as i32 + 1, y as i32 + 1), diameter - 2)\n                                    .into_styled(PrimitiveStyle::with_fill(BinaryColor::Off))\n                                    .draw(&mut screen);\n                        }\n                    }\n                }\n                let _ = screen.flush();\n            }\n        }\n    });\n\n    Ok(())\n}\n\nfn main() {\n    match run() {\n        Ok(()) => {}\n        Err(_e) => {\n            writeln!(Console::writer(), \"[BUTTONS] Err could not run app\").unwrap();\n        }\n    }\n}\n"
  },
  {
    "path": "demos/embedded_graphics/spin/Cargo.toml",
    "content": "[package]\nname = \"spin\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2021\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version = \"1.87\"\ndescription = \"libtock-rs spin app with embedded graphics\"\n\n[dependencies]\nembedded-graphics = \"0.8.1\"\nlibm = \"0.2.15\"\n\nlibtock = { path = \"../../../\", version = \"0.1.0\" }\nembedded_graphics_libtock = { path = \"../../../libraries/embedded_graphics_libtock\", version = \"0.1.0\" }\n\n[build-dependencies]\nlibtock_build_scripts = { path = \"../../../build_scripts\" }\n\n[workspace]\n"
  },
  {
    "path": "demos/embedded_graphics/spin/Makefile",
    "content": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := spin\n\nall: tab\n\ninclude ../../../Targets.mk\n\n$(ELF_TARGETS):\n\tLIBTOCK_LINKER_FLASH=$(F) LIBTOCK_LINKER_RAM=$(R) cargo build --target=$(T) --release\n\t@mkdir -p target/$(A).$(F).$(R)/\n\t@cp target/$(T)/release/$(DEMO) target/$(A).$(F).$(R)/\n\t$(eval ELF_LIST += target/$(A).$(F).$(R)/$(DEMO),$(A).$(F).$(R))\n\n# This target (`make tab`) is not parallel-safe\n.PHONY: tab\ntab: $(ELF_TARGETS)\n\t@mkdir -p target/tab\n\telf2tab --kernel-major 2 --kernel-minor 1 -n $(DEMO) -o target/tab/$(DEMO).tab --stack 1024 --minimum-footer-size 256 $(ELF_LIST)\n"
  },
  {
    "path": "demos/embedded_graphics/spin/README.md",
    "content": "Spin Demo Using Embedded Graphics\n=================================\n\nThis demo spins a line on a screen. It was tested using the SSD1306 screen on\nthe nRF52840dk."
  },
  {
    "path": "demos/embedded_graphics/spin/build.rs",
    "content": "fn main() {\n    libtock_build_scripts::auto_layout();\n}\n"
  },
  {
    "path": "demos/embedded_graphics/spin/src/main.rs",
    "content": "#![no_main]\n#![no_std]\nuse libtock::alarm::Alarm;\nuse libtock::alarm::Milliseconds;\nuse libtock::runtime::{set_main, stack_size};\n\nuse embedded_graphics_libtock::tock_screen::TockMonochrome8BitPage128x64Screen;\n\nuse embedded_graphics::draw_target::DrawTarget;\nuse embedded_graphics::pixelcolor::BinaryColor;\nuse embedded_graphics::prelude::Point;\nuse embedded_graphics::prelude::Primitive;\nuse embedded_graphics::primitives::{Line, PrimitiveStyle};\nuse embedded_graphics::Drawable;\n\nset_main! {main}\nstack_size! {4000}\n\nfn main() {\n    let mut screen = TockMonochrome8BitPage128x64Screen::new();\n\n    let width = screen.get_width() as i32;\n    let height = screen.get_height() as i32;\n\n    let center_x = width / 2;\n    let center_y = height / 2;\n    let radius = if width < height {\n        center_x - 1\n    } else {\n        center_y - 1\n    };\n\n    let mut rot: usize = 0;\n\n    loop {\n        let _ = screen.clear(BinaryColor::Off);\n\n        let angle = (rot as f32 / 100.0) * (2.0 * core::f32::consts::PI);\n\n        let x = (center_x as f32 + (radius as f32 * libm::cosf(angle))) as i32;\n        let y = (center_y as f32 + (radius as f32 * libm::sinf(angle))) as i32;\n\n        let _ = Line::new(Point::new(center_x, center_y), Point::new(x, y))\n            .into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))\n            .draw(&mut screen);\n\n        let _ = screen.flush();\n\n        Alarm::sleep_for(Milliseconds(200)).unwrap();\n\n        rot = (rot + 1) % 100;\n    }\n}\n"
  },
  {
    "path": "demos/st7789/Cargo.toml",
    "content": "[package]\nname = \"st7789\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.87\"\nauthors = [\"Alistair Francis <alistair.francis@wdc.com>\"]\ndescription = \"\"\"A demo to drive a ST7789 display via SPI using libtock-rs.\"\"\"\nlicense = \"Apache-2.0 OR MIT\"\n\n[dependencies]\nlibtock = { path = \"../../\", features = [\"rust_embedded\"] }\n\nembedded-hal = \"1.0\"\n\nmipidsi = \"0.8.0\"\ndisplay-interface-spi = \"0.5\"\nembedded-graphics = \"0.8\"\n\n[build-dependencies]\nlibtock_build_scripts = { path = \"../../build_scripts\" }\n\n[workspace]\n"
  },
  {
    "path": "demos/st7789/Makefile",
    "content": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := st7789\n\nall: tab\n\ninclude ../../Targets.mk\n\n$(ELF_TARGETS):\n\tLIBTOCK_LINKER_FLASH=$(F) LIBTOCK_LINKER_RAM=$(R) cargo build --target=$(T) --release\n\t@mkdir -p target/$(A).$(F).$(R)/\n\t@cp target/$(T)/release/$(DEMO) target/$(A).$(F).$(R)/\n\t$(eval ELF_LIST += target/$(A).$(F).$(R)/$(DEMO),$(A).$(F).$(R))\n\n# This target (`make tab`) is not parallel-safe\n.PHONY: tab\ntab: $(ELF_TARGETS)\n\t@mkdir -p target/tab\n\telf2tab --kernel-major 2 --kernel-minor 1 -n $(DEMO) -o target/tab/$(DEMO).tab --stack 1024 --minimum-footer-size 256 $(ELF_LIST)\n"
  },
  {
    "path": "demos/st7789/build.rs",
    "content": "fn main() {\n    libtock_build_scripts::auto_layout();\n}\n"
  },
  {
    "path": "demos/st7789/src/main.rs",
    "content": "//! This sample demonstrates displaying text on a ST7789 display\n//! using a rust-embedded based crate\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::console::Console;\nuse libtock::gpio::Gpio;\nuse libtock::platform::Syscalls;\nuse libtock::runtime::{set_main, stack_size, TockSyscalls};\nuse libtock::spi_controller::EmbeddedHalSpi;\n\nuse display_interface_spi::SPIInterface;\nuse embedded_graphics::{\n    mono_font::{ascii::FONT_10X20, MonoTextStyle},\n    pixelcolor::Rgb565,\n    prelude::*,\n    text::Text,\n};\nuse mipidsi::{models::ST7789, options::ColorInversion, Builder};\n\nset_main! {main}\nstack_size! {0x1000}\n\n// Display\nconst W: i32 = 240;\nconst H: i32 = 240;\n\nstruct Delay;\n\nimpl embedded_hal::delay::DelayNs for Delay {\n    fn delay_ns(&mut self, ns: u32) {\n        Alarm::sleep_for(Milliseconds(ns / (1000 * 1000))).unwrap();\n    }\n}\n\nfn main() {\n    writeln!(Console::writer(), \"st7789: example\\r\").unwrap();\n\n    let mut gpio_dc = Gpio::get_pin(0).unwrap();\n    let dc = gpio_dc.make_output().unwrap();\n\n    let mut gpio_reset = Gpio::get_pin(1).unwrap();\n    let reset = gpio_reset.make_output().unwrap();\n\n    let di = SPIInterface::new(EmbeddedHalSpi, dc);\n\n    let mut delay = Delay;\n    let mut display = Builder::new(ST7789, di)\n        .display_size(W as u16, H as u16)\n        .invert_colors(ColorInversion::Inverted)\n        .reset_pin(reset)\n        .init(&mut delay)\n        .unwrap();\n\n    // Text\n    let text_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);\n    let text = \"Hello World ^_^;\";\n    let text_x = W;\n    let text_y = H / 2;\n\n    // Clear the display initially\n    display.clear(Rgb565::BLUE).unwrap();\n\n    writeln!(Console::writer(), \"Clear complete\\r\").unwrap();\n\n    // Draw text\n    Text::new(text, Point::new(text_x, text_y), text_style)\n        .draw(&mut display)\n        .unwrap();\n\n    loop {\n        TockSyscalls::yield_wait();\n    }\n}\n"
  },
  {
    "path": "demos/st7789-slint/Cargo.toml",
    "content": "[package]\nname = \"st7789-slint\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.87\"\nauthors = [\"Alistair Francis <alistair.francis@wdc.com>\"]\ndescription = \"\"\"A demo to use the Slint GUI library with a ST7789 display via SPI using libtock-rs.\"\"\"\nlicense = \"Apache-2.0 OR MIT\"\n\n[dependencies]\nlibtock = { path = \"../../\", features = [\"rust_embedded\"] }\n\nembedded-hal = \"1.0\"\n\nmipidsi = \"0.8.0\"\ndisplay-interface-spi = \"0.5\"\nembedded-graphics = \"0.8\"\n\n# The heap allocator and portable atomics\nembedded-alloc = \"0.5.1\"\ncritical-section = \"1.0\"\n\nslint = { git = \"https://github.com/slint-ui/slint\", default-features = false, features = [\"libm\", \"unsafe-single-threaded\"] }\nmcu-board-support = { git = \"https://github.com/slint-ui/slint\" }\n\ndisplay-interface = \"0.5\"\n\n[build-dependencies]\nlibtock_build_scripts = { path = \"../../build_scripts\" }\n\nslint-build = { git = \"https://github.com/slint-ui/slint\" }\n\n[workspace]\nresolver = \"3\"\n"
  },
  {
    "path": "demos/st7789-slint/Makefile",
    "content": "# Makefile for the demo app.\n\n# Crate name of the demo app\nDEMO := st7789-slint\n\nall: tab\n\ninclude ../../Targets.mk\n\n$(ELF_TARGETS):\n\tLIBTOCK_LINKER_FLASH=$(F) LIBTOCK_LINKER_RAM=$(R) cargo build --target=$(T) --release\n\t@mkdir -p target/$(A).$(F).$(R)/\n\t@cp target/$(T)/release/$(DEMO) target/$(A).$(F).$(R)/\n\t$(eval ELF_LIST += target/$(A).$(F).$(R)/$(DEMO),$(A).$(F).$(R))\n\n# This target (`make tab`) is not parallel-safe\n.PHONY: tab\ntab: $(ELF_TARGETS)\n\t@mkdir -p target/tab\n\telf2tab --kernel-major 2 --kernel-minor 1 -n $(DEMO) -o target/tab/$(DEMO).tab --stack 1024 --minimum-footer-size 256 $(ELF_LIST)\n"
  },
  {
    "path": "demos/st7789-slint/build.rs",
    "content": "fn main() {\n    libtock_build_scripts::auto_layout();\n\n    let config = slint_build::CompilerConfiguration::new()\n        .embed_resources(slint_build::EmbedResourcesKind::EmbedForSoftwareRenderer);\n    slint_build::compile_with_config(\"ui/appwindow.slint\", config).unwrap();\n    slint_build::print_rustc_flags().unwrap();\n}\n"
  },
  {
    "path": "demos/st7789-slint/src/main.rs",
    "content": "//! This sample demonstrates displaying a slint GUI on a ST7789 display\n//! using a rust-embedded based crate\n\n#![no_main]\n#![no_std]\n\nextern crate alloc;\n\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::console::Console;\nuse libtock::gpio::Gpio;\nuse libtock::platform::ErrorCode;\nuse libtock::runtime::{set_main, stack_size};\nuse libtock::spi_controller::EmbeddedHalSpi;\n\nuse critical_section::RawRestoreState;\nuse embedded_alloc::Heap;\n\nuse display_interface_spi::SPIInterface;\nuse embedded_hal::digital::OutputPin;\nuse mipidsi::{models::ST7789, options::ColorInversion, Builder, Display};\n\nslint::include_modules!();\n\nset_main! {main}\nstack_size! {0x1400}\n\n#[global_allocator]\nstatic HEAP: Heap = Heap::empty();\n\nstruct MyCriticalSection;\ncritical_section::set_impl!(MyCriticalSection);\n\nunsafe impl critical_section::Impl for MyCriticalSection {\n    unsafe fn acquire() -> RawRestoreState {\n        // Tock is single threaded, so this can only be preempted by interrupts\n        // The kernel won't schedule anything from our app unless we yield\n        // so as long as we don't yield we won't concurrently run with\n        // other critical sections from our app.\n        // The kernel might schedule itself or other applications, but there\n        // is nothing we can do about that.\n    }\n\n    unsafe fn release(_token: RawRestoreState) {}\n}\n\n// Setup the heap and the global allocator.\nunsafe fn setup_heap() {\n    use core::mem::MaybeUninit;\n\n    const HEAP_SIZE: usize = 1024 * 6;\n    static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];\n    unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }\n}\n\n// Display\nconst W: i32 = 240;\nconst H: i32 = 240;\n\nstruct Delay;\n\nimpl embedded_hal::delay::DelayNs for Delay {\n    fn delay_ns(&mut self, ns: u32) {\n        Alarm::sleep_for(Milliseconds(ns / (1000 * 1000))).unwrap();\n    }\n}\n\n#[mcu_board_support::entry]\nfn main() {\n    writeln!(Console::writer(), \"st7789-slint: example\\r\").unwrap();\n\n    unsafe {\n        setup_heap();\n    }\n\n    // Configure platform for Slint\n    let window = slint::platform::software_renderer::MinimalSoftwareWindow::new(\n        slint::platform::software_renderer::RepaintBufferType::ReusedBuffer,\n    );\n\n    window.set_size(slint::PhysicalSize::new(240, 240));\n\n    slint::platform::set_platform(alloc::boxed::Box::new(SlintPlatform {\n        window: window.clone(),\n    }))\n    .unwrap();\n\n    MainWindow::new().unwrap().run().unwrap();\n}\n\nstruct SlintPlatform {\n    window: alloc::rc::Rc<slint::platform::software_renderer::MinimalSoftwareWindow>,\n}\n\nimpl slint::platform::Platform for SlintPlatform {\n    fn create_window_adapter(\n        &self,\n    ) -> Result<alloc::rc::Rc<dyn slint::platform::WindowAdapter>, slint::PlatformError> {\n        Ok(self.window.clone())\n    }\n\n    fn duration_since_start(&self) -> core::time::Duration {\n        core::time::Duration::from_millis(Alarm::get_milliseconds().unwrap())\n    }\n\n    fn debug_log(&self, arguments: core::fmt::Arguments) {\n        writeln!(Console::writer(), \"{arguments}\\r\").unwrap();\n    }\n\n    fn run_event_loop(&self) -> Result<(), slint::PlatformError> {\n        let mut gpio_dc = Gpio::get_pin(0).unwrap();\n        let dc = gpio_dc.make_output().unwrap();\n\n        let mut gpio_reset = Gpio::get_pin(1).unwrap();\n        let reset = gpio_reset.make_output().unwrap();\n\n        let di = SPIInterface::new(EmbeddedHalSpi, dc);\n\n        let mut delay = Delay;\n        let display = Builder::new(ST7789, di)\n            .display_size(W as u16, H as u16)\n            .invert_colors(ColorInversion::Inverted)\n            .reset_pin(reset)\n            .init(&mut delay)\n            .unwrap();\n\n        let mut buffer_provider = DrawBuffer {\n            display,\n            buffer: &mut [slint::platform::software_renderer::Rgb565Pixel(100); 240],\n        };\n\n        writeln!(Console::writer(), \"Setup platform, running loop\\r\").unwrap();\n\n        loop {\n            slint::platform::update_timers_and_animations();\n\n            self.window.draw_if_needed(|renderer| {\n                renderer.render_by_line(&mut buffer_provider);\n            });\n\n            if self.window.has_active_animations() {\n                continue;\n            }\n\n            if let Some(duration) = slint::platform::duration_until_next_timer_update() {\n                Alarm::sleep_for(Milliseconds(duration.as_millis() as u32)).unwrap();\n            }\n        }\n    }\n}\n\nstruct DrawBuffer<'a, Display> {\n    display: Display,\n    buffer: &'a mut [slint::platform::software_renderer::Rgb565Pixel],\n}\n\nimpl<DI: display_interface::WriteOnlyDataCommand, RST: OutputPin<Error = ErrorCode>>\n    slint::platform::software_renderer::LineBufferProvider\n    for &mut DrawBuffer<'_, Display<DI, mipidsi::models::ST7789, RST>>\n{\n    type TargetPixel = slint::platform::software_renderer::Rgb565Pixel;\n\n    fn process_line(\n        &mut self,\n        line: usize,\n        range: core::ops::Range<usize>,\n        render_fn: impl FnOnce(&mut [slint::platform::software_renderer::Rgb565Pixel]),\n    ) {\n        let buffer = &mut self.buffer[range.clone()];\n\n        render_fn(buffer);\n\n        // We send empty data just to get the device in the right window\n        self.display\n            .set_pixels(\n                range.start as u16,\n                line as _,\n                range.end as u16,\n                line as u16,\n                buffer\n                    .iter()\n                    .map(|x| embedded_graphics::pixelcolor::raw::RawU16::new(x.0).into()),\n            )\n            .unwrap();\n    }\n}\n"
  },
  {
    "path": "demos/st7789-slint/ui/appwindow.slint",
    "content": "import {Button, AboutSlint} from \"std-widgets.slint\";\n\nexport component MainWindow inherits Window {\n    width: 240px;\n    height: 240px;\n    VerticalLayout {\n        AboutSlint { }\n    }\n}\n"
  },
  {
    "path": "doc/CargoFeatures.md",
    "content": "Cargo Features\n==============\n\nOn the surface, `cargo`'s\n[features](https://doc.rust-lang.org/cargo/reference/features.html) mechanism\nlooks great for `libtock-rs`. Process binary crates can depend on `libtock-rs`,\nand use `cargo` features to specify which optional `libtock-rs` functionality\nthey want.\n\nHowever, `cargo` assumes that it can compile a crate with features that a binary\ndoes not need. This isn't necessarily true for embedded crates, where process\nbinary authors care about the app size.\n\n## Process Binaries in a Workspace\n\nWhen used with workspaces, `cargo` features can result in excess code being\nbuilt into a repository.\n\nFor example, suppose that `libtock` exposes a `malloc` feature, which adds a\ndynamic memory allocator. Then if a `libtock` user creates a `cargo` workspace\nwith the following process binaries in it:\n\n1. `no_malloc`, which depends on `libtock` and does not depend on the `malloc`\n   feature.\n2. `malloc`, which depends on `libtock` and the `malloc` feature.\n\nWith this setup, `malloc` will always work correctly. Also, if you run `cargo\nbuild -p no_malloc`, then `no_malloc` will correctly build without a memory\nallocation.\n\nSeems optimal, right?\n\nIt's not: if you build the entire workspace with `cargo build --workspace`,\n`libtock` will only be built once, with the `malloc` feature! That will result\nin a `no_malloc` process binary that contains a memory allocator, which is not\nwhat the author desired.\n\n## Alternative to `cargo` Features\n\nIn many cases, `cargo` features can be replaced by splitting a crate up into\nsmaller crates, and letting process binaries choose what to depend on. For\nexample, memory allocation can be in a separate crate that process binaries\ndepend on if and only if they need memory allocation.\n\nHere are some questions to help guide the decision between using a `cargo`\nfeature and separate crates:\n\n1. Do you forsee a single user writing multiple process binaries, some of which\n   use this feature? If yes, then maybe it should not be a `cargo` feature.\n2. Will the compiler optimize the feature away entirely if it is included but\n   unused? If yes, then making it a `cargo` feature is probably fine.\n\nIn many cases, it will make sense to add a `cargo` feature to `libtock` but use\noptional crates to implement the feature internally. This way, users with\nmultiple process binaries in a workspace can choose whether each process binary\ndepends on the optimal crate.\n"
  },
  {
    "path": "doc/CodeReview.md",
    "content": "Code Review\n===========\n\n## Code Review Practices\n\nPR to `libtock-rs` can be divided into two categories:\n\n1. **Upkeep pull requests** are self-contained changes that do not introduce\n   significant code churn, and are unlikely to cause major merge conflicts.\n1. **Significant pull requests** are pull requests that are too substantial to\n   be considered upkeep pull requests. Significant pull requests may represent a\n   significant change in `libtock-rs`'s design or include large refactorings\n   that are likely to cause merge conflicts for other pull requests.\n\nThe owners of `libtock-rs` (listed [below](#owners)) determine whether a PR is\nan upkeep PR or a significant PR. PRs should be merged by the `libtock-rs`\nowners rather than the PR's author. In general, PRs should be merged using a\n`bors r+` command rather than the GitHub UI (see the [bors\ndocumentation](https://bors.tech/documentation/) for more information on bors).\n\nA PR may only be merged when all of the following are true:\n\n1. At least one `libtock-rs` owner (who is not the PR author) has approved the PR.\n1. All outstanding review discussions have been resolved.\n1. If the pull request is significant, a 7 day waiting period has passed since\n   the PR was opened.\n\nWe recommend that authors of significant PRs comment on the PR when they believe\nthe above criteria have been satisfied (including the waiting period). This is\nprimarily to remind the owners to merge the PR. Secondarily, it should help\nidentify confusion about a PR review's status.\n\n## Owners\n\nThe owners of `libtock-rs` are:\n\n* The [Tock Core Working\n  Group](https://github.com/tock/tock/tree/master/doc/wg/core#members).\n* Alistair Francis, [alistair23](https://github.com/alistair23), Western Digital\n"
  },
  {
    "path": "doc/Dependencies.md",
    "content": "Third Party Dependencies\n========================\n\nThis document is about dependencies that are required to build applications\nusing `libtock-rs`. These dependencies are not contained in the libtock-rs\nrepository, but are used by libtock-rs when libtock-rs is used as a dependency\nof an application. Dependencies required to run `libtock-rs`' tests (such as\n`make`) are outside the scope of this document.\n\n## Unaudited Required Dependencies\n\n`libtock-rs` has the following required build dependencies, none of which are\ncurrently audited:\n\n* The Rust toolchain, including\n  [`cargo`](https://github.com/rust-lang/cargo),\n  [`rustc`](https://github.com/rust-lang/rust/tree/master/src/rustc), and\n  [`libcore`](https://github.com/rust-lang/rust/tree/master/src/libcore). The\n  specific toolchain version used is specified by the `rust-toolchain` file at\n  the root of the repository.\n* [`syn`](https://crates.io/crates/syn), pulled in by `libtock_codegen`.\n* [`quote`](https://crates.io/crates/quote), pulled in by `libtock_codegen`.\n* [`proc-macro2`](https://crates.io/crates/proc-macro2), pulled in by\n  `libtock_codegen`.\n\n## Avoiding Optional Dependencies\n\nTo avoid pulling in optional dependencies, users should use `libtock_core`\ninstead of `libtock`. `libtock_core` is in the `core/` directory.\n"
  },
  {
    "path": "doc/DesignConsiderations.md",
    "content": "Design Considerations\n=====================\n\nThis document describes several of the factors that constrain the design of\n`libtock_core`.\n\n## Size impact\n\nTock is designed to run on hardware with limited program storage and limited\nRAM. On Google's H1 chip, the Tock kernel and apps are limited to a 256 KiB\nflash region. The HiFive1 Rev B board has only 16 KiB of RAM.\n\nNote that a Tock system may have multiple process binaries, each of which uses\n`libtock_core`, so `libtock_core` must minimize its size impact to the extent\npossible.\n\nA process binary is generally stored in non-volatile memory and contains:\n\n  * Runtime headers (the `.crt0_header` section)\n  * Executable code (the `.text` section)\n  * Read-only data (the `.rodata` section)\n  * Non-zero-initialized read-write data (the `.data` section)\n\nA process' memory section is in RAM and contains:\n\n  * Heap memory (if a dynamic memory allocator is present)\n  * Zero-initialized read-write data (the `.bss` section)\n  * Non-zero-initialized read-write data (the `.data` section)\n  * Stack memory\n\n`libtock_core` developers should consider the space usage of their code, and\nwhere the space usage is (non-volatile memory or RAM). Important note: the\n`.data` section consumes space in both non-volatile memory and RAM!\n\nMost apps will not use all functionality in `libtock_core`. The size impact of\nusing `libtock_core` in an app should be commensurate with the `libtock_core`\nfunctionality that app uses. If done correctly, this will allow `libtock_core`'s\nusers to build Tock systems with multiple small, single-purpose apps without\nexcessive code duplication.\n\n## Testability\n\nProgrammatic tests are important to verify that new functionality works\ncorrectly and to keep existing functionality working through nontrivial\nrefactorings. Different types of tests offer different capabilities:\n\n  * **Host-based unit tests** run on a non-Tock host OS (such as Linux). They\n    can only be used with portable `libtock_core` code, as the code they test\n    must run on both Tock and the host OS. These tests must either test code\n    that does not directly use system calls, or must direct the system calls to\n    a fake Tock kernel. These tests can be fast (compile and run in seconds),\n    and can easily simulate a variety of failure modes (e.g. kernel errors) that\n    may be difficult to generate with a real Tock kernel.\n  * **Emulation tests** run on an emulated Tock system. Currently, emulation\n    tests run in QEMU on an emulated HiFive1 Rev B board. These test\n    `libtock_core`'s interaction with a real Tock kernel, albeit with limited\n    hardware access.\n  * **Hardware tests** run on physical hardware with a real Tock kernel. These\n    are end-to-end tests that test not only `libtock_core`'s functionality but\n    also the Tock kernel's interaction with the real hardware. However,\n    automating these tests is difficult, and currently we do not have a way to\n    run hardware tests in CI.\n\nIf `libtock_core` is functional on real hardware with a real kernel, it should\nbe able to support emulation tests and hardware tests. However, host-based unit\ntests require more work. In its intended use case, `libtock_core` is not\nsupposed to be portable, supporting only the Tock kernel. Hoever, host-based\nunit tests are very valuable, both for rapid development and for testing error\nhandling code. To support host-based tests, `libtock_core` must be built out of\nportable pieces that can be unit tested, even though the library as a whole is\nnot portable.\n\nTesting pieces of `libtock_core` against a fake kernel can be done using\ndependency injection, but most dependency injection techniques have considerable\ncode size and RAM usage costs. `libtock_core` needs either a dependency\ninjection technique that has minimal size impact or an alternative mechanism for\ntesting `libtock_core`'s system call error handling logic.\n\n## Support multiple asynchronous programming models.\n\nThe general Rust ecosystem has converged on futures as its building block for\ninteroperable asynchronous APIs, but futures have a [size\ncost](https://github.com/tock/design-explorations/tree/master/size_comparison)\nthat makes them impractical for some use cases of `libtock_core`. Although\n`libtock_core` is still a work in progress (see [issue\n217](https://github.com/tock/libtock-rs/issues/217)), it will probably use an\nasynchronous API design based on the [Asynchronous Components using Zero Sized\nType\nPointers](https://github.com/tock/design-explorations/tree/master/zst_pointer_async)\nexploration.\n\nIn order to interoperate with other libraries as well as the `async`/`await`\nfunctionality built in to Rust, we need `libtock_core` to interface well with\nfutures. In addition, there are several use cases of `libtock_core` that consist\nprimarily of synchronous code, so we need to be able to use `libtock_core`'s\nAPIs in a synchronous manner.\n\nThe `libtock-c` developers are already familiar with some of the complications\nthat come up when synchronous code is interfaced to asynchronous code. For\nexample, calling `printf` -- an extremely common debugging tool -- causes\ncallbacks to run in the background. This causes surprising and hard-to-debug\nreentrancy issues.\n\n## Dependency tree minimization\n\nSome of users of `libtock_core` intend to use it in applications that will\nundergo code audits for security certifications. To make this auditing\npractical, it is important to allow users to use `libtock_core` without pulling\nin a large dependency tree.\n\nAs a general rule, a `libtock_core` should avoid having required dependencies\nunless those dependencies are minimal (that is, avoiding the dependency would\nrequire reimplementing nearly all of it). Dependencies included in the Rust\ntoolchain (such as the `core` crate and its dependencies) are an exception, as\nthey are a part of the language itself.\n\n## No hard `alloc` dependency\n\nIt should be possible to use `libtock_core` without bringing in the `alloc`. Of\ncourse, it is fine for `libtock_core` to offer a memory allocator as an optional\nfeature.\n"
  },
  {
    "path": "doc/FaultDebuggingExample.md",
    "content": "Fault Debugging Example\n=======================\n\nThis document shows the debugging process I (@jrvanwhy) used to find the cause\nof an illegal instruction error. I wrote this document because the debugging\nprocess demonstrates the use of valuable debugging tools (such as `objdump`) as\nwell as the thought process I use to debug low-level issues.\n\n## The failure\n\nWhen I attempt to run the `low_level_debug` example, I get the following app\nfault (note: the early debug messages are from a work-in-progress PR, but should\nbe self-explanatory):\n\n```\nPackage name: \"low_level_debug\"\nTAB path: target/riscv32imac-unknown-none-elf/release/examples/low_level_debug.tab\nProtected region size: 72\nFound .stack section, size: 256\nELF file: \"target/riscv32imac-unknown-none-elf/release/examples/low_level_debug\"\nTBF path: target/riscv32imac-unknown-none-elf/release/examples/low_level_debug.tbf\nelf2tab command: \"elf2tab\" \"-n\" \"low_level_debug\" \"-o\" \"target/riscv32imac-unknown-none-elf/release/examples/low_level_debug.tab\" \"--protected-region-size\" \"72\" \"--stack\" \"256\" \"target/riscv32imac-unknown-none-elf/release/examples/low_level_debug\" \"-v\"\nSpawning elf2tab\nCreating \"target/riscv32imac-unknown-none-elf/release/examples/low_level_debug.tbf\"\nMin RAM size from segments in ELF: 0 bytes\nNumber of writeable flash regions: 0\nEntry point is in .start section\n  Adding .start section. Offset: 72 (0x48). Length: 118 (0x76) bytes.\n  Adding .text section. Offset: 190 (0xbe). Length: 64 (0x40) bytes.\nWarning! Placing section .text at 0xbe, which is not 4-byte aligned.\nSearching for .rel.X sections to add.\nTBF Header:\n               version:        2        0x2\n           header_size:       64       0x40\n            total_size:      512      0x200\n                 flags:        1        0x1\n\n        init_fn_offset:       40       0x28\n        protected_size:        8        0x8\n      minimum_ram_size:     2304      0x900\n\n     start_process_ram: 2147493888 0x80002800\n   start_process_flash: 537133128 0x20040048\n\nelf2tab finished. exit status: 0\nQEMU command: \"tock2/tools/qemu/build/qemu-system-riscv32\" \"-M\" \"sifive_e,revb=true\" \"-kernel\" \"tock2/target/riscv32imac-unknown-none-elf/release/hifive1\" \"-nographic\" \"-device\" \"loader,file=target/riscv32imac-unknown-none-elf/release/examples/low_level_debug.tbf,addr=0x20040000\"\nSpawning QEMU\nHiFive1 initialization complete.\nEntering main loop.\n\npanicked at 'Process low_level_debug had a fault', kernel/src/process.rs:1037:17\n        Kernel version release-1.6-954-g17e698e8f\n\n---| No debug queue found. You can set it with the DebugQueue component.\n\n---| RISC-V Machine State |---\nLast cause (mcause): Illegal instruction (interrupt=0, exception code=0x00000002)\nLast value (mtval):  0x00000000\n\nSystem register dump:\n mepc:    0x20012948    mstatus:     0x00000088\n mcycle:  0xFF33A41C    minstret:    0xFF33CBEA\n mtvec:   0x20010100\n mstatus: 0x00000088\n  uie:    false  upie:   false\n  sie:    false  spie:   false\n  mie:    true   mpie:   true\n  spp:    false\n mie:   0x00000888   mip:   0x00000000\n  usoft:  false               false \n  ssoft:  false               false \n  msoft:  true                false \n  utimer: false               false \n  stimer: false               false \n  mtimer: true                false \n  uext:   false               false \n  sext:   false               false \n  mext:   true                false \n\n---| App Status |---\nApp: low_level_debug   -   [Faulted]\n Events Queued: 0   Syscall Count: 1   Dropped Callback Count: 0\n Restart Count: 0\n Last Syscall: Some(Memop { operand: 0, arg0: 2147494144 })\n\n\n ╔═══════════╤══════════════════════════════════════════╗\n ║  Address  │ Region Name    Used | Allocated (bytes)  ║\n ╚0x800037C0═╪══════════════════════════════════════════╝\n             │ ▼ Grant         960 |    960          \n  0x80003400 ┼───────────────────────────────────────────\n             │ Unused\n  0x80002900 ┼───────────────────────────────────────────\n             │ ▲ Heap            ? |      ?               S\n  ?????????? ┼─────────────────────────────────────────── R\n             │ Data              ? |      ?               A\n  ?????????? ┼─────────────────────────────────────────── M\n             │ ▼ Stack           ? |      ?\n  0x80002900 ┼───────────────────────────────────────────\n             │ Unused\n  0x80002800 ┴───────────────────────────────────────────\n             .....\n  0x20040200 ┬─────────────────────────────────────────── F\n             │ App Flash       440                        L\n  0x20040048 ┼─────────────────────────────────────────── A\n             │ Protected        72                        S\n  0x20040000 ┴─────────────────────────────────────────── H\n\n R0 : 0x00000000    R16: 0x00000000\n R1 : 0x200400BE    R17: 0x00000000\n R2 : 0x80002900    R18: 0x00000000\n R3 : 0x00000000    R19: 0x00000000\n R4 : 0x00000000    R20: 0x00000000\n R5 : 0x00000000    R21: 0x00000000\n R6 : 0x00000000    R22: 0x00000000\n R7 : 0x00000000    R23: 0x00000000\n R8 : 0x20040068    R24: 0x00000000\n R9 : 0x20040068    R25: 0x00000000\n R10: 0x00000000    R26: 0x00000000\n R11: 0x80002900    R27: 0x00000000\n R12: 0x00000FC0    R28: 0x00000000\n R13: 0x80003400    R29: 0x00000000\n R14: 0x00000005    R30: 0x00000000\n R15: 0x20040048    R31: 0x00000000\n PC : 0x200400F6    SP : 0x80002900\n\n mcause: 0x00000002 (Illegal instruction)\n mtval:  0x00000000\n\n PMP regions:\n  [0]: addr=0x20040000, size=0x00000200, cfg=0xD (r-x)\n  [1]: addr=0x80002800, size=0x00000100, cfg=0xB (rw-)\n  <unset>\n  <unset>\n\nTo debug, run `make lst` in the app's folder\nand open the arch.0x20040048.0x80002800.lst file.\n```\n\n## Debugging process\n\nWhen I see an illegal instruction error, my first thought is \"did the code just\njump to an address that is not code?\". The kernel's output indicates that `pc`\nis `0x200400F6`. To see if `0x200400F6` is code, we disassemble the binary:\n\n```\njrvanwhy@penguin:~/libtock-rs$ riscv64-unknown-elf-objdump -d -j .start -j .text target/riscv32imac-unknown-none-elf/release/examples/low_level_debug\n\ntarget/riscv32imac-unknown-none-elf/release/examples/low_level_debug:     file format elf32-littleriscv\n\n\nDisassembly of section .start:\n\n20040048 <rt_header>:\n20040048:       0068                    addi    a0,sp,12\n2004004a:       2004                    fld     fs1,0(s0)\n2004004c:       2900                    fld     fs0,16(a0)\n2004004e:       8000                    0x8000\n20040050:       2900                    fld     fs0,16(a0)\n20040052:       8000                    0x8000\n20040054:       0000                    unimp\n20040056:       0000                    unimp\n20040058:       2900                    fld     fs0,16(a0)\n2004005a:       8000                    0x8000\n2004005c:       2900                    fld     fs0,16(a0)\n2004005e:       8000                    0x8000\n20040060:       0000                    unimp\n20040062:       0000                    unimp\n20040064:       2900                    fld     fs0,16(a0)\n20040066:       8000                    0x8000\n\n20040068 <start>:\n20040068:       00000417                auipc   s0,0x0\n2004006c:       87aa                    mv      a5,a0\n2004006e:       4384                    lw      s1,0(a5)\n20040070:       00940c63                beq     s0,s1,20040088 <start+0x20>\n20040074:       4521                    li      a0,8\n20040076:       4585                    li      a1,1\n20040078:       4609                    li      a2,2\n2004007a:       4709                    li      a4,2\n2004007c:       00000073                ecall\n20040080:       4501                    li      a0,0\n20040082:       4719                    li      a4,6\n20040084:       00000073                ecall\n20040088:       4501                    li      a0,0\n2004008a:       43cc                    lw      a1,4(a5)\n2004008c:       4715                    li      a4,5\n2004008e:       00000073                ecall\n20040092:       0087a103                lw      sp,8(a5)\n20040096:       47c8                    lw      a0,12(a5)\n20040098:       c909                    beqz    a0,200400aa <start+0x42>\n2004009a:       4b8c                    lw      a1,16(a5)\n2004009c:       4bd0                    lw      a2,20(a5)\n2004009e:       4194                    lw      a3,0(a1)\n200400a0:       c214                    sw      a3,0(a2)\n200400a2:       1571                    addi    a0,a0,-4\n200400a4:       0591                    addi    a1,a1,4\n200400a6:       0611                    addi    a2,a2,4\n200400a8:       f97d                    bnez    a0,2004009e <start+0x36>\n200400aa:       4f88                    lw      a0,24(a5)\n200400ac:       c519                    beqz    a0,200400ba <start+0x52>\n200400ae:       4fcc                    lw      a1,28(a5)\n200400b0:       00058023                sb      zero,0(a1)\n200400b4:       157d                    addi    a0,a0,-1\n200400b6:       0585                    addi    a1,a1,1\n200400b8:       fd65                    bnez    a0,200400b0 <start+0x48>\n200400ba:       03c000ef                jal     ra,200400f6 <rust_start>\n\nDisassembly of section .text:\n\n200400c0 <_ZN15low_level_debug4main17h52d4e61b1cb7ceefE>:\n200400c0:       4709                    li      a4,2\n200400c2:       4521                    li      a0,8\n200400c4:       4605                    li      a2,1\n200400c6:       4589                    li      a1,2\n200400c8:       4681                    li      a3,0\n200400ca:       00000073                ecall\n200400ce:       4709                    li      a4,2\n200400d0:       468d                    li      a3,3\n200400d2:       4521                    li      a0,8\n200400d4:       4609                    li      a2,2\n200400d6:       458d                    li      a1,3\n200400d8:       00000073                ecall\n200400dc:       8082                    ret\n\n200400de <libtock_unsafe_main>:\n200400de:       1141                    addi    sp,sp,-16\n200400e0:       c606                    sw      ra,12(sp)\n200400e2:       00000097                auipc   ra,0x0\n200400e6:       fde080e7                jalr    -34(ra) # 200400c0 <_ZN15low_level_debug4main17h52d4e61b1cb7ceefE>\n200400ea:       4719                    li      a4,6\n200400ec:       4501                    li      a0,0\n200400ee:       4581                    li      a1,0\n200400f0:       00000073                ecall\n        ...\n\n200400f6 <rust_start>:\n200400f6:       00000097                auipc   ra,0x0\n200400fa:       fe8080e7                jalr    -24(ra) # 200400de <libtock_unsafe_main>\n        ...\n```\n\nIn the ELF file, `0x200400f6` is the beginning of a valid instruction. So maybe\nsomething is going wrong in the ELF to TBF conversion, or in the deployment?\n\n## Address checking\n\nThe [RISC-V entry\npoint](https://github.com/tock/libtock-rs/blob/b0f8593c1c5dc2a4ded1305809841202107d7c75/runtime/asm/asm_riscv32.S)\nhas logic to verify the program counter is incorrect. If that logic executed,\nthen we know the TBF file was deployed to the correct location in flash. But how\ndo we know it executed, rather than the kernel trying to start execution at\n`0x200400f6` immediately?\n\nWe can see some evidence of that in the kernel's output:\n\n```\nLast Syscall: Some(Memop { operand: 0, arg0: 2147494144 })\n```\n\nThe only place that Memop calls occur in `low_level_debug` is in `asm_riscv32.S`:\n\n```\n.section .start, \"ax\"\n.globl start\nstart:\n    /* First, verify the process binary was loaded at the correct address. The\n     * check is performed by comparing the program counter at the start to the\n     * address of `start`, which is stored in rt_header. */\n    auipc s0, 0            /* s0 = pc */\n    mv a5, a0              /* Save rt_header so syscalls don't overwrite it */\n    lw s1, 0(a5)           /* s1 = rt_header.start */\n    beq s0, s1, .Lset_brk  /* Skip error handling code if pc is correct */\n    /* If the beq on the previous line did not jump, then the binary is not at\n     * the correct location. Report the error via LowLevelDebug then exit. */\n    li a0, 8  /* LowLevelDebug driver number */\n    li a1, 1  /* Command: Print alert code */\n    li a2, 2  /* Alert code 2 (incorrect location) */\n    li a4, 2  /* `command` class */\n    ecall\n    li a0, 0  /* exit-terminate */\n    /* TODO: Set a completion code, once completion codes are decided */\n    li a4, 6  /* `exit` class */\n    ecall\n\n.Lset_brk:\n    /* memop(): set brk to rt_header's initial break value */\n    li a0, 0      /* operation: set break */\n    lw a1, 4(a5)  /* rt_header's initial process break */\n    li a4, 5      /* `memop` class */\n    ecall\n```\n\nNotably, the initial process break is loaded from `4(a5)`, and `a5` is set\n*before* the `pc` check runs. So if the memory break is correct, then we can be\nfairly confident the `pc` check ran. `2147494144` is `0x80002900`, which is 256\nbytes past the beginning of the process binary's flash region (from\n`runtime/layouts/hifive1.ld`):\n\n```\nMEMORY {\n  /* Note that the SRAM address may need to be changed depending on\n   * the kernel binary, check for the actual address of APP_MEMORY!\n   */\n  FLASH (X) : ORIGIN = 0x20040000, LENGTH = 32M\n  RAM   (W) : ORIGIN = 0x80002800, LENGTH = 0x1800\n}\n```\n\nThat seems completely reasonable. Next, I suspect an issue in the ELF -> TBF\nconversion.\n\n## Decoding the TBF file\n\nThis is the point where the tiny size of `low_level_debug` becomes hugely\nbeneficial. We hexdump the entirety of the TBF file:\n\n```\njrvanwhy@penguin:~/libtock-rs$ hexdump -C target/riscv32imac-unknown-none-elf/release/examples/low_level_debug.tbf | tee ~/decoded_tbf\n00000000  02 00 40 00 00 02 00 00  01 00 00 00 62 03 4d ff  |..@.........b.M.|\n00000010  01 00 0c 00 28 00 00 00  08 00 00 00 00 09 00 00  |....(...........|\n00000020  03 00 0f 00 6c 6f 77 5f  6c 65 76 65 6c 5f 64 65  |....low_level_de|\n00000030  62 75 67 00 05 00 08 00  00 28 00 80 48 00 04 20  |bug......(..H.. |\n00000040  00 00 00 00 00 00 00 00  68 00 04 20 00 29 00 80  |........h.. .)..|\n00000050  00 29 00 80 00 00 00 00  00 29 00 80 00 29 00 80  |.).......)...)..|\n00000060  00 00 00 00 00 29 00 80  17 04 00 00 aa 87 84 43  |.....).........C|\n00000070  63 0c 94 00 21 45 85 45  09 46 09 47 73 00 00 00  |c...!E.E.F.Gs...|\n00000080  01 45 19 47 73 00 00 00  01 45 cc 43 15 47 73 00  |.E.Gs....E.C.Gs.|\n00000090  00 00 03 a1 87 00 c8 47  09 c9 8c 4b d0 4b 94 41  |.......G...K.K.A|\n000000a0  14 c2 71 15 91 05 11 06  7d f9 88 4f 19 c5 cc 4f  |..q.....}..O...O|\n000000b0  23 80 05 00 7d 15 85 05  65 fd ef 00 c0 03 09 47  |#...}...e......G|\n000000c0  21 45 05 46 89 45 81 46  73 00 00 00 09 47 8d 46  |!E.F.E.Fs....G.F|\n000000d0  21 45 09 46 8d 45 73 00  00 00 82 80 41 11 06 c6  |!E.F.Es.....A...|\n000000e0  97 00 00 00 e7 80 e0 fd  19 47 01 45 81 45 73 00  |.........G.E.Es.|\n000000f0  00 00 00 00 97 00 00 00  e7 80 80 fe 00 00 00 00  |................|\n00000100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n*\n00000200\n```\n\nI then use a text editor to remove the last two lines (which represent padding\nspace), and change the high bits of the addresses to match the addresses the TBF\nfile is deployed to:\n\n```\n20040000  02 00 40 00 00 02 00 00  01 00 00 00 62 03 4d ff  |..@.........b.M.|\n20040010  01 00 0c 00 28 00 00 00  08 00 00 00 00 09 00 00  |....(...........|\n20040020  03 00 0f 00 6c 6f 77 5f  6c 65 76 65 6c 5f 64 65  |....low_level_de|\n20040030  62 75 67 00 05 00 08 00  00 28 00 80 48 00 04 20  |bug......(..H.. |\n20040040  00 00 00 00 00 00 00 00  68 00 04 20 00 29 00 80  |........h.. .)..|\n20040050  00 29 00 80 00 00 00 00  00 29 00 80 00 29 00 80  |.).......)...)..|\n20040060  00 00 00 00 00 29 00 80  17 04 00 00 aa 87 84 43  |.....).........C|\n20040070  63 0c 94 00 21 45 85 45  09 46 09 47 73 00 00 00  |c...!E.E.F.Gs...|\n20040080  01 45 19 47 73 00 00 00  01 45 cc 43 15 47 73 00  |.E.Gs....E.C.Gs.|\n20040090  00 00 03 a1 87 00 c8 47  09 c9 8c 4b d0 4b 94 41  |.......G...K.K.A|\n200400a0  14 c2 71 15 91 05 11 06  7d f9 88 4f 19 c5 cc 4f  |..q.....}..O...O|\n200400b0  23 80 05 00 7d 15 85 05  65 fd ef 00 c0 03 09 47  |#...}...e......G|\n200400c0  21 45 05 46 89 45 81 46  73 00 00 00 09 47 8d 46  |!E.F.E.Fs....G.F|\n200400d0  21 45 09 46 8d 45 73 00  00 00 82 80 41 11 06 c6  |!E.F.Es.....A...|\n200400e0  97 00 00 00 e7 80 e0 fd  19 47 01 45 81 45 73 00  |.........G.E.Es.|\n200400f0  00 00 00 00 97 00 00 00  e7 80 80 fe 00 00 00 00  |................|\n20040100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|\n```\n\nAt this point, I start going through the TBF file byte-by-byte, using the [TBF\ndocumentation](https://github.com/tock/tock/blob/master/doc/TockBinaryFormat.md)\nto decode it and add notes describing what each byte means. Once I make it past\nthe headers, I also compare the bytes against the disassembly, looking for a\ndifference. Eventually, I find one:\n\n```\nTBF headers:\n20040000  02 00 40 00 00 02 00 00                          Version 2, header len 64, TBF len 512\n20040008  01 00 00 00 62 03 4d ff                          Process enabled, checksum\n20040010  01 00 0c 00 28 00 00 00                          Main element, Data len 12, _start offset 0x28\n20040018  08 00 00 00 00 09 00 00                          Protected size 8, Minimum RAM size 2304\n20040020  03 00 0f 00                                      Package name, len 15\n20040024  6c 6f 77 5f 6c 65 76 65 6c 5f 64 65 62 75 67 00  \"low_level_debug\", padding\n20040034  05 00 08 00 00 28 00 80 48 00 04 20              Fixed addrs, Len 8, RAM 0x80002800, Flash 0x20040048\n20040040  00 00 00 00 00 00 00 00                          Post-header padding\n\nrt_header:\n20040048  68 00 04 20 00 29 00 80 00 29 00 80 00 00 00 00  rt_header (first 16 bytes)\n20040058  00 29 00 80 00 29 00 80 00 00 00 00 00 29 00 80  rt_header (second 16 bytes)\n\nstart:\n20040068  17 04 00 00 aa 87 84 43\n20040070  63 0c 94 00 21 45 85 45  09 46 09 47 73 00 00 00\n20040080  01 45 19 47 73 00 00 00  01 45 cc 43 15 47 73 00\n20040090  00 00 03 a1 87 00 c8 47  09 c9 8c 4b d0 4b 94 41\n200400a0  14 c2 71 15 91 05 11 06  7d f9 88 4f 19 c5 cc 4f\n200400b0  23 80 05 00 7d 15 85 05  65 fd ef 00 c0 03\n\n.text (misplaced!):\n200400be  09 47\n200400c0  21 45 05 46 89 45 81 46  73 00 00 00 09 47 8d 46\n200400d0  21 45 09 46 8d 45 73 00  00 00 82 80 41 11 06 c6\n200400e0  97 00 00 00 e7 80 e0 fd  19 47 01 45 81 45 73 00\n200400f0  00 00 00 00 97 00 00 00  e7 80 80 fe 00 00 00 00\n20040100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040160  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n20040190  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n200401a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n200401b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n200401c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n200401d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n200401e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n200401f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00\n```\n\n`.text` in the TBF starts at `0x200400be`, but in the ELF file it starts at\n`0x200400c0`! There should be 2 more bytes of padding between `.start` and\n`.text`, so that `.text` is located at a multiple of 4 bytes.\n\n## The fix\n\nIt turns out this is a known issue in `elf2tab`, and was fixed in\nhttps://github.com/tock/elf2tab/pull/35. I resolved the fault by updating\n`elf2tab`.\n"
  },
  {
    "path": "doc/MiriTips.md",
    "content": "Miri Tips\n=========\n\n`libtock-rs` runs most of its unit tests under\n[Miri](https://github.com/rust-lang/miri) to detect undefined behavior. However,\nMiri does not detect all undefined behavior encountered. This document lists\ntechniques for maximizing the amount of undefined behavior identified by Miri.\n\n## Miri flags\n\nMiri has [configuration\nflags](https://github.com/rust-lang/miri#miri--z-flags-and-environment-variables),\nwhich can be set using the `MIRIFLAGS` environment variable. We run the tests\nboth with and without `-Zmiri-track-raw-pointers`, as both versions of Stacked\nBorrows has undefined behavior the other does not (see [this\ndiscussion](https://github.com/rust-lang/miri/pull/1748) for more information).\nOn the run with `-Zmiri-track-raw-pointers`, we also set\n`-Zmiri-symbolic-alignment-check` to make Miri's alignment check more pendantic.\n\n## Detecting invalid values\n\nMiri does not always detect undefined behavior when an invalid value is created\nbut not used. Here are some cases that Miri currently accepts:\n\n1. Unused reference to an invalid value\n   (https://github.com/rust-lang/miri/issues/1638)\n1. Unused uninitialized value (https://github.com/rust-lang/miri/issues/1340)\n1. Slices pointing to invalid values\n   (https://github.com/rust-lang/miri/issues/1240)\n\nNote that copying the value around (including passing it to functions) does\n*not* count as a use for the purpose of this check.\n\nFor types that implement `core::fmt::Debug` (i.e. most types), you can check a\nvalue is valid by attempting to debug-print it:\n\n```rust\nformat!(\"{:?}\", value);\n```\n\nIf `value` is invalid, then Miri will identify undefined behavior in the above\ncode.\n"
  },
  {
    "path": "doc/Overview.md",
    "content": "Overview\n======\n\nThis document gives an overview of the crates in this repository, and is\nintended to be useful to `libtock-rs` newcomers.\n\n## `libtock`\n\n`libtock` provides the default `libtock-rs` experience. It re-exports all of the\ndrivers `libtock-rs` provides, and provides usable defaults for panic handling\nand memory allocation. It should be easy to build a Tock application that only\nhas one direct dependency: `libtock`.\n\nIn order to be easy to use, `libtock` has a hard dependency on\n`libtock_runtime`, and therefore cannot be used in a unit test environment. If\nyou want to unit test code that uses `libtock-rs`, you should depend on the\nindividual libraries rather than `libtock`.\n\n## Naming convention note\n\nAlthough these crates have yet to be uploaded to crates.io, they likely will be\nuploaded in the future. Therefore, to avoid name collisions, most crates in this\nrepository have a name that begins with `libtock`. Crates that are only intended\nfor internal use (e.g. `syscall_tests`, which tests code internal to\n`libtock_platform`) do not have the `libtock_` prefix.\n\nThe directory names of `libtock_` crates do not contain the `libtock_` prefix.\n\n## Core abstractions: `libtock_platform`\n\nIn order to unit test `libtock-rs` code, we need a way to run `libtock-rs` on\nour development machines (and in CI). Ironically, that means most crates in\n`libtock-rs` are platform independent. `libtock_platform` provides the tools\nthat allow code to run in both a unit test environment and in real Tock apps. It\nconsists primarily of the `Syscalls` trait and supporting machinery.\n\n## Syscall implementations: `libtock_runtime` and `libtock_unittest`\n\nIn order to run `libtock-rs` code, you need a `libtock_platform::Syscalls`\nimplementation. Multiple implementations exist that work in different\nenvironments:\n\n* `libtock_runtime` provides a syscall interface that uses a real Tock kernel.\n  This is the crate to use in Tock process binaries.\n* `libtock_unittest` provides a fake kernel for use in unit tests.\n\nIn addition, `libtock_runtime` provides the linker script and Rust runtime\nneeded to start a Tock process binary. `libtock_unittest` relies on `std` to\nprovide a runtime.\n\n## Panic handler crates\n\nEach Rust binary must have exactly one panic handler (note that `std` provides a\npanic handler for binaries that depend on it). The following crates provide a\n`#[panic_handler]` implementation for Tock process binaries:\n\n* `libtock_panic_debug` provides useful diagnostics in the event of a panic, at\n  the expense of code size. This is the panic handler used by `libtock`.\n\n## Driver crates\n\nDriver crates provide interfaces to specific Tock APIs in the `/apis` directory.\n"
  },
  {
    "path": "doc/PlatformDesignStory.md",
    "content": "`libtock_platform` Design Story\n===============================\n\n`libtock_platform` is a crate that will contain core abstractions that will be\nused by `libtock_core`'s drivers. For example, it will contain abstractions for\nasynchronous APIs that are lighter weight (in terms of code size and RAM usage)\nthan Rust's futures.\n\nThis document serves as a justification for, and explanation of, the high-level\ndesign of `libtock_platform`. Instead of describing the various components and\nhow they interact, it starts with a hello world application and extracts some of\nthe functionality out into a reusable library. As we do so, we see that\n`libtock_core`'s [design considerations](DesignConsiderations.md) lead\nincrementally to a design for `libtock_platform`.\n\nIn order to keep things understandable, this document makes several\nsimplifications. Error handling logic is omitted, although we still structure\nthe code so as to allow it. We use `unsafe` in places where we should instead\nhave an additional, safe, abstraction. We use a simplified form of the Tock 2.0\nsystem calls, which are currently undergoing design revisions.\n\n## Hello World\n\nWe start with the following example app. In order to show how `libtock_platform`\nwill handle asynchronous callbacks, it is written in an asynchronous manner.\n\n```rust\n#![no_std]\n\nstatic GREETING: [u8; 7] = *b\"Hello, \";\nstatic NOUN: [u8; 7] = *b\"World!\\n\";\nstatic mut DONE: bool = false;\n\n// Driver, command, allow, and subscription numbers.\nconst DRIVER: usize = 1;\nconst WRITE_DONE: usize = 1;\nconst WRITE_BUFFER: usize = 1;\nconst START_WRITE: usize = 1;\n\nfn main() {\n    libtock_runtime::subscribe(DRIVER, WRITE_DONE, write_complete, 0);\n    libtock_runtime::const_allow(DRIVER, WRITE_BUFFER, &GREETING);\n    libtock_runtime::command(DRIVER, START_WRITE, GREETING.len(), 0);\n    loop {\n        libtock_runtime::yieldk();\n    }\n}\n\nextern \"C\" fn write_complete(bytes: usize, _: usize, _: usize, _data: usize) {\n    // Detect if this write completion is a result of writing NOUN (the\n    // second write). If so, return immediately to avoid an infinite loop.\n    unsafe {\n        if DONE { return; }\n        DONE = true;\n    }\n    // At this point, we just finished writing GREETING and need to write NOUN.\n    libtock_runtime::const_allow(DRIVER, WRITE_BUFFER, &NOUN);\n    libtock_runtime::command(DRIVER, START_WRITE, NOUN.len(), 0);\n}\n```\n\nStrictly speaking, in this app, `DONE` could be tracked by passing it as the\n`data` argument to `subscribe`. However, most applications will need to track\nmore than 32 bits of persistent state -- and use more than one callback -- so\nthey will need to manage persistent state themselves. To make this app\nrepresentative of most apps, we keep the state in userspace memory.\n\nThis example assumes that the `libtock_runtime` crate exposes system call\nimplementations that look like the following (these are a simplification of the\nTock 2.0 system calls):\n\n```rust\npub fn subscribe(driver_num: usize,\n                 subscription_num: usize,\n                 callback: extern \"C\" fn(usize, usize, usize, usize),\n                 data: usize);\n\npub fn const_allow(driver_num: usize, buffer_num: usize, buffer: &'static [u8]);\npub fn command(driver_num: usize, command_num: usize, arg1: usize, arg2: usize);\npub fn yieldk();\n```\n\nWhat do we already get \"right\" in this example? Except for the two intentional\ninefficiencies explained above (performing the write in two steps rather than 1\nand maintaining the `DONE` state in process memory), it is very efficient. It\nhas only 3 global variables: `GREETING`, `NOUN`, and `DONE`. It has almost zero\nbookkeeping overhead; it fairly directly makes 8 system calls (`subscribe`,\n`const_allow`, `command`, `yieldk`, `const_allow`, `command`, `yieldk`,\n`yieldk`).\n\nWhat do we want to improve? It calls system calls directly from application code\n-- there should be a reusable `console` library that implements the system calls\ninstead! The application shouldn't need to know what command number starts a\nwrite, it should just tell the console driver to do that for it.\n\n## Adding a Console Library\n\nLet's start taking some of the console-specific parts and moving them into a new\ncrate. The first system call the app makes is to `subscribe` to the write done\ncallback, so let's add a function to a new `libtock_console` crate that sets a\nwrite callback using `subscribe`:\n\n```rust\n#![no_std]\n\nconst DRIVER: usize = 1;\nconst WRITE_DONE: usize = 1;\n\nfn set_write_callback(callback: fn(bytes: usize, data: usize), data: usize) {\n    libtock_runtime::subscribe(DRIVER, WRITE_DONE, write_complete, data);\n    // We need to store `callback` somewhere -- where to do so?\n}\n\nextern \"C\" fn write_complete(bytes: usize, _: usize, _: usize, data: usize) {\n    // Hmm, how do we access the callback?\n}\n```\n\nYou may notice that the code is not quite complete: `set_write_callback` takes a\ncallback but doesn't store it anywhere. We don't want to store it in a global\nvariable because doing so would not be zero-cost: the original app didn't need\nto store a function pointer, and we want to do this refactoring without bloating\nthe app. We could pass it through `data`, but what if the client code needs to\nuse `data` itself? That pattern isn't extensible: if there is another\nasynchronous layer about the console (e.g. a virtualization system), it won't\nhave access to `data` to pass its callbacks through.\n\nInstead, we can pass the callback through the type system. We need a new trait\nto represent the callback. This trait won't be specific to `libtock_console`,\nand we'll later use it in unit tests -- which run on Linux, not Tock, so we'll\nput it in the `libtock_platform` crate:\n\n```rust\npub trait FreeCallback<AsyncResponse> {\n    fn call(response: AsyncResponse);\n}\n```\n\nWe call this `FreeCallback` because it represents a free function as opposed to\na method. (This forshadows `MethodCallback`, which we will need later)\n\nThe reason why we made this a shared generic trait rather than adding a\n`libtock_console::Client` trait as the Tock kernel does will be apparent later.\n\nUsing this trait, we can now write `libtock_console::set_write_callback`:\n\n```rust\n#![no_std]\n\nuse libtock_platform::FreeCallback;\n\nconst DRIVER: usize = 1;\nconst WRITE_DONE: usize = 1;\n\npub struct WriteCompleted {\n    pub bytes: usize,\n    pub data: usize,\n}\n\npub fn set_write_callback<Callback: FreeCallback<WriteCompleted>>(data: usize) {\n    libtock_runtime::subscribe(DRIVER, WRITE_DONE, write_complete::<Callback>, data);\n}\n\nextern \"C\" fn write_complete<Callback: FreeCallback<WriteCompleted>>(\n    bytes: usize, _: usize, _: usize, data: usize)\n{\n    Callback::call(WriteCompleted { bytes, data });\n}\n```\n\nTo finish `libtock_console`, we also need to add `set_write_buffer` (which calls\n`allow`) and `start_write` (which calls `command`), which are much simpler:\n\n```rust\nconst WRITE_BUFFER: usize = 1;\nconst START_WRITE: usize = 1;\n\npub fn set_write_buffer(buffer: &'static [u8]) {\n    libtock_runtime::const_allow(DRIVER, WRITE_BUFFER, buffer);\n}\n\npub fn start_write(bytes: usize) {\n    libtock_runtime::command(DRIVER, START_WRITE, bytes, 0);\n}\n```\n\nWe can then make use of `libtock_console` in our app as follows:\n\n```rust\n#![no_std]\n\nstatic GREETING: [u8; 7] = *b\"Hello, \";\nstatic NOUN: [u8; 7] = *b\"World!\\n\";\nstatic mut DONE: bool = false;\n\nfn main() {\n    libtock_console::set_write_callback::<App>(0);\n    libtock_console::set_write_buffer(&GREETING);\n    libtock_console::start_write(GREETING.len());\n    loop {\n        libtock_runtime::yieldk();\n    }\n}\n\nstruct App;\n\nimpl libtock_platform::FreeCallback<libtock_console::WriteCompleted> for App {\n    fn call(_response: WriteCompleted) {\n        unsafe {\n            if DONE { return; }\n            DONE = true;\n        }\n        libtock_console::set_write_buffer(&NOUN);\n        libtock_console::start_write(NOUN.len());\n    }\n}\n```\n\nNow we have a reusable console library! However, we still don't have any unit\ntests.\n\n## Adding a Fake Kernel\n\nA good unit test for the console driver would test not only the driver's\noperation with successful system calls but also also test the driver's\nerror-handling logic. That is difficult to do if we test using a real Tock\nkernel in an emulator -- the real kernel has the goal of avoiding system call\nerrors! Instead of using a real Tock kernel, driver unit tests should use a\n\"fake kernel\" that simulates the kernel's functionality while allowing errors to\nbe injected.\n\nTo keep this document reasonably short and understandable, we have omitted error\nhandling, but we can still structure our unit tests in a manner that would allow\na test to inject errors when error handling logic is added.\n\nTo allow the console driver to work with both a real kernel and a fake kernel,\nwe add a `Syscalls` trait to `libtock_platform`. When compiled into a Tock\nprocess binary, `Syscalls` will be implemented by a zero-sized type, which\navoids wasting non-volatile storage space or RAM area. To avoid passing around\nreferences to a `Syscalls` implementation, we can pass the `Syscalls` by value\nrather than by reference (i.e. take `self` rather than `&self`). For practical\nuse, this requires the `Syscalls` implementations to be `Copy`.\n\n```rust\npub trait Syscalls: Copy {\n    fn subscribe(self, driver: usize, minor: usize,\n                 callback: extern \"C\" fn(usize, usize, usize, usize),\n                 data: usize);\n\n    fn const_allow(self, major: usize, minor: usize, buffer: &'static [u8]);\n    fn command(self, major: usize, miner: usize, arg1: usize, arg2: usize);\n    fn yieldk(self);\n}\n```\n\nWe then implement `Syscalls` using a real Tock kernel in `libtock_runtime`:\n\n```rust\n#[derive(Clone, Copy)]\npub struct TockSyscalls;\n\nimpl libtock_platform::Syscalls for TockSyscalls {\n    /* Omitted implementation details */\n}\n```\n\nWe adapt `libtock_console` to use an app-provided `Syscalls` implementation\nrather than directly calling into `libtock_runtime`:\n\n```rust\npub fn set_write_callback<S: Syscalls, Callback: FreeCallback<WriteCompleted>>(\n    syscalls: S, data: usize)\n{\n    syscalls.subscribe(1, 1, write_complete::<Callback>, data);\n}\n\nextern \"C\" fn write_complete<Callback: FreeCallback<WriteCompleted>>(\n    bytes: usize, _: usize, _: usize, data: usize)\n{\n    Callback::call(WriteCompleted { bytes, data });\n}\n\npub fn set_write_buffer<S: Syscalls>(syscalls: S, buffer: &'static [u8]) {\n    syscalls.const_allow(1, 1, buffer);\n}\n\npub fn start_write<S: Syscalls>(syscalls: S, bytes: usize) {\n    syscalls.command(1, 1, bytes, 0);\n}\n```\n\nWe'll create a new crate, `libtock_unittest`, which contains test utilities such\nas the fake Tock kernel. The fake kernel, unlike\n`libtock_runtime::TockSyscalls`, needs to maintain state, so it cannot be a\nzero-sized type. Instead of implementing `Syscalls` on the fake kernel directly,\nwe implement it on a shared reference:\n\n```rust\ntype RawCallback = extern \"C\" fn(usize, usize, usize, usize);\n\npub struct FakeSyscalls {\n    callback_pending: core::cell::Cell<Option<usize>>,\n    output: core::cell::Cell<Vec<u8>>,\n    write_buffer: core::cell::Cell<Option<&'static [u8]>>,\n    write_callback: core::cell::Cell<Option<RawCallback>>,\n    write_data: core::cell::Cell<usize>,\n}\n\nimpl FakeSyscalls {\n    pub fn new() -> Self {\n        FakeSyscalls {\n            callback_pending: Cell::new(None),\n            output: Cell::new(Vec::new()),\n            write_buffer: Cell::new(None),\n            write_callback: Cell::new(None),\n            write_data: Cell::new(0),\n        }\n    }\n\n    pub fn read_buffer(&self) -> &'static [u8] {\n        self.write_buffer.take().unwrap_or(&[])\n    }\n}\n\nimpl libtock_platform::Syscalls for &FakeSyscalls {\n    fn subscribe(self, driver: usize, minor: usize, callback: RawCallback, data: usize) {\n        if driver == 1 && minor == 1 {\n            self.write_callback.set(Some(callback));\n            self.write_data.set(data);\n        }\n    }\n\n    fn const_allow(self, major: usize, minor: usize, buffer: &'static [u8]) {\n        if major == 1 && minor == 1 {\n            self.write_buffer.set(Some(buffer));\n        }\n    }\n\n    fn command(self, major: usize, minor: usize, arg1: usize, _arg2: usize) {\n        if major != 1 || minor != 1 { return; }\n        if let Some(buffer) = self.write_buffer.get() {\n            let mut output = self.output.take();\n            let bytes = core::cmp::min(arg1, buffer.len());\n            output.extend_from_slice(&buffer[..bytes]);\n            self.output.set(output);\n            self.callback_pending.set(Some(bytes));\n        }\n    }\n\n    fn yieldk(self) {\n        let bytes = match self.callback_pending.take() {\n            Some(bytes) => bytes,\n            None => return,\n        };\n        if let Some(callback) = self.write_callback.get() {\n            callback(bytes, 0, 0, self.write_data.get());\n        }\n    }\n}\n```\n\n## Adding a Synchronous Adapter\n\nWe're still not ready to add unit tests to `libtock_console` yet!\n`libtock_console` is asynchronous, which is difficult to work with in a unit\ntest. `libtock_core` should provide synchronous APIs for apps that do not wish\nto be fully asynchronous, so lets go ahead and implement a synchronous API. To\navoid re-implementing synchronous APIs for every driver, let's make it work\ngenerically with all `libtock_core` drivers. This is where we benefit from\nmaking `FreeCallback` a generic trait rather than having a\n`libtock_console::Client` trait.\n\nThe synchronous adapter will need to store a copy of an `AsyncResponse`, so its\ncallback cannot be a free function (it needs access to `self`). Therefore, we\nadd the `MethodCallback` trait to `libtock_platform`:\n\n```rust\npub trait MethodCallback<AsyncResponse> {\n    fn call(&self, response: AsyncResponse);\n}\n```\n\nUsing `MethodCallback`, we can now write `SyncAdapter`. We add `SyncAdapter` to\na new crate, `libtock_sync`, as not all Tock apps will want it:\n\n```rust\nuse libtock_platform::MethodCallback;\n\npub struct SyncAdapter<AsyncResponse, Syscalls> {\n    response: core::cell::Cell<Option<AsyncResponse>>,\n    syscalls: Syscalls,\n}\n\nimpl<AsyncResponse, Syscalls> SyncAdapter<AsyncResponse, Syscalls> {\n    pub const fn new(syscalls: Syscalls) -> SyncAdapter<AsyncResponse, Syscalls> {\n        SyncAdapter { response: core::cell::Cell::new(None), syscalls }\n    }\n}\n\nimpl<AsyncResponse, Syscalls: libtock_platform::Syscalls> SyncAdapter<AsyncResponse, Syscalls> {\n    pub fn wait(&self) -> AsyncResponse {\n        loop {\n            match self.response.take() {\n                Some(response) => return response,\n                None => self.syscalls.yieldk(),\n            }\n        }\n    }\n}\n\nimpl<AsyncResponse, Syscalls: libtock_platform::Syscalls>\nMethodCallback<AsyncResponse> for SyncAdapter<AsyncResponse, Syscalls> {\n    fn call(&self, response: AsyncResponse) {\n        self.response.set(Some(response));\n    }\n}\n```\n\n## Adding a Unit Test\n\nBefore we write the test itself, we should add one more utility to\n`libtock_unittest`. That utility is the `test_component!` macro, which creates a\nthread-local instance of a type and provides `FreeCallback` implementations for\nevery `MethodCallback` implementation the type has:\n\n```rust\n#[macro_export]\nmacro_rules! test_component {\n    [$link:ident, $name:ident: $comp:ty = $init:expr] => {\n        let $name = std::boxed::Box::leak(std::boxed::Box::new($init)) as &$comp;\n        std::thread_local!(static GLOBAL: std::cell::Cell<Option<&'static $comp>>\n                           = const {std::cell::Cell::new(None)})\n        GLOBAL.with(|g| g.set(Some($name)));\n        struct $link;\n        impl<T> libtock_platform::FreeCallback<T> for $link\n        where $comp: libtock_platform::MethodCallback<T> {\n            fn call(response: T) {\n                GLOBAL.with(|g| g.get().unwrap()).call(response);\n            }\n        }\n    };\n}\n```\n\nWe can finally add a unit test to `libtock_console`:\n\n```rust\n#[cfg(test)]\nmod tests {\n    #[test]\n    fn write() {\n        extern crate std;\n\n        use libtock_platform::MethodCallback;\n        use libtock_sync::SyncAdapter;\n        use libtock_unittest::FakeSyscalls;\n        use std::boxed::Box;\n        use std::thread_local;\n        use super::{set_write_buffer, set_write_callback, start_write, WriteCompleted};\n\n        let syscalls: &_ = Box::leak(Box::new(FakeSyscalls::new()));\n        libtock_unittest::test_component![SyncAdapterLink, sync_adapter: SyncAdapter<WriteCompleted, &'static FakeSyscalls>\n                                          = SyncAdapter::new(syscalls)];\n\n        set_write_callback::<_, SyncAdapterLink>(syscalls, 1234);\n        set_write_buffer(syscalls, b\"Hello\");\n        start_write(syscalls, 5);\n        let response = sync_adapter.wait();\n        assert_eq!(response.bytes, 5);\n        assert_eq!(response.data, 1234);\n        assert_eq!(syscalls.read_buffer(), b\"Hello\");\n    }\n}\n```\n\n## Adding `static_component!`\n\nWe added `libtock_unittest::test_component!` to make it easy to set up\ncomponents in unit tests, but we have no equivalent for apps. Our app still uses\n`unsafe` to access its `DONE` variable. Instead, lets hide that unsafety behind\na new macro. This macro is only sound in `libtock_runtime`'s single-threaded\nenvironment, so we add it to `libtock_runtime` directly:\n\n```rust\n#[macro_export]\nmacro_rules! static_component {\n    [$link:ident, $name:ident: $comp:ty = $init:expr] => {\n        static mut COMPONENT: $comp = $init;\n        struct $link;\n        impl<T> libtock_platform::FreeCallback<T> for $link\n        where $comp: libtock_platform::MethodCallback<T> {\n            fn call(response: T) {\n                unsafe { &COMPONENT }.call(response);\n            }\n        }\n    };\n}\n```\n\nWe can now use `static_component!` in our Hello World app to instantiate the\n`App` struct:\n\n```rust\n#![no_std]\n\nstatic GREETING: [u8; 7] = *b\"Hello, \";\nstatic NOUN: [u8; 7] = *b\"World!\\n\";\n\nfn main() {\n    libtock_console::set_write_callback::<_, AppLink>(0);\n    libtock_console::set_write_buffer(&GREETING);\n    libtock_console::start_write(GREETING.len());\n    loop {\n        libtock_runtime::yieldk();\n    }\n}\n\nstruct App {\n    done: core::cell::Cell<bool>\n}\n\nimpl App {\n    pub const fn new() -> App {\n        App {\n            done: core::cell::Cell::new(false)\n        }\n    }\n}\n\nimpl MethodCallback<WriteCompleted> for App {\n    fn call(&self, _response: WriteCompleted) {\n        if self.done.get() { return; }\n        self.done.set(true);\n        set_write_buffer(TockSyscalls, &NOUN );\n        start_write(TockSyscalls, NOUN.len() );\n    }\n}\n\nlibtock_runtime::static_component![AppLink, APP: App = App::new()];\n```\n\nNow our app has no more unsafe!\n\n## Recap\n\nWe wrote a Hello World application that uses Tock's console system calls and\nasynchronous callbacks. We then extracted the console system call interface into\na reusable library, creating the `FreeCallback` trait along the way.\n\nIn order to provide unit tests for the console library, we needed to create\nseveral new abstractions. We created `Syscalls` so that we can direct tho\nconsole driver's system calls to a fake kernel. We created the\n`libtock_unittest` crate which contains the fake kernel as well as a\n`test_component!` helper macro. We created `SyncAdapter` so that the unit test\ncan be written in a synchronous manner -- although `SyncAdapter` is not\ntesting-specific! We created `MethodCallback` because `FreeCallback` is not a\npowerful-enough abstraction on its own for `SyncAdapter`.\n\nWe ended up with six Rust crates:\n\n1. `libtock_console`, which contains the console driver logic and unit test\n   code.\n2. `libtock_platform`, which provides abstractions that can be shared with other\n   drivers.\n3. `libtock_runtime`, which contains non-portable system call implementations.\n4. `libtock_sync`, which provides a synchronous interface using\n   `libtock_platform`'s traits.\n5. `libtock_unittest`, which provides a fake Tock kernel and other utilities.\n6. The hello world app itself.\n"
  },
  {
    "path": "doc/Startup.md",
    "content": "Startup\n=======\n\nThis document describes the `libtock_runtime` startup process, up until the\nprocess binary's `main` starts executing.\n\n## Step 1: `start` assembly\n\nThe first code to start executing is in a symbol called `start`, which is\nwritten in handwritten assembly. These implementations are specific to each\narchitecture, and live in `runtime/asm`. This assembly does the following:\n\n1. Checks the initial program counter value against the correct `start` address.\n   This verifies the process was deployed at the direct address in non-volatile\n   storage. This is necessary because `libtock-rs` apps are statically-linked,\n   and an incorrect location would cause undefined behavior. If this check\n   fails, an error may be reported (if the `low_level_debug` capsule is present)\n   and the process terminates.\n1. Moves the process break to make room for the stack, `.data`, and `.bss`. The\n   process break is the top of the process-accessible RAM. The process break is\n   initially moved to be shortly after the end of the `.bss` section (depending\n   on alignment constraints).\n1. Initialize the stack. The initial stack pointer value is provided by the\n   linker script, which calculates it using a symbol called `STACK_MEMORY` in\n   the `.stack_buffer` section.\n1. Copies `.data` from non-volatile storage into RAM. The .data section contains\n   read-write global variables (e.g. `static mut` values) that have nonzero\n   initial values.\n1. Zeroes out `.bss`. `.bss` contains read-write global variables that have zero\n   initial values.\n1. Calls `rust_start`.\n\n## Step 2: `rust_start`\n\n`rust_start` is the first Rust code to execute in a process. It is defined in\nthe `libtock_runtime::startup` module. It runs some higher-level initialization,\nsuch as giving debug information (stack and heap addresses) to the kernel.\n`rust_start` then calls `libtock_unsafe_main`.\n\n## Step 3: `libtock_unsafe_main`\n\n`libtock_unsafe_main` is a shim used to direct execution from `libtock_runtime`\nto the process binary's `main` function. It is generated by the\n`libtock_runtime::set_main!` macro. `libtock_unsafe_main` just calls the\nuser-provided `main` function, then calls `Termination::complete()` on the\nvalue returned from `main`.\n\n## Step 4: `main`\n\nAt this point, the user's `main` starts executing, and `libtock_runtime` is no\nlonger in control. Main is required to return either `!`, or a type which\nimplements the `Termination` trait, which includes a `complete()` method that\nnever returns. Implementations of this trait are provided for `()` and\n`Result<(), ErrorCode>` which call exit-terminate.\nIf a process wishes to loop forever to service callbacks,\nit should call the yield-wait system call in a loop. Process binaries are free to call\nthe `exit` system call themselves if needed.\n\n## Appendix: Why `#![no_main]`?\n\nWriting a `#![no_std]` `bin` crate currently requires using either `#![no_main]`\nor the `start` unstable feature. Because we want to move `libtock-rs` to stable\nRust eventually (hopefully soon after `asm` is stabilized), `libtock-rs` expects\nprocess binaries to be `#![no_main]`.\n"
  },
  {
    "path": "doc/Style.md",
    "content": "Coding Style\n============\n\n## List Ordering\n\nSource code tends to contain many lists whose order is unimportant, such as\ndependency lists in `Cargo.toml` and `mod` declarations in `.rs` files. When\nthere isn't a better reason to prefer a particular order, these lists should be\nin alphabetical order.\n\nBenefits:\n\n1. When lists become long, this makes it easier to search for a particular\n   entry.\n2. Always adding new entries at the bottom of the list results in merge\n   conflicts whenever two PRs add entries to the same list. Putting them in\n   alphabetical order decreases the probability of merge conflicts.\n\n## Naming Conventions\n\nMany things in `libtock-rs` live outside Rust's namespacing system, and can\ntherefore collide with other libraries. Examples include:\n\n1. `cargo` package names\n2. Environment variables\n3. Linker script file names\n\nFor example, if `libtock-rs` were to contain a `cargo` package called `adc`,\nthat package would likely collide with another package if we were to try to\nupload it to crates.io.\n\nTo prevent these collisions, things in `libtock-rs` that can experience external\nname collisions should have a `libtock` prefix (with suitable capitalization).\nFor example:\n\n1. The runtime crate is called `libtock_runtime`\n2. The build platform environment variable is `LIBTOCK_PLATFORM`\n3. The linker script is called `libtock_layout.ld`\n\nHowever, this prefix should be omitted when it is unnecessary, to avoid naming\neverything in the repository `libtock_*`. For example:\n\n1. `libtock_` is omitted from directory names. `libtock_runtime` lives in the\n   `/runtime/` directory.\n2. Cargo packages that are not used externally, such as the `print_sizes` tool\n   (which is only used for developing `libtock-rs` itself), do not have the\n   `libtock_` prefix.\n"
  },
  {
    "path": "doc/Testing.md",
    "content": "Testing\n=======\n\nThis document gives an introduction to the tests in this repository, and is\nintended to be useful to `libtock-rs` contributors.\n\n## Unit Tests\n\nCargo packages in this repository that are platform-independent (i.e. that do\nnot depend on `libtock_runtime`) have unit tests that use Rust's builtin test\nharness. These unit tests run on a fully-featured host OS (Linux, Mac OS,\nWindows, etc...) and therefore do not depend on a real Tock kernel. Instead,\nthese unit tests use the fake kernel provided by `libtock_unittest`. As a\nresult, most `libtock-rs` crates have `libtock_unittest` in their\n`[dev-dependencies]`.\n\n`libtock_platform` is a bit of an exception to this rule. If all of\n`libtock_platform`'s unit tests were in `libtock_platform`, the following would\noccur:\n\n1. `cargo` builds `libtock_platform` with `cfg(test)` enabled to make the test\n   binary.\n2. `cargo` builds `libtock_unittest` because it is a `[dev-dependency]` of\n   `libtock_platform`\n3. `cargo` builds `libtock_platform` without `cfg(test)` because it is a\n   dependency of `libtock_unittest`\n\nBoth copies of `libtock_platform` end up in the final binary. These contain\nincompatible instances of the `Syscalls` trait, resulting in hard-to-understand\nerrors.\n\nTo solve this, some of `libtock_platform`'s unit tests (namely, those that\nrequire `libtock_unittest`) were moved to a `platform_test` crate.\n\n## Integration Tests\n\n`libtock-rs`'s integration tests are Tock process binaries that can run on an\nemulated or real Tock system. They live in `libtock`'s `tests/` directory.\n\nTODO: Figure out a test runner strategy for automatically running all the\nintegration tests, and document it here.\n"
  },
  {
    "path": "doc/UnitTestOwnership.md",
    "content": "Unit Test Ownership Design\n==========================\n\n**TODO: This document describes a not-yet-implemented design for\n`libtock_unittest`. This TODO will be removed when `libtock_unittest` is\nrefactored to use the new design.**\n\nThis document examines the component-level call graph for unit tests, including\nthe code under test, fake kernel, and fake syscall drivers. The call graph\ncontains both shared references and circular references, so representing it via\nRust's ownership system is nontrivial. This document derives an ownership\nstrategy for the fake kernel and fake syscall drivers.\n\n## The Call Graph\n\nFor our current purposes, we are looking at the interactions between the\nfollowing components:\n\n1. **Unit test:** The `#[test]` function, which sets up the test environment and\n   drives the test execution.\n2. **Code under test:** The code which we are testing, which should not depend\n   on `libtock_unittest` (as this code should run on Tock as well as the host\n   system).\n3. **`fake::Kernel`:** A single instance of `fake::Kernel` that handles system\n   calls.\n4. **`fake::SyscallDriver`:** 0 or more `fake::SyscallDriver` instances that\n   implement system call interfaces.\n\nThe function calls we anticipate are as follows:\n\n1. **Unit test -> Code under test:** The test case will instantiate components\n   to test and call into them to execute the test.\n2. **Unit test -> `fake::Kernel`:** The test case will create a fake kernel and\n   call into it to configure it, including registering `fake::SyscallDriver`s\n   with it.\n3. **Unit test -> `fake::SyscallDriver`:** The test case may talk to fake\n   syscall drivers to configure them or inspect their state (e.g. to verify\n   whether the code under test performed particular actions).\n4. **Code under test -> `fake::Kernel`:** The code under test will execute\n   syscalls, which call into the fake kernel.\n5. **`fake::Kernel` -> Code under test:** When the code under test invokes the\n   Yield system call, the fake kernel may call back into the code under test to\n   execute an upcall.\n6. **`fake::Kernel` -> `fake::SyscallDriver`:** The fake kernel will call into\n   fake syscall drivers as part of registering them, and to invoke Command\n   system calls (and perhaps other system calls as well).\n7. **`fake::SyscallDriver` -> `fake::Kernel`:** The fake syscall drivers will\n   call into the fake kernel to queue upcalls and access Allow buffers.\n\nThe **`fake::Kernel` -> Code under test** calls always occur via function\npointer, with the function pointer passed via the Subscribe system call, so we\ndo not need to represent them directly in Rust's ownership system. Therefore I\nwill represent them via a dotted line.\n\nI'll use the term \"share access\" to refer to fake syscall drivers queueing\nupcalls and accessing Allow buffers, as `libtock_platform` uses that terminology\nfor that same functionality.\n\nThis gives the following call graph:\n\n```\n      +----------------------------------------+\n      |             Unit test case             |\n      +----------------------------------------+\n       |                    |                 |\n       V                    V                 V\n+-------+  RawSyscalls  +--------+  Command  +=========+\n| Code  |-------------->| Fake   |---------->| Fake    |\n| under |               | kernel |           | syscall |\n| test  |< - - - - - - -|        |<----------| drivers |\n+-------+  Upcall       +--------+   Share   +=========+\n           invocation                access\n```\n\nThere are a few things to note here:\n\n1. The `fake::Kernel` is shared between the unit test case and the code under\n   test.\n2. The `fake::SyscallDriver` instances are shared between the unit test case and\n   the `fake::Kernel`.\n3. There is a circular dependency between the `fake::Kernel` and the\n   `fake::SyscallDriver`s.\n\nNote that we can ignore the shared access to the code under test, because that\nis handled by `libtock_platform`'s syscall API design.\n\n## Handling the `fake::Kernel` <-> `fake::SyscallDriver` circular dependency\n\nWe cannot do both of the following:\n\n1. Store `&dyn fake::SyscallDriver` references in the `fake::Kernel`.\n2. Store `&fake::Kernel` references in the `fake::SyscallDriver`s.\n\nbecause those references types require lifetime parameters, and drop check will\nnot pass (both `fake::Kernel` and the `fake::SyscallDriver`s use dynamic memory\nallocation). Therefore, we need to give up on one of the above.\n\nFortunately, number 2 (storing references to the kernel inside the fake syscall\ndrivers) isn't quite what we want anyway. Fake syscall drivers should have\naccess to share data associated with their driver number, but not other drivers.\nSo it makes more sense to give them a handle type, which we can call\n`DriverShareRef`, which only gives them access to their own shares. To avoid the\ndrop check issues, `DriverShareRef` cannot have a lifetime parameter, so the\nshare data itself needs to be pulled out into a separate object:\n\n```\n      +----------------------------------------+\n      |             Unit test case             |\n      +----------------------------------------+\n       |                    |                 |\n       V                    V                 V\n+-------+  RawSyscalls  +--------+  Command  +=========+\n| Code  |-------------->| Fake   |---------->| Fake    |\n| under |               | kernel |           | syscall |\n| test  |< - - - - - - -|        |           | drivers |\n+-------+  Upcall       +--------+           +=========+\n           invocation           |             |\n                                | Rc<>        | DriverShareRef\n                                V             V\n                               +---------------+\n                               | ShareData     |\n                               +---------------+\n```\n\n`ShareData` would contain data common to all `fake::SyscallDriver`s (such as the\nupcall queue).\n\n`DriverShareRef`'s API will allow the `fake::SyscallDriver`s to read Allow\nbuffers shared with them as well as queue upcalls. As such, it will need to\ncontain the following data:\n\n```rust\nstruct DriverShareRef {\n    driver_num: u32,\n    share_data: Rc<ShareData>,\n}\n```\n\nTo give the `DriverShareRef` to the `fake::SyscallDriver`s, we need to add a\nregistration function to `fake::SyscallDriver`:\n\n```rust\ntrait SyscallDriver {\n    /* ... */\n\n    fn register(&self, share_ref: DriverShareRef);\n}\n```\n\n## Remaining details\n\nWith the above design for `fake::Kernel` and `fake::SyscallDriver`, the unit\ntest case can directly own both the `fake::Kernel` and the\n`fake::SyscallDriver`s. The `fake::Kernel` can hold `&dyn fake::SyscallDriver`s.\n\nIf we implement `RawSyscalls` on `&fake::Kernel`, then we can avoid using\nthread-local storage.\n\nThis will require the `fake::Kernel` and `fake::SyscallDriver`s to use interior\nmutability.\n"
  },
  {
    "path": "examples/adc.rs",
    "content": "//! A simple libtock-rs example. Checks for adc driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Console;\n\nuse libtock::adc::Adc;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x200}\n\nfn main() {\n    if Adc::exists().is_err() {\n        writeln!(Console::writer(), \"adc driver unavailable\").unwrap();\n        return;\n    }\n\n    loop {\n        match Adc::read_single_sample_sync() {\n            Ok(adc_val) => writeln!(Console::writer(), \"Sample: {adc_val}\\n\").unwrap(),\n            Err(_) => writeln!(Console::writer(), \"error while reading sample\",).unwrap(),\n        }\n\n        Alarm::sleep_for(Milliseconds(2000)).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/ambient_light.rs",
    "content": "//! A simple libtock-rs example. Checks for ambient light driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Console;\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::ambient_light::AmbientLight;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x200}\n\nfn main() {\n    if AmbientLight::exists().is_err() {\n        writeln!(Console::writer(), \"ambient light driver unavailable\").unwrap();\n        return;\n    }\n\n    loop {\n        match AmbientLight::read_intensity_sync() {\n            Ok(intensity_val) => {\n                writeln!(Console::writer(), \"Light intensity: {intensity_val} lux\\n\").unwrap()\n            }\n            Err(_) => writeln!(Console::writer(), \"error while reading light intensity\",).unwrap(),\n        }\n\n        Alarm::sleep_for(Milliseconds(2000)).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/blink.rs",
    "content": "//! The blink app.\n\n#![no_main]\n#![no_std]\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::leds::Leds;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x200}\n\nfn main() {\n    let mut count = 0;\n    if let Ok(leds_count) = Leds::count() {\n        loop {\n            for led_index in 0..leds_count {\n                if count & (1 << led_index) > 0 {\n                    let _ = Leds::on(led_index);\n                } else {\n                    let _ = Leds::off(led_index);\n                }\n            }\n\n            Alarm::sleep_for(Milliseconds(250)).unwrap();\n\n            count += 1;\n        }\n    }\n}\n"
  },
  {
    "path": "examples/buttons.rs",
    "content": "//! An extremely simple libtock-rs example. Register button events.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::buttons::{ButtonListener, Buttons};\nuse libtock::console::Console;\nuse libtock::leds::Leds;\nuse libtock::runtime::{set_main, stack_size};\nuse libtock_platform::{share, Syscalls};\nuse libtock_runtime::TockSyscalls;\n\nset_main! {main}\nstack_size! {0x1000}\n\nfn main() {\n    let listener = ButtonListener(|button, state| {\n        let _ = Leds::toggle(button);\n        writeln!(Console::writer(), \"button {button:?}: {state:?}\").unwrap();\n    });\n    if let Ok(buttons_count) = Buttons::count() {\n        writeln!(Console::writer(), \"button count: {buttons_count}\").unwrap();\n\n        share::scope(|subscribe| {\n            // Subscribe to the button callback.\n            Buttons::register_listener(&listener, subscribe).unwrap();\n\n            // Enable interrupts for each button press.\n            for i in 0..buttons_count {\n                Buttons::enable_interrupts(i).unwrap();\n            }\n\n            // Wait for buttons to be pressed.\n            loop {\n                TockSyscalls::yield_wait();\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "examples/console.rs",
    "content": "//! An extremely simple libtock-rs example. Just prints out a message\n//! using the Console capsule, then terminates.\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::console::Console;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x100}\n\nfn main() {\n    writeln!(Console::writer(), \"Hello world!\").unwrap();\n}\n"
  },
  {
    "path": "examples/gpio.rs",
    "content": "//! A simple GPIO example for getting GPIO interrupts.\n//!\n//! This will configure GPIO 0 to be a rising-edge triggered interrupt and print\n//! a message when the interrupt is triggered.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Console;\nuse libtock::gpio;\nuse libtock::gpio::Gpio;\nuse libtock::runtime::{set_main, stack_size};\nuse libtock_platform::{share, Syscalls};\nuse libtock_runtime::TockSyscalls;\n\nset_main! {main}\nstack_size! {0x1000}\n\nfn main() {\n    let listener = gpio::GpioInterruptListener(|gpio_index, state| {\n        writeln!(Console::writer(), \"GPIO[{gpio_index}]: {state:?}\").unwrap();\n    });\n\n    if !Gpio::count().is_ok_and(|c| c > 0) {\n        writeln!(Console::writer(), \"No GPIO pins on this board.\").unwrap();\n        return;\n    }\n\n    // Configure pin 0 as an input and enable rising interrupts\n    let pin = Gpio::get_pin(0).unwrap();\n    let input_pin = pin.make_input::<gpio::PullNone>().unwrap();\n    let _ = input_pin.enable_interrupts(gpio::PinInterruptEdge::Rising);\n\n    // Wait for callbacks.\n    share::scope(|subscribe| {\n        Gpio::register_listener(&listener, subscribe).unwrap();\n\n        loop {\n            TockSyscalls::yield_wait();\n        }\n    });\n}\n"
  },
  {
    "path": "examples/i2c_master_write_read.rs",
    "content": "//! This sample demonstrates setting up the i2c ip (assuming board has support)\n//! for master mode. In the event loop, we write some bytes to the target, then\n//! attempt to read some bytes from the target.\n//!\n//! This sample is tested with `i2c_slave_send_recv.rs` sample running on the\n//! slave device. That sample uses the synchronous slave api, so the order of operations\n//! is important to ensure we don't cause the slave to stretch clocks if it hasn't setup\n//! send buffers in time.\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::console::Console;\nuse libtock::i2c_master_slave::I2CMasterSlave;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x400}\n\npub const SLAVE_DEVICE_ADDR: u16 = 0x69;\n\nfn main() {\n    let addr = SLAVE_DEVICE_ADDR;\n    // 7-bit addressing\n    assert!(addr <= 0x7f);\n    let mut tx_buf: [u8; 4] = [0; 4];\n    // Write 4 bytes to the slave\n    let tx_len = 4;\n    let mut rx_buf: [u8; 2] = [0; 2];\n    // Attempt to read 2 bytes from the slave\n    let rx_len = 2;\n\n    writeln!(Console::writer(), \"i2c-master: write-read sample\\r\").unwrap();\n    writeln!(Console::writer(), \"i2c-master: slave address 0x{addr:x}!\\r\").unwrap();\n\n    let mut i: u32 = 0;\n    loop {\n        writeln!(\n            Console::writer(),\n            \"i2c-master: write-read operation {i:?}\\r\"\n        )\n        .unwrap();\n\n        // Change up the data in tx-buffer\n        tx_buf[0] = tx_buf[0].wrapping_add(2);\n        tx_buf[1] = tx_buf[1].wrapping_add(4);\n        tx_buf[2] = tx_buf[2].wrapping_add(6);\n        tx_buf[3] = tx_buf[3].wrapping_add(8);\n\n        if let Err(why) = I2CMasterSlave::i2c_master_slave_write_sync(addr, &tx_buf, tx_len) {\n            writeln!(\n                Console::writer(),\n                \"i2c-master: write operation failed {why:?}\"\n            )\n            .unwrap();\n        } else {\n            // This sample target the i2c_slave_send_recv.rs sample, which is synchronous.\n            //      so allow some time for it to setup 'send' buffer.\n            Alarm::sleep_for(Milliseconds(200)).unwrap();\n\n            let r = I2CMasterSlave::i2c_master_slave_read_sync(addr, &mut rx_buf, rx_len);\n            match r.1 {\n                Ok(()) => {\n                    writeln!(\n                        Console::writer(),\n                        \"{:} bytes read from slave | data received (0h): {:x?}\\r\\n\",\n                        r.0,\n                        rx_buf\n                    )\n                    .unwrap();\n                }\n                Err(why) => {\n                    writeln!(\n                        Console::writer(),\n                        \"i2c-master: read operation failed {why:?}\"\n                    )\n                    .unwrap();\n                }\n            }\n            i += 1;\n        }\n        Alarm::sleep_for(Milliseconds(1000)).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/i2c_slave_send_recv.rs",
    "content": "//! This sample demonstrates setting up the i2c ip (assuming board has support)\n//! for target mode. In the event loop, we first expect the master to write some data\n//! then we setup a response packet.\n//!\n//! NOTE: The device (based on hwip) may stretch clocks by holding the SCL line low if the master attempts to\n//! read data before we have setup the read data buffers.\n//!\n//! This sample is tested with `i2c_master_write_read.rs` sample running on the\n//! master device.\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::console::Console;\nuse libtock::i2c_master_slave::I2CMasterSlave;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x400}\npub const SLAVE_DEVICE_ADDR: u8 = 0x69;\nfn main() {\n    let mut rx_buf: [u8; 8] = [0; 8];\n    let mut tx_buf: [u8; 8] = [0; 8];\n    let addr: u8 = SLAVE_DEVICE_ADDR;\n    // 7-bit addressing\n    assert!(addr <= 0x7f);\n\n    writeln!(Console::writer(), \"i2c-slave: setting up\\r\").unwrap();\n    writeln!(Console::writer(), \"i2c-slave: address 0x{addr:x}!\\r\").unwrap();\n\n    I2CMasterSlave::i2c_master_slave_set_slave_address(addr).expect(\"i2c-target: Failed to listen\");\n    let mut i: u32 = 0;\n    loop {\n        writeln!(Console::writer(), \"i2c-slave: operation {i:?}\\r\").unwrap();\n\n        // Expect a write, if the master reads here, the IP may stretch clocks!\n        let r = I2CMasterSlave::i2c_master_slave_write_recv_sync(&mut rx_buf);\n\n        if let Err(why) = r.1 {\n            writeln!(\n                Console::writer(),\n                \"i2c-slave: error to receiving data {why:?}\\r\"\n            )\n            .unwrap();\n        } else {\n            writeln!(\n                Console::writer(),\n                \"{:} bytes received from master | buf: {:x?}\\r\",\n                r.0,\n                rx_buf\n            )\n            .unwrap();\n\n            // Note: The master should allow a little delay when communicating with this slave\n            //       as we are doing everything synchronously.\n            // Expect a 2 byte read by master and let's keep changing the values\n            tx_buf[0] = tx_buf[0].wrapping_add(1);\n            tx_buf[1] = tx_buf[1].wrapping_add(5);\n            let r = I2CMasterSlave::i2c_master_slave_read_send_sync(&tx_buf, tx_buf.len());\n\n            match r.1 {\n                Ok(()) => {\n                    writeln!(\n                        Console::writer(),\n                        \"{:} bytes read by master | data sent: {:x?}\\r\",\n                        r.0,\n                        tx_buf\n                    )\n                    .unwrap();\n                    i += 1;\n                }\n                Err(why) => {\n                    writeln!(\n                        Console::writer(),\n                        \"i2c-slave: error setting up read_send {why:?}\\r\"\n                    )\n                    .unwrap();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "examples/ieee802154_raw.rs",
    "content": "//! An example showing use of IEEE 802.15.4 networking.\n//!\n//! The kernel contains a standard and phy 15.4 driver. This example\n//! expects the kernel to be configured with the phy 15.4 driver to\n//! allow direct access to the radio and the ability to send \"raw\"\n//! frames. An example board file using this driver is provided at\n//! `boards/tutorials/nrf52840dk-thread-tutorial`.\n//!\n//! \"No Support\" Errors for setting the channel/tx power are a telltale\n//! sign that the kernel is not configured with the phy 15.4 driver.\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::console::Console;\nuse libtock::ieee802154::{Ieee802154, RxOperator as _, RxRingBuffer, RxSingleBufferOperator};\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x600}\n\nfn main() {\n    // Configure the radio\n    let pan: u16 = 0xcafe;\n    let addr_short: u16 = 0xdead;\n    let addr_long: u64 = 0xdead_dad;\n    let tx_power: i8 = -3;\n    let channel: u8 = 11;\n\n    writeln!(Console::writer(), \"Configuring IEEE 802.15.4 radio...\\n\").unwrap();\n\n    Ieee802154::set_pan(pan);\n    writeln!(Console::writer(), \"Set PAN to {:#06x}\\n\", pan).unwrap();\n\n    Ieee802154::set_address_short(addr_short);\n    writeln!(\n        Console::writer(),\n        \"Set short address to {:#06x}\\n\",\n        addr_short\n    )\n    .unwrap();\n\n    Ieee802154::set_address_long(addr_long);\n    writeln!(\n        Console::writer(),\n        \"Set long address to {:#018x}\\n\",\n        addr_long\n    )\n    .unwrap();\n\n    Ieee802154::set_tx_power(tx_power).unwrap();\n    writeln!(Console::writer(), \"Set TX power to {}\\n\", tx_power).unwrap();\n\n    Ieee802154::set_channel(channel).unwrap();\n    writeln!(Console::writer(), \"Set channel to {}\\n\", channel).unwrap();\n\n    // Don't forget to commit the config!\n    Ieee802154::commit_config();\n    writeln!(Console::writer(), \"Committed radio configuration!\\n\").unwrap();\n\n    // Turn the radio on\n    Ieee802154::radio_on().unwrap();\n    assert!(Ieee802154::is_on());\n\n    // Transmit a frame\n    Ieee802154::transmit_frame_raw(b\"foobar\").unwrap();\n\n    Console::write(b\"Transmitted frame!\\n\").unwrap();\n\n    // Showcase receiving to a single buffer - there is a risk of losing some frames.\n    // See [RxSingleBufferOperator] docs for more details.\n    rx_single_buffer();\n}\n\nfn rx_single_buffer() {\n    let mut buf = RxRingBuffer::<2>::new();\n    let mut operator = RxSingleBufferOperator::new(&mut buf);\n\n    let frame1 = operator.receive_frame().unwrap();\n    // Access frame1 data here:\n    let _body_len = frame1.payload_len;\n    let _first_body_byte = frame1.body[0];\n\n    let _frame2 = operator.receive_frame().unwrap();\n    // Access frame2 data here\n}\n"
  },
  {
    "path": "examples/ieee802154_rx_raw.rs",
    "content": "//! An example showing use of IEEE 802.15.4 networking.\n//! It infinitely received a frame and prints its content to Console.\n//!\n//! The kernel contains a standard and phy 15.4 driver. This example\n//! expects the kernel to be configured with the phy 15.4 driver to\n//! allow direct access to the radio and the ability to send \"raw\"\n//! frames. An example board file using this driver is provided at\n//! `boards/tutorials/nrf52840dk-thread-tutorial`.\n//!\n//! \"No Support\" Errors for setting the channel/tx power are a telltale\n//! sign that the kernel is not configured with the phy 15.4 driver.\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::console::Console;\nuse libtock::ieee802154::{Ieee802154, RxOperator as _, RxRingBuffer, RxSingleBufferOperator};\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x600}\n\nfn main() {\n    // Configure the radio\n    let pan: u16 = 0xcafe;\n    let addr_short: u16 = 0xdead;\n    let addr_long: u64 = 0xdead_dad;\n    let tx_power: i8 = 4;\n    let channel: u8 = 11;\n\n    writeln!(Console::writer(), \"Configuring IEEE 802.15.4 radio...\\n\").unwrap();\n\n    Ieee802154::set_pan(pan);\n    writeln!(Console::writer(), \"Set PAN to {:#06x}\\n\", pan).unwrap();\n\n    Ieee802154::set_address_short(addr_short);\n    writeln!(\n        Console::writer(),\n        \"Set short address to {:#06x}\\n\",\n        addr_short\n    )\n    .unwrap();\n\n    Ieee802154::set_address_long(addr_long);\n    writeln!(\n        Console::writer(),\n        \"Set long address to {:#018x}\\n\",\n        addr_long\n    )\n    .unwrap();\n\n    Ieee802154::set_tx_power(tx_power).unwrap();\n    writeln!(Console::writer(), \"Set TX power to {}\\n\", tx_power).unwrap();\n\n    Ieee802154::set_channel(channel).unwrap();\n    writeln!(Console::writer(), \"Set channel to {}\\n\", channel).unwrap();\n\n    // Don't forget to commit the config!\n    Ieee802154::commit_config();\n    writeln!(Console::writer(), \"Committed radio configuration!\\n\").unwrap();\n\n    // Turn the radio on\n    Ieee802154::radio_on().unwrap();\n    assert!(Ieee802154::is_on());\n    writeln!(Console::writer(), \"Radio is on!\\n\").unwrap();\n\n    let mut buf = RxRingBuffer::<2>::new();\n    let mut operator = RxSingleBufferOperator::new(&mut buf);\n    loop {\n        let frame = operator.receive_frame().unwrap();\n\n        let body_len = frame.payload_len;\n\n        // Parse the counter.\n        let text = &frame.body[..body_len as usize - core::mem::size_of::<usize>()];\n        let counter_bytes =\n            &frame.body[body_len as usize - core::mem::size_of::<usize>()..body_len as usize];\n        let counter = usize::from_be_bytes(counter_bytes.try_into().unwrap());\n\n        writeln!(\n            Console::writer(),\n            \"Received frame with body of len {}: \\\"{} {}\\\"\\n\",\n            body_len,\n            core::str::from_utf8(text).unwrap_or(\"-- error decoding utf8 string --\"),\n            counter,\n        )\n        .unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/ieee802154_rx_tx_raw.rs",
    "content": "//! An example showing use of IEEE 802.15.4 networking.\n//! It infinitely sends a frame with a constantly incremented counter,\n//! and after each send receives a frame and prints it to Console.\n//!\n//! The kernel contains a standard and phy 15.4 driver. This example\n//! expects the kernel to be configured with the phy 15.4 driver to\n//! allow direct access to the radio and the ability to send \"raw\"\n//! frames. An example board file using this driver is provided at\n//!\n//! \"No Support\" Errors for setting the channel/tx power are a telltale\n//! sign that the kernel is not configured with the phy 15.4 driver.\n//! `boards/tutorials/nrf52840dk-thread-tutorial`.\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::console::Console;\nuse libtock::ieee802154::{Ieee802154, RxOperator as _, RxRingBuffer, RxSingleBufferOperator};\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x600}\n\nfn main() {\n    // Configure the radio\n    let pan: u16 = 0xcafe;\n    let addr_short: u16 = 0xdead;\n    let addr_long: u64 = 0xdead_dad;\n    let tx_power: i8 = 4;\n    let channel: u8 = 11;\n\n    writeln!(Console::writer(), \"Configuring IEEE 802.15.4 radio...\\n\").unwrap();\n\n    Ieee802154::set_pan(pan);\n    writeln!(Console::writer(), \"Set PAN to {:#06x}\\n\", pan).unwrap();\n\n    Ieee802154::set_address_short(addr_short);\n    writeln!(\n        Console::writer(),\n        \"Set short address to {:#06x}\\n\",\n        addr_short\n    )\n    .unwrap();\n\n    Ieee802154::set_address_long(addr_long);\n    writeln!(\n        Console::writer(),\n        \"Set long address to {:#018x}\\n\",\n        addr_long\n    )\n    .unwrap();\n\n    Ieee802154::set_tx_power(tx_power).unwrap();\n    writeln!(Console::writer(), \"Set TX power to {}\\n\", tx_power).unwrap();\n\n    Ieee802154::set_channel(channel).unwrap();\n    writeln!(Console::writer(), \"Set channel to {}\\n\", channel).unwrap();\n\n    // Don't forget to commit the config!\n    Ieee802154::commit_config();\n    writeln!(Console::writer(), \"Committed radio configuration!\\n\").unwrap();\n\n    // Turn the radio on\n    Ieee802154::radio_on().unwrap();\n    assert!(Ieee802154::is_on());\n    writeln!(Console::writer(), \"Radio is on!\\n\").unwrap();\n\n    let mut buf = RxRingBuffer::<2>::new();\n    let mut operator = RxSingleBufferOperator::new(&mut buf);\n\n    let mut counter = 0_usize;\n    let mut buf = [\n        b'f', b'r', b'a', b'm', b'e', b' ', b'n', b'.', b'o', b'.', b' ', b'\\0', b'\\0', b'\\0',\n        b'\\0',\n    ];\n    fn set_buf_cnt(buf: &mut [u8], counter: &mut usize) {\n        let buf_len = buf.len();\n        let buf_cnt = &mut buf[buf_len - core::mem::size_of_val(&counter)..];\n        buf_cnt.copy_from_slice(&counter.to_be_bytes());\n    }\n\n    loop {\n        Alarm::sleep_for(Milliseconds(1000)).unwrap();\n\n        set_buf_cnt(&mut buf, &mut counter);\n\n        // Transmit a frame\n        Ieee802154::transmit_frame_raw(&buf).unwrap();\n\n        writeln!(Console::writer(), \"Transmitted frame {counter}!\\n\").unwrap();\n\n        let frame = operator.receive_frame().unwrap();\n\n        let body_len = frame.payload_len;\n\n        // Parse the counter.\n        let text = &frame.body[..body_len as usize - core::mem::size_of::<usize>()];\n        let counter_bytes =\n            &frame.body[body_len as usize - core::mem::size_of::<usize>()..body_len as usize];\n        let received_counter = usize::from_be_bytes(counter_bytes.try_into().unwrap());\n\n        writeln!(\n            Console::writer(),\n            \"Received frame with body of len {}: \\\"{} {}\\\"\\n\",\n            body_len,\n            core::str::from_utf8(text).unwrap_or(\"-- error decoding utf8 string --\"),\n            received_counter,\n        )\n        .unwrap();\n\n        counter += 1;\n    }\n}\n"
  },
  {
    "path": "examples/ieee802154_tx_raw.rs",
    "content": "//! An example showing use of IEEE 802.15.4 networking.\n//! It infinitely sends a frame with a constantly incremented counter.\n//!\n//! The kernel contains a standard and phy 15.4 driver. This example\n//! expects the kernel to be configured with the phy 15.4 driver to\n//! allow direct access to the radio and the ability to send \"raw\"\n//! frames. An example board file using this driver is provided at\n//! `boards/tutorials/nrf52840dk-thread-tutorial`.\n//!\n//! \"No Support\" Errors for setting the channel/tx power are a telltale\n//! sign that the kernel is not configured with the phy 15.4 driver.\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::console::Console;\nuse libtock::ieee802154::Ieee802154;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x600}\n\nfn main() {\n    // Configure the radio\n    let pan: u16 = 0xcafe;\n    let addr_short: u16 = 0xdead;\n    let addr_long: u64 = 0xdeaddad;\n    let tx_power: i8 = 4;\n    let channel: u8 = 11;\n\n    writeln!(Console::writer(), \"Configuring IEEE 802.15.4 radio...\\n\").unwrap();\n\n    Ieee802154::set_pan(pan);\n    writeln!(Console::writer(), \"Set PAN to {:#06x}\\n\", pan).unwrap();\n\n    Ieee802154::set_address_short(addr_short);\n    writeln!(\n        Console::writer(),\n        \"Set short address to {:#06x}\\n\",\n        addr_short\n    )\n    .unwrap();\n\n    Ieee802154::set_address_long(addr_long);\n    writeln!(\n        Console::writer(),\n        \"Set long address to {:#018x}\\n\",\n        addr_long\n    )\n    .unwrap();\n\n    Ieee802154::set_tx_power(tx_power).unwrap();\n    writeln!(Console::writer(), \"Set TX power to {}\\n\", tx_power).unwrap();\n\n    Ieee802154::set_channel(channel).unwrap();\n    writeln!(Console::writer(), \"Set channel to {}\\n\", channel).unwrap();\n\n    // Don't forget to commit the config!\n    Ieee802154::commit_config();\n    writeln!(Console::writer(), \"Committed radio configuration!\\n\").unwrap();\n\n    // Turn the radio on\n    Ieee802154::radio_on().unwrap();\n    assert!(Ieee802154::is_on());\n    writeln!(Console::writer(), \"Radio is on!\\n\").unwrap();\n\n    let mut counter = 0_usize;\n    let mut buf = [\n        b'f', b'r', b'a', b'm', b'e', b' ', b'n', b'.', b'o', b'.', b' ', b'\\0', b'\\0', b'\\0',\n        b'\\0',\n    ];\n    fn set_buf_cnt(buf: &mut [u8], counter: &mut usize) {\n        let buf_len = buf.len();\n        let buf_cnt = &mut buf[buf_len - core::mem::size_of_val(&counter)..];\n        buf_cnt.copy_from_slice(&counter.to_be_bytes());\n    }\n\n    loop {\n        Alarm::sleep_for(Milliseconds(1000)).unwrap();\n\n        set_buf_cnt(&mut buf, &mut counter);\n\n        // Transmit a frame\n        Ieee802154::transmit_frame_raw(&buf).unwrap();\n\n        writeln!(Console::writer(), \"Transmitted frame {counter}!\\n\").unwrap();\n\n        counter += 1;\n    }\n}\n"
  },
  {
    "path": "examples/kv.rs",
    "content": "//! A key-value store example. Gets and sets key-value objects.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse core::str;\nuse libtock::console::Console;\n\nuse libtock::key_value::KeyValue;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x200}\n\n/// Retrieve a key and insert the value into `value`. Then print the value\n/// contents as a UTF-8 string or as hex values.\nfn get_and_print(key: &[u8], value: &mut [u8]) {\n    match KeyValue::get(key, value) {\n        Ok(val_length) => {\n            let val_length: usize = val_length as usize;\n            writeln!(Console::writer(), \"Got value len: {val_length}\").unwrap();\n\n            match str::from_utf8(&value[0..val_length]) {\n                Ok(val_str) => writeln!(Console::writer(), \"Value: {val_str}\").unwrap(),\n                Err(_) => {\n                    write!(Console::writer(), \"Value: \").unwrap();\n                    for val in &value[0..val_length] {\n                        write!(Console::writer(), \"{val:02x}\").unwrap();\n                    }\n                    writeln!(Console::writer()).unwrap();\n                }\n            }\n        }\n        Err(_) => writeln!(Console::writer(), \"error KV::get()\",).unwrap(),\n    }\n}\n\nfn main() {\n    // Check if there is key-value support on this board.\n    if KeyValue::exists() {\n        writeln!(Console::writer(), \"KV available!\").unwrap()\n    } else {\n        writeln!(Console::writer(), \"ERR! KV unavailable\").unwrap();\n    }\n\n    // Do a test query for key: a.\n    let key = \"a\";\n    let mut value: [u8; 64] = [0; 64];\n    get_and_print(key.as_bytes(), &mut value);\n\n    // Now set, get, delete, then get the key: libtock-rs.\n    let set_key = \"libtock-rs\";\n    let set_val = \"kv test app\";\n\n    match KeyValue::set(set_key.as_bytes(), set_val.as_bytes()) {\n        Ok(()) => {\n            writeln!(Console::writer(), \"Successfully set the key-value\").unwrap();\n        }\n        Err(_) => writeln!(Console::writer(), \"error KV::set()\",).unwrap(),\n    }\n\n    get_and_print(set_key.as_bytes(), &mut value);\n\n    match KeyValue::delete(set_key.as_bytes()) {\n        Ok(()) => {\n            writeln!(Console::writer(), \"Successfully deleted the key-value\").unwrap();\n        }\n        Err(_) => writeln!(Console::writer(), \"error KV::delete()\",).unwrap(),\n    }\n\n    get_and_print(set_key.as_bytes(), &mut value);\n}\n"
  },
  {
    "path": "examples/leds.rs",
    "content": "//! A simple libtock-rs example. Just blinks all the LEDs.\n\n#![no_main]\n#![no_std]\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::leds::Leds;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x200}\n\nfn main() {\n    if let Ok(leds_count) = Leds::count() {\n        loop {\n            for led_index in 0..leds_count {\n                let _ = Leds::toggle(led_index);\n            }\n            Alarm::sleep_for(Milliseconds(250)).unwrap();\n        }\n    }\n}\n"
  },
  {
    "path": "examples/low_level_debug.rs",
    "content": "//! An extremely simple libtock-rs example. Just prints out a few numbers using\n//! the LowLevelDebug capsule then terminates.\n\n#![no_main]\n#![no_std]\n\nuse libtock::low_level_debug::LowLevelDebug;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x100}\n\nfn main() {\n    LowLevelDebug::print_1(1);\n    LowLevelDebug::print_2(2, 3);\n}\n"
  },
  {
    "path": "examples/music.rs",
    "content": "//! Implementation done by : https://github.com/teodorobert\n//! A simple libtock-rs example. Plays Ode of Joy using the buzzer.\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse core::time::Duration;\nuse libtock::buzzer::{Buzzer, Note};\nuse libtock::console::Console;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x800}\n\n// Adapted from https://github.com/robsoncouto/arduino-songs\n\n// Notes in the form of (note_frequency, note_delay in musical terms)\nconst MELODY: [(Note, i32); 62] = [\n    (Note::E4, 4),\n    (Note::E4, 4),\n    (Note::F4, 4),\n    (Note::G4, 4),\n    (Note::G4, 4),\n    (Note::F4, 4),\n    (Note::E4, 4),\n    (Note::D4, 4),\n    (Note::C4, 4),\n    (Note::C4, 4),\n    (Note::D4, 4),\n    (Note::E4, 4),\n    (Note::E4, -4),\n    (Note::D4, 8),\n    (Note::D4, 2),\n    (Note::E4, 4),\n    (Note::E4, 4),\n    (Note::F4, 4),\n    (Note::G4, 4),\n    (Note::G4, 4),\n    (Note::F4, 4),\n    (Note::E4, 4),\n    (Note::D4, 4),\n    (Note::C4, 4),\n    (Note::C4, 4),\n    (Note::D4, 4),\n    (Note::E4, 4),\n    (Note::D4, -4),\n    (Note::C4, 8),\n    (Note::C4, 2),\n    (Note::D4, 4),\n    (Note::D4, 4),\n    (Note::E4, 4),\n    (Note::C4, 4),\n    (Note::D4, 4),\n    (Note::E4, 8),\n    (Note::F4, 8),\n    (Note::E4, 4),\n    (Note::C4, 4),\n    (Note::D4, 4),\n    (Note::E4, 8),\n    (Note::F4, 8),\n    (Note::E4, 4),\n    (Note::D4, 4),\n    (Note::C4, 4),\n    (Note::D4, 4),\n    (Note::G3, 2),\n    (Note::E4, 4),\n    (Note::E4, 4),\n    (Note::F4, 4),\n    (Note::G4, 4),\n    (Note::G4, 4),\n    (Note::F4, 4),\n    (Note::E4, 4),\n    (Note::D4, 4),\n    (Note::C4, 4),\n    (Note::C4, 4),\n    (Note::D4, 4),\n    (Note::E4, 4),\n    (Note::D4, -4),\n    (Note::C4, 8),\n    (Note::C4, 2),\n];\n\nconst TEMPO: u32 = 114;\nconst WHOLE_NOTE: u32 = (60000 * 4) / TEMPO;\n\nfn main() {\n    if Buzzer::exists().is_err() {\n        writeln!(Console::writer(), \"There is no available buzzer\").unwrap();\n        return;\n    }\n\n    writeln!(Console::writer(), \"Ode to Joy\").unwrap();\n\n    for (frequency, duration) in MELODY.iter() {\n        let mut note_duration: Duration =\n            Duration::from_millis((WHOLE_NOTE / duration.unsigned_abs()) as u64);\n        // let mut note_duration = WHOLE_NOTE / duration.unsigned_abs();\n        if duration < &0 {\n            note_duration = note_duration * 15 / 10;\n        }\n\n        let note_duration = note_duration * 9 / 10;\n        Buzzer::tone_sync(*frequency as u32 * 3, note_duration).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/ninedof.rs",
    "content": "//! Libtock-rs example for the ninedof sensor.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Console;\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::ninedof::NineDof;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x2000}\n\nfn main() {\n    if NineDof::exists().is_err() {\n        writeln!(Console::writer(), \"NineDof driver unavailable\").unwrap();\n        return;\n    }\n\n    writeln!(Console::writer(), \"NineDof driver available\").unwrap();\n    loop {\n        let accelerometer_data = NineDof::read_accelerometer_sync();\n        let magnetomer_data = NineDof::read_magnetometer_sync();\n        let gyroscope_data = NineDof::read_gyroscope_sync();\n\n        match accelerometer_data {\n            Ok(data) => {\n                writeln!(\n                    Console::writer(),\n                    \"Accelerometer: x: {}, y: {}, z: {}\",\n                    data.x,\n                    data.y,\n                    data.z\n                )\n                .unwrap();\n            }\n            Err(_) => writeln!(Console::writer(), \"error while reading accelerometer\").unwrap(),\n        }\n\n        match magnetomer_data {\n            Ok(data) => {\n                writeln!(\n                    Console::writer(),\n                    \"Magnetometer: x: {}, y: {}, z: {}\",\n                    data.x,\n                    data.y,\n                    data.z\n                )\n                .unwrap();\n            }\n            Err(_) => writeln!(Console::writer(), \"error while reading magnetometer\").unwrap(),\n        }\n\n        match gyroscope_data {\n            Ok(data) => {\n                writeln!(\n                    Console::writer(),\n                    \"Gyroscope: x: {}, y: {}, z: {}\",\n                    data.x,\n                    data.y,\n                    data.z\n                )\n                .unwrap();\n            }\n            Err(_) => writeln!(Console::writer(), \"error while reading gyroscope\").unwrap(),\n        }\n        Alarm::sleep_for(Milliseconds(700)).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/proximity.rs",
    "content": "//! A simple libtock-rs example. Checks for proximity driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Console;\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::proximity::Proximity;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x200}\n\nfn main() {\n    if Proximity::exists().is_err() {\n        writeln!(Console::writer(), \"proximity driver unavailable\").unwrap();\n        return;\n    }\n    writeln!(Console::writer(), \"proximity driver available\").unwrap();\n    loop {\n        match Proximity::read_sync() {\n            Ok(prox_val) => writeln!(Console::writer(), \"Proximity: {prox_val}\\n\").unwrap(),\n            Err(_) => writeln!(Console::writer(), \"error while reading proximity\",).unwrap(),\n        }\n\n        Alarm::sleep_for(Milliseconds(2000)).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/rng.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::console::Console;\nuse libtock::rng::Rng;\nuse libtock::runtime::{set_main, stack_size};\n\nstack_size! {0x300}\nset_main! {main}\n\nstruct Randomness<'a, const N: usize>(&'a [u8; N]);\n\nimpl<'a, const N: usize> core::fmt::Display for Randomness<'a, N> {\n    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n        let bytes = self.0.iter();\n        for &byte in bytes {\n            write!(f, \"{byte:02x}\")?;\n        }\n        Ok(())\n    }\n}\n\nfn main() {\n    if let Err(e) = Rng::exists() {\n        writeln!(Console::writer(), \"RNG DRIVER ERROR: {e:?}\").unwrap();\n        return;\n    }\n\n    let mut console_writer = Console::writer();\n    let mut buffer: [u8; 32] = Default::default();\n    let n: u32 = 32;\n\n    loop {\n        match Rng::get_bytes_sync(&mut buffer, n) {\n            Ok(()) => {\n                let _ = writeln!(console_writer, \"Randomness: {}\", Randomness(&buffer));\n            }\n            Err(e) => {\n                let _ = writeln!(console_writer, \"Error while getting bytes {e:?}\");\n            }\n        }\n        let _ = Alarm::sleep_for(Milliseconds(2000));\n    }\n}\n"
  },
  {
    "path": "examples/rng_async.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse core::fmt::Write;\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::rng::RngListener;\nuse libtock::{console::Console, rng::Rng};\nuse libtock_platform::{share, Syscalls};\nuse libtock_runtime::{set_main, stack_size, TockSyscalls};\n\nstack_size! {0x300}\nset_main! {main}\n\nfn main() {\n    if let Err(e) = Rng::exists() {\n        writeln!(Console::writer(), \"RNG DRIVER ERROR: {e:?}\").unwrap();\n        return;\n    }\n\n    let mut console_writer = Console::writer();\n    let rng_listener = RngListener(|_| write!(Console::writer(), \"Randomness: \").unwrap());\n    let mut buffer: [u8; 32] = Default::default();\n    let n: u32 = 32;\n\n    loop {\n        share::scope(|allow_rw| {\n            Rng::allow_buffer(&mut buffer, allow_rw).unwrap();\n\n            share::scope(|subscribe| {\n                Rng::register_listener(&rng_listener, subscribe).unwrap();\n\n                Rng::get_bytes_async(n).unwrap();\n                TockSyscalls::yield_wait();\n            });\n        });\n\n        buffer.iter().for_each(|&byte| {\n            let _ = write!(console_writer, \"{byte:02x}\");\n        });\n        let _ = writeln!(console_writer);\n\n        let _ = Alarm::sleep_for(Milliseconds(2000));\n    }\n}\n"
  },
  {
    "path": "examples/screen.rs",
    "content": "#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::alarm::Alarm;\nuse libtock::alarm::Milliseconds;\nuse libtock::console::Console;\nuse libtock::display::Screen;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {11*1024}\n\nfn main() {\n    // Output a message to the console\n    let _ = writeln!(Console::writer(), \"available resolutions\\n\");\n\n    // Query the number of supported Screen resolution modes\n    let resolutions = match Screen::get_resolution_modes_count() {\n        Ok(val) => val,\n        Err(e) => {\n            let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            0\n        }\n    };\n\n    // Exit if no resolutions found\n    if resolutions == 0 {\n        assert_eq!(0, 1);\n    }\n\n    let _ = writeln!(Console::writer(), \"{resolutions}\\n\");\n\n    // Iterate over each resolution mode and print the width and height\n    for index in 0..resolutions {\n        let (width, height) = match Screen::get_resolution_width_height(index as usize) {\n            Ok((width, height)) => (width, height),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n                (0, 0)\n            }\n        };\n\n        let width = (width, height).0;\n        let height = (width, height).1;\n\n        // Abort if invalid resolution\n        if width == 0 && height == 0 {\n            assert_eq!(0, 1);\n        }\n\n        let _ = writeln!(Console::writer(), \" {width} x {height} \\n\");\n    }\n\n    // Print supported color depths\n    let _ = writeln!(Console::writer(), \"available colors depths\\n\");\n\n    let pixel_format = match Screen::get_pixel_format() {\n        Ok(val) => val,\n        Err(e) => {\n            let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            0\n        }\n    };\n\n    if pixel_format == 0 {\n        assert_eq!(0, 1);\n    }\n\n    // List each supported color format\n    for index in 0..pixel_format {\n        let format = match Screen::pixel_format(index as usize) {\n            Ok(val) => val,\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n                0\n            }\n        };\n        let _ = writeln!(Console::writer(), \"  {format} bpp\\n\");\n    }\n\n    const BUFFER_SIZE: usize = 10 * 1024;\n\n    // Initialize the Screen screen buffer\n    let mut buffer = [0u8; BUFFER_SIZE];\n\n    // Set Screen brightness to 100%\n    match Screen::set_brightness(100) {\n        Ok(()) => (),\n        Err(e) => {\n            let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n        }\n    };\n\n    // Get current screen resolution\n    let (width, height) = match Screen::get_resolution() {\n        Ok((width, height)) => (width, height),\n        Err(e) => {\n            let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            (0, 0)\n        }\n    };\n\n    // Unwrap width and height\n    let width = (width, height).0;\n    let height = (width, height).1;\n\n    if width == 0 && height == 0 {\n        assert_eq!(0, 1);\n    };\n\n    // Set full-screen write frame and clear screen\n    match Screen::set_write_frame(0, 0, width, height) {\n        Ok(()) => (),\n        Err(e) => {\n            let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n        }\n    };\n    match Screen::fill(&mut buffer, 0x0) {\n        Ok(()) => (),\n        Err(e) => {\n            let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n        }\n    };\n\n    // Animation loop: cycle through rotations and color block updates\n    let mut invert = false;\n    for i in 0.. {\n        // Every 4 iterations, toggle Screen inversion\n        if i % 4 == 3 {\n            invert = !invert;\n            if invert {\n                let _ = Screen::set_invert_on();\n            } else {\n                let _ = Screen::set_invert_off();\n            }\n        }\n\n        // Set Screen rotation (0 to 3)\n        match Screen::set_rotation(i % 4) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n\n        // Draw a red square at (10, 20)\n        match Screen::set_write_frame(10, 20, 30, 30) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n        match Screen::fill(&mut buffer, 0xF800) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n\n        // Draw a black square at (88, 20)\n        match Screen::set_write_frame(88, 20, 30, 30) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n        match Screen::fill(&mut buffer, 0x0) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n\n        // Wait 1 second\n        Alarm::sleep_for(Milliseconds(1000)).unwrap();\n\n        // Clear the red square\n        match Screen::set_write_frame(10, 20, 30, 30) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n        match Screen::fill(&mut buffer, 0x0) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n\n        // Draw a green square at (88, 20)\n        match Screen::set_write_frame(88, 20, 30, 30) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n        match Screen::fill(&mut buffer, 0x07F0) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n\n        // Wait 1 second\n        Alarm::sleep_for(Milliseconds(1000)).unwrap();\n\n        // Clear screen\n        match Screen::set_write_frame(0, 0, width, height) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n        match Screen::fill(&mut buffer, 0x0) {\n            Ok(()) => (),\n            Err(e) => {\n                let _ = writeln!(Console::writer(), \"{e:?}\\n\");\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "examples/sound_pressure.rs",
    "content": "//! This example shows how to use the sound pressure driver.\n//! It checks for the sound pressure driver and samples the sensor every second.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Console;\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::runtime::{set_main, stack_size};\nuse libtock::sound_pressure::SoundPressure;\n\nset_main! {main}\nstack_size! {0x200}\n\nfn main() {\n    if SoundPressure::exists().is_err() {\n        writeln!(Console::writer(), \"Sound pressure driver not found\").unwrap();\n        return;\n    }\n\n    writeln!(Console::writer(), \"Sound pressure driver found\").unwrap();\n    let enable = SoundPressure::enable();\n    match enable {\n        Ok(()) => {\n            writeln!(Console::writer(), \"Sound pressure driver enabled\").unwrap();\n            loop {\n                match SoundPressure::read_sync() {\n                    Ok(sound_pressure_val) => {\n                        writeln!(Console::writer(), \"Sound Pressure: {sound_pressure_val}\\n\")\n                            .unwrap()\n                    }\n                    Err(_) => {\n                        writeln!(Console::writer(), \"error while reading sound pressure\",).unwrap()\n                    }\n                }\n                Alarm::sleep_for(Milliseconds(1000)).unwrap();\n            }\n        }\n        Err(_e) => writeln!(Console::writer(), \"Sound pressure driver enable failed\",).unwrap(),\n    }\n}\n"
  },
  {
    "path": "examples/spi_controller_write_read.rs",
    "content": "//! This sample demonstrates setting up the SPI controller (assuming board has support)\n\n#![no_main]\n#![no_std]\nuse core::fmt::Write;\nuse libtock::console::Console;\nuse libtock::runtime::{set_main, stack_size};\nuse libtock::spi_controller::SpiController;\n\nset_main! {main}\nstack_size! {0x400}\n\nconst OPERATION_LEN: usize = 0x08;\n\nfn main() {\n    let tx_buf: [u8; OPERATION_LEN] = [0x12; OPERATION_LEN];\n    let mut rx_buf: [u8; OPERATION_LEN] = [0; OPERATION_LEN];\n\n    writeln!(Console::writer(), \"spi-controller: write-read\\r\").unwrap();\n    if let Err(why) =\n        SpiController::spi_controller_write_read_sync(&tx_buf, &mut rx_buf, OPERATION_LEN as u32)\n    {\n        writeln!(\n            Console::writer(),\n            \"spi-controller: write-read operation failed {why:?}\\r\"\n        )\n        .unwrap();\n    } else {\n        writeln!(\n            Console::writer(),\n            \"spi-controller: write-read: wrote {tx_buf:x?}: read {rx_buf:x?}\\r\"\n        )\n        .unwrap();\n    }\n\n    writeln!(Console::writer(), \"spi-controller: write\\r\").unwrap();\n    if let Err(why) = SpiController::spi_controller_write_sync(&tx_buf, OPERATION_LEN as u32) {\n        writeln!(\n            Console::writer(),\n            \"spi-controller: write operation failed {why:?}\\r\"\n        )\n        .unwrap();\n    } else {\n        writeln!(Console::writer(), \"spi-controller: wrote {tx_buf:x?}\\r\").unwrap();\n    }\n\n    writeln!(Console::writer(), \"spi-controller: read\\r\").unwrap();\n    if let Err(why) = SpiController::spi_controller_read_sync(&mut rx_buf, OPERATION_LEN as u32) {\n        writeln!(\n            Console::writer(),\n            \"spi-controller: read operation failed {why:?}\\r\"\n        )\n        .unwrap();\n    } else {\n        writeln!(Console::writer(), \"spi-controller: read {rx_buf:x?}\\r\").unwrap();\n    }\n\n    writeln!(Console::writer(), \"spi-controller: inplace write-read\\r\").unwrap();\n    if let Err(why) =\n        SpiController::spi_controller_inplace_write_read_sync(&mut rx_buf, OPERATION_LEN as u32)\n    {\n        writeln!(\n            Console::writer(),\n            \"spi-controller: inplace write-read operation failed {why:?}\\r\"\n        )\n        .unwrap();\n    } else {\n        writeln!(\n            Console::writer(),\n            \"spi-controller: inplace write-read: wrote {tx_buf:x?}: read {rx_buf:x?}\\r\"\n        )\n        .unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/temperature.rs",
    "content": "//! A simple libtock-rs example. Checks for temperature driver\n//! and samples the sensor every 2 seconds.\n\n#![no_main]\n#![no_std]\n\nuse core::fmt::Write;\nuse libtock::console::Console;\n\nuse libtock::alarm::{Alarm, Milliseconds};\nuse libtock::runtime::{set_main, stack_size};\nuse libtock::temperature::Temperature;\n\nset_main! {main}\nstack_size! {0x200}\n\nfn main() {\n    match Temperature::exists() {\n        Ok(()) => writeln!(Console::writer(), \"temperature driver available\").unwrap(),\n        Err(_) => {\n            writeln!(Console::writer(), \"temperature driver unavailable\").unwrap();\n            return;\n        }\n    }\n\n    loop {\n        match Temperature::read_temperature_sync() {\n            Ok(temp_val) => writeln!(\n                Console::writer(),\n                \"Temperature: {}{}.{}*C\\n\",\n                if temp_val > 0 { \"\" } else { \"-\" },\n                i32::abs(temp_val) / 100,\n                i32::abs(temp_val) % 100\n            )\n            .unwrap(),\n            Err(_) => writeln!(Console::writer(), \"error while reading temperature\",).unwrap(),\n        }\n\n        Alarm::sleep_for(Milliseconds(2000)).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/usb_i2c_mctp.rs",
    "content": "//! A sample app that implements MCTP messages to be transceived from a host\n//! machine without exposed SMBus/I2C capabilities to a target endpoint using\n//! UART and I2C.\n//!\n//! The following topology is used:\n//!\n//! [HOST MACHINE] <--UART--> [USB_I2C_BRIDGE_DEVICE] <--I2C/SmBus--> [TARGET_ENDPOiNT]\n//!\n//! The host machine will issue a message to the USB_I2C_BRIDGE_DEVICE, which runs this app.\n//! The app then determines the end point target address based on the received packet header,\n//! and forwards this data to the target endpoint. As we are supporting MCTP, there are no\n//! I2C reads, only write. Thus, the endpoint must then master the bus and write a response\n//! back. This message is forwarded to the host again via UART.\n//!\n//! The host application must append a small packet header of the following format\n//! for any messages being send to this device.\n//!\n//! host_tx[0] = 0xAA // Preamble\n//! host_tx[1] = XX   // Endpoint target address\n//! host_tx[2] = YY   // MSB of 16bit data length\n//! host_tx[3] = ZZ   // LSB of 16bit data length\n//!\n//! For reception, the device (this app) first sends a packet header of the following format\n//!\n//! device_tx[0] = 0xBB // Preamble\n//! device_tx[1] = 0xFF // Unused\n//! device_tx[2] = YY   // MSB of 16bit data length\n//! device_tx[3] = ZZ   // LSB of 16bit data length\n//!\n//! Based on the data length, the host can read the next ((YY << 8) | ZZ )\n//! as data message.\n//!\n//! Required Kernel Configuration:\n//!\n//! This application requires that the kernel console buffer sizes are increased\n//! as well as i2c-master-slave driver buffers. This is because we are doing transfers\n//! of sizes greater than what the upstream kernel is allowed to do.\n//!\n//! The following reference can be used to prepare the kernel for the uart/console buffers.\n//! The size specified here must be >= RX_BUF_LEN (as specified below).\n//!\n//! ```\n//! diff --git a/capsules/core/src/console.rs b/capsules/core/src/console.rs\n//! index a3b3af6cf..4eaf401a9 100644\n//! --- a/capsules/core/src/console.rs\n//! +++ b/capsules/core/src/console.rs\n//! @@ -54,7 +54,7 @@ pub const DRIVER_NUM: usize = driver::NUM::Console as usize;\n//!\n//!  /// Default size for the read and write buffers used by the console.\n//!  /// Boards may pass different-size buffers if needed.\n//! -pub const DEFAULT_BUF_SIZE: usize = 64;\n//! +pub const DEFAULT_BUF_SIZE: usize = 132;\n//!\n//!  /// IDs for subscribed upcalls.\n//!  mod upcall {\n//! ```\n//!\n//! ```\n//! diff --git a/capsules/core/src/virtualizers/virtual_uart.rs b/capsules/core/src/virtualizers/virtual_uart.rs\n//! index 0d39fe024..59e0435a1 100644\n//! --- a/capsules/core/src/virtualizers/virtual_uart.rs\n//! +++ b/capsules/core/src/virtualizers/virtual_uart.rs\n//! @@ -54,7 +54,7 @@ use kernel::hil::uart;\n//!  use kernel::utilities::cells::{OptionalCell, TakeCell};\n//!  use kernel::ErrorCode;\n//!\n//! -pub const RX_BUF_LEN: usize = 64;\n//! +pub const RX_BUF_LEN: usize = 132;\n//!\n//!  pub struct MuxUart<'a> {\n//!      uart: &'a dyn uart::Uart<'a>,\n//! ```\n//!\n//! For i2c-master-slave buffers, use a buffer size that is >= MAX_DLEN\n//! (as specified below).\n//!\n\n#![no_main]\n#![no_std]\nuse libtock::console::Console;\nuse libtock::i2c_master_slave::I2CMasterSlave;\nuse libtock::leds::Leds;\nuse libtock::runtime::{set_main, stack_size};\n\nset_main! {main}\nstack_size! {0x900}\n\n/// The address to which we listen for in slave/target mode.\npub const MY_ID: u8 = 0x34;\n/// Contains packet metadata\npub const HEADER_LEN: usize = 4;\n/// Max data message length\npub const MAX_DLEN: usize = 128;\n/// Total amount of bytes we can receive in a single UART RX\npub const RX_BUF_LEN: usize = HEADER_LEN + MAX_DLEN;\n/// Debug LED config, change these based on the board config\npub const PANIC_LED: u32 = 0;\n/// Triggered when waiting for RX\npub const RX_LED: u32 = 1;\n/// Triggered when TX in progress\npub const TX_LED: u32 = 2;\n\n/// # Summary\n///\n/// A helper function to append the packet metadata do the outgoing buffer\n/// pointed to by @buf.\n///\n/// # Parameter\n///\n/// * `buf`: the buffer in which to append the metadata to.\n/// * `n_bytes`: length of data message body of the next message this is\n///              stored in the packet header, so that the host can\n///              determine the data message read length.\n///\n/// # Returns\n///\n/// Ok(n) returns the total size of bytes to send from this buffer (buf[0..n]).\n///\n/// # Panics\n///\n/// If the buffer capacity cannot fit the packet metadata\n///\nfn prepare_tx_header(buf: &mut [u8], n_bytes: usize) -> Result<usize, ()> {\n    let total_bytes_to_send = HEADER_LEN;\n    if total_bytes_to_send > buf.len() {\n        return Err(());\n    }\n    // Setup Header\n    buf[0] = 0xBB;\n    buf[1] = 0xFF;\n    // Upper 8-bits\n    buf[2..=3].copy_from_slice(&u16::to_be_bytes(n_bytes as u16));\n\n    Ok(total_bytes_to_send)\n}\n\nfn main() {\n    let led_count = Leds::count().unwrap_or(0);\n\n    // Using the led number, set it on iff it's available\n    let led_on = |led_num| {\n        if led_num < led_count {\n            Leds::on(led_num).unwrap()\n        }\n    };\n\n    // Using the led number, set it off iff it's available\n    let led_off = |led_num| {\n        if led_num < led_count {\n            Leds::off(led_num).unwrap()\n        }\n    };\n\n    // RX Buffer layout\n    // [0] = Preamble\n    // [1] = TargetID\n    // [2] = Length Upper Byte\n    // [3] = Length Lower Byte\n    let mut rx_buf: [u8; RX_BUF_LEN] = [0x00; RX_BUF_LEN];\n    let mut msg_len: u16;\n    let mut target_id: u16;\n\n    loop {\n        led_on(RX_LED);\n        let (_, err) = Console::read(&mut rx_buf);\n        led_off(RX_LED);\n\n        if err.is_err() {\n            led_on(PANIC_LED);\n            panic!(\"Failed to read from host {:?}\", err);\n        }\n        // If we don't get a matching preamble, then the rest of the data is unreliable.\n        assert_eq!(rx_buf[0], 0xAA);\n        // Target in 7-bit address range?\n        assert!(rx_buf[1] <= 0x7F);\n        target_id = rx_buf[1] as u16;\n        // Data length should be non-zero, otherwise why are we here? just to suffer?\n        msg_len = u16::from_be_bytes([rx_buf[2], rx_buf[3]]);\n        assert!(msg_len as usize <= MAX_DLEN);\n        assert_ne!(msg_len, 0);\n\n        if let Err(why) = I2CMasterSlave::i2c_master_slave_write_sync(\n            target_id,\n            &mut rx_buf[HEADER_LEN..HEADER_LEN + msg_len as usize],\n            msg_len,\n        ) {\n            led_on(PANIC_LED);\n            panic!(\"i2c-master: write operation failed {:?}\", why);\n        }\n\n        I2CMasterSlave::i2c_master_slave_set_slave_address(MY_ID)\n            .expect(\"i2c-target: Failed to set slave address\");\n\n        // Expect a write, if the master reads here, the IP may stretch clocks!\n        let r = I2CMasterSlave::i2c_master_slave_write_recv_sync(&mut rx_buf[HEADER_LEN..]);\n\n        if let Err(why) = r.1 {\n            led_on(PANIC_LED);\n            panic!(\"i2c-slave: error to receiving data {:?}\\r\", why);\n        }\n        let mut header: [u8; HEADER_LEN] = [0; HEADER_LEN];\n        let mut tx_len = 0;\n        if let Ok(n) = prepare_tx_header(&mut header, r.0) {\n            tx_len = n;\n        }\n        assert_eq!(tx_len, HEADER_LEN);\n\n        // Write header first, this allows the host to know how many bytes to\n        // expect in the following data message.\n        led_on(TX_LED);\n        if Console::write(&mut header).is_err() {\n            led_on(PANIC_LED);\n        }\n\n        // Data message body.\n        if Console::write(&mut rx_buf[HEADER_LEN..HEADER_LEN + r.0]).is_err() {\n            led_on(PANIC_LED);\n        }\n        led_off(TX_LED);\n    }\n}\n"
  },
  {
    "path": "libraries/embedded_graphics_libtock/Cargo.toml",
    "content": "[package]\nname = \"embedded_graphics_libtock\"\nversion = \"0.1.0\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nlicense = \"Apache-2.0 OR MIT\"\nedition = \"2018\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\ndescription = \"libtock-rs port of embedded graphics\"\n\n[dependencies]\nembedded-graphics = \"0.8.1\"\n\nlibtock = { path = \"../../\" }\nlibtock_platform = { path = \"../../platform\" }"
  },
  {
    "path": "libraries/embedded_graphics_libtock/README.md",
    "content": "Embedded Graphics - Libtock\n===========================\n\nThis crate connects the\n[Embedded Graphics library](https://crates.io/crates/embedded-graphics) to\nlibtock-rs. Specifically, this implements the\n[DrawTarget trait](https://docs.rs/embedded-graphics/latest/embedded_graphics/draw_target/trait.DrawTarget.html)\nusing the Tock `screen` systemcall.\n"
  },
  {
    "path": "libraries/embedded_graphics_libtock/src/lib.rs",
    "content": "//! Interface library for using Embedded Graphics with libtock-rs\n//!\n//! This library implements `embedded_graphics::draw_target::DrawTarget` from\n//! the [Embedded Graphics](https://crates.io/crates/embedded-graphics) graphics\n//! library using the screen system call driver in Tock.\n//!\n//! ## Example Usage\n//!\n//! Using Embedded Graphics to draw a circle on the screen might look like:DrawTarget\n//!\n//! ```rust\n//! use embedded_graphics_libtock::tock_screen::TockMonochrome8BitPage128x64Screen;\n//!\n//! use embedded_graphics::pixelcolor::BinaryColor;\n//! use embedded_graphics::prelude::Point;\n//! use embedded_graphics::primitives::{Circle, PrimitiveStyle};\n//!\n//! let mut screen = TockMonochrome8BitPage128x64Screen::new();\n//!\n//! let x = 50;\n//! let y = 50;\n//! let diameter = 40;\n//! let _ = Circle::new(Point::new(x as i32, y as i32), diameter)\n//!     .into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))\n//!     .draw(&mut screen);\n//! }\n//! let _ = screen.flush();\n//! ```\n\n#![no_std]\n\npub mod tock_screen;\n"
  },
  {
    "path": "libraries/embedded_graphics_libtock/src/tock_screen.rs",
    "content": "//! Implementations of `DrawTarget` using the screen system call.\n\nuse libtock::display::Screen;\nuse libtock_platform::ErrorCode;\n\n/// An implementation of a `DrawTarget` for monochromatic, 128x64 pixel screens\n/// where the pixels in each byte are vertical on the screen.\n///\n/// This corresponds to the `Mono_8BitPage` pixel format documented\n/// [here](https://github.com/tock/tock/blob/master/doc/syscalls/90001_screen.md#command-number-25).\npub struct TockMonochrome8BitPage128x64Screen {\n    /// The framebuffer for the max supported screen size (128x64). Each pixel\n    /// is a bit.\n    framebuffer: [u8; (128 * 64) / 8],\n    width: u32,\n    height: u32,\n}\n\nimpl Default for TockMonochrome8BitPage128x64Screen {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl TockMonochrome8BitPage128x64Screen {\n    pub fn new() -> Self {\n        let (width, height) = Screen::get_resolution().unwrap_or((0, 0));\n\n        // Because this is a specific type of screen with a specific pixel\n        // format, we tell the kernel that is the pixel format we expect.\n        let mono_8_bit_page = 6;\n        let _ = Screen::set_pixel_format(mono_8_bit_page);\n\n        Self {\n            framebuffer: [0; 1024],\n            width,\n            height,\n        }\n    }\n\n    pub fn get_width(&self) -> u32 {\n        self.width\n    }\n\n    pub fn get_height(&self) -> u32 {\n        self.height\n    }\n\n    /// Updates the screen from the framebuffer.\n    pub fn flush(&self) -> Result<(), ErrorCode> {\n        Screen::set_write_frame(0, 0, self.width, self.height)?;\n        Screen::write(&self.framebuffer)?;\n        Ok(())\n    }\n}\n\nimpl embedded_graphics::draw_target::DrawTarget for TockMonochrome8BitPage128x64Screen {\n    type Color = embedded_graphics::pixelcolor::BinaryColor;\n    type Error = core::convert::Infallible;\n\n    fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>\n    where\n        I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,\n    {\n        for embedded_graphics::Pixel(coord, color) in pixels.into_iter() {\n            if coord.x >= 0\n                && coord.x < self.width as i32\n                && coord.y >= 0\n                && coord.y < self.height as i32\n            {\n                const X_FACTOR: usize = 1;\n                const Y_FACTOR: usize = 8;\n                const X_COLS: usize = 128;\n\n                let x = coord.x as usize;\n                let y = coord.y as usize;\n\n                let byte_index = (x / X_FACTOR) + ((y / Y_FACTOR) * X_COLS);\n                let bit_index = y % Y_FACTOR;\n\n                if color.is_on() {\n                    self.framebuffer[byte_index] |= 1 << bit_index;\n                } else {\n                    self.framebuffer[byte_index] &= !(1 << bit_index);\n                }\n            }\n        }\n\n        Ok(())\n    }\n}\n\nimpl embedded_graphics::geometry::OriginDimensions for TockMonochrome8BitPage128x64Screen {\n    fn size(&self) -> embedded_graphics::geometry::Size {\n        embedded_graphics::geometry::Size::new(128, 64)\n    }\n}\n"
  },
  {
    "path": "nightly/rust-toolchain.toml",
    "content": "# This is the nightly Rust toolchain used by `make test`.\n[toolchain]\nchannel = \"nightly-2025-09-11\"\ncomponents = [\"miri\", \"rust-src\"]\n"
  },
  {
    "path": "panic_handlers/debug_panic/Cargo.toml",
    "content": "[package]\nname = \"libtock_debug_panic\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nversion = \"0.1.0\"\ndescription = \"\"\"Debug panic handler for libtock. Prints panic info to console and terminates.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\n\n[dependencies]\nlibtock_console = { path = \"../../apis/interface/console\" }\nlibtock_low_level_debug = { path = \"../../apis/kernel/low_level_debug\" }\nlibtock_platform = { path = \"../../platform\" }\nlibtock_runtime = { path = \"../../runtime\" }\n"
  },
  {
    "path": "panic_handlers/debug_panic/src/lib.rs",
    "content": "#![no_std]\nuse core::fmt::Write;\nuse libtock_console::Console;\nuse libtock_low_level_debug::{AlertCode, LowLevelDebug};\nuse libtock_platform::{ErrorCode, Syscalls};\nuse libtock_runtime::TockSyscalls;\n\n/// This handler requires some 0x400 bytes of stack\n#[panic_handler]\nfn panic_handler(info: &core::panic::PanicInfo) -> ! {\n    // Signal a panic using the LowLevelDebug capsule (if available).\n    LowLevelDebug::<TockSyscalls>::print_alert_code(AlertCode::Panic);\n\n    let mut writer = Console::<TockSyscalls>::writer();\n    // If this printing fails, we can't panic harder, and we can't print it either.\n    let _ = writeln!(writer, \"{info}\");\n    // Exit with a non-zero exit code to indicate failure.\n    TockSyscalls::exit_terminate(ErrorCode::Fail as u32);\n}\n"
  },
  {
    "path": "panic_handlers/small_panic/Cargo.toml",
    "content": "[package]\nname = \"libtock_small_panic\"\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nversion = \"0.1.0\"\ndescription = \"\"\"Small and basic panic handler for libtock. Calls low-level debug on panic and terminates.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\n\n[dependencies]\nlibtock_low_level_debug = { path = \"../../apis/kernel/low_level_debug\" }\nlibtock_platform = { path = \"../../platform\" }\nlibtock_runtime = { path = \"../../runtime\" }\n"
  },
  {
    "path": "panic_handlers/small_panic/src/lib.rs",
    "content": "#![no_std]\n\nuse libtock_low_level_debug::{AlertCode, LowLevelDebug};\nuse libtock_platform::{ErrorCode, Syscalls};\nuse libtock_runtime::TockSyscalls;\n\n#[panic_handler]\nfn panic_handler(_info: &core::panic::PanicInfo) -> ! {\n    // Signal a panic using the LowLevelDebug capsule (if available).\n    LowLevelDebug::<TockSyscalls>::print_alert_code(AlertCode::Panic);\n\n    // Exit with a non-zero exit code to indicate failure.\n    // TODO(kupiakos@google.com): Make this logic consistent with tock/tock#2914\n    // when it is merged.\n    TockSyscalls::exit_terminate(ErrorCode::Fail as u32);\n}\n"
  },
  {
    "path": "platform/Cargo.toml",
    "content": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\ndescription = \"\"\"libtock-rs platform layer. Provides the Platform abstraction,\n                 an abstraction that extends Tock's system calls to form the\n                 basis for libtock-rs' asynchronous APIs. libtock_platform is\n                 intended for use in both TBF binaries and unit tests that run\n                 on Linux.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nname = \"libtock_platform\"\nrepository = \"https://www.github.com/tock/libtock/rs\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[features]\nrust_embedded = [\"embedded-hal\"]\n\n[dependencies]\nembedded-hal = { version = \"1.0\", optional = true }\n"
  },
  {
    "path": "platform/src/allow_ro.rs",
    "content": "use crate::share::List;\nuse crate::Syscalls;\nuse core::marker::PhantomData;\n\n// -----------------------------------------------------------------------------\n// `AllowRo` struct\n// -----------------------------------------------------------------------------\n\n/// A `share::Handle<AllowRo>` instance allows safe code to call Tock's\n/// Read-Only Allow system call, by guaranteeing the buffer will be revoked\n/// before 'share ends. It is intended for use with the `share::scope` function,\n/// which offers a safe interface for constructing `share::Handle<AllowRo>`\n/// instances.\npub struct AllowRo<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> {\n    _syscalls: PhantomData<S>,\n\n    // Make this struct invariant with respect to the 'share lifetime.\n    //\n    // If AllowRo were covariant with respect to 'share, then an\n    // `AllowRo<'static, ...>` could be used to share a buffer that has a\n    // shorter lifetime. The capsule would still have access to the memory after\n    // the buffer is deallocated and the memory re-used (e.g. if the buffer is\n    // on the stack), likely leaking data the process binary does not want to\n    // share. Therefore, AllowRo cannot be covariant with respect to 'share.\n    // Contravariance would not have this issue, but would still be confusing\n    // and would be unexpected.\n    //\n    // Additionally, this makes AllowRo !Sync, which is probably desirable, as\n    // Sync would allow for races between threads sharing buffers with the\n    // kernel.\n    _share: PhantomData<core::cell::Cell<&'share [u8]>>,\n}\n\n// We can't derive(Default) because S is not Default, and derive(Default)\n// generates a Default implementation that requires S to be Default. Instead, we\n// manually implement Default.\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Default\n    for AllowRo<'share, S, DRIVER_NUM, BUFFER_NUM>\n{\n    fn default() -> Self {\n        Self {\n            _syscalls: PhantomData,\n            _share: PhantomData,\n        }\n    }\n}\n\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Drop\n    for AllowRo<'share, S, DRIVER_NUM, BUFFER_NUM>\n{\n    fn drop(&mut self) {\n        S::unallow_ro(DRIVER_NUM, BUFFER_NUM);\n    }\n}\n\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> List\n    for AllowRo<'share, S, DRIVER_NUM, BUFFER_NUM>\n{\n}\n\n// -----------------------------------------------------------------------------\n// `Config` trait\n// -----------------------------------------------------------------------------\n\n/// `Config` configures the behavior of the Read-Only Allow system call. It\n/// should generally be passed through by drivers, to allow application code to\n/// configure error handling.\npub trait Config {\n    /// Called if a Read-Only Allow call succeeds and returns a non-zero buffer.\n    /// In some applications, this may indicate unexpected reentrance. By\n    /// default, the non-zero buffer is ignored.\n    fn returned_nonzero_buffer(_driver_num: u32, _buffer_num: u32) {}\n}\n"
  },
  {
    "path": "platform/src/allow_rw.rs",
    "content": "use crate::share::List;\nuse crate::Syscalls;\nuse core::marker::PhantomData;\n\n// -----------------------------------------------------------------------------\n// `AllowRw` struct\n// -----------------------------------------------------------------------------\n\n/// A `share::Handle<AllowRw>` instance allows safe code to call Tock's\n/// Read-Write Allow system call, by guaranteeing the buffer will be revoked\n/// before 'share ends. It is intended for use with the `share::scope` function,\n/// which offers a safe interface for constructing `share::Handle<AllowRw>`\n/// instances.\npub struct AllowRw<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> {\n    _syscalls: PhantomData<S>,\n\n    // Make this struct invariant with respect to the 'share lifetime.\n    //\n    // If AllowRw were covariant with respect to 'share, then an\n    // `AllowRw<'static, ...>` could be used to share a buffer that has a\n    // shorter lifetime. The capsule would still have access to the memory after\n    // the buffer is deallocated and the memory re-used (e.g. if the buffer is\n    // on the stack), allowing it to cause undefined behavior in the process.\n    // Therefore, AllowRw cannot be covariant with respect to 'share.\n    // Contravariance would not have this issue, but would still be confusing\n    // and would be unexpected.\n    //\n    // Additionally, this makes AllowRw !Sync, which is probably desirable, as\n    // Sync would allow for races between threads sharing buffers with the\n    // kernel.\n    _share: PhantomData<core::cell::Cell<&'share mut [u8]>>,\n}\n\n// We can't derive(Default) because S is not Default, and derive(Default)\n// generates a Default implementation that requires S to be Default. Instead, we\n// manually implement Default.\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Default\n    for AllowRw<'share, S, DRIVER_NUM, BUFFER_NUM>\n{\n    fn default() -> Self {\n        Self {\n            _syscalls: PhantomData,\n            _share: PhantomData,\n        }\n    }\n}\n\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> Drop\n    for AllowRw<'share, S, DRIVER_NUM, BUFFER_NUM>\n{\n    fn drop(&mut self) {\n        S::unallow_rw(DRIVER_NUM, BUFFER_NUM);\n    }\n}\n\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const BUFFER_NUM: u32> List\n    for AllowRw<'share, S, DRIVER_NUM, BUFFER_NUM>\n{\n}\n\n// -----------------------------------------------------------------------------\n// `Config` trait\n// -----------------------------------------------------------------------------\n\n/// `Config` configures the behavior of the Read-Write Allow system call. It\n/// should generally be passed through by drivers, to allow application code to\n/// configure error handling.\npub trait Config {\n    /// Called if a Read-Write Allow call succeeds and returns a non-zero\n    /// buffer. In some applications, this may indicate unexpected reentrance.\n    /// By default, the non-zero buffer is ignored.\n    fn returned_nonzero_buffer(_driver_num: u32, _buffer_num: u32) {}\n}\n"
  },
  {
    "path": "platform/src/command_return.rs",
    "content": "use crate::{return_variant, ErrorCode, ReturnVariant};\n\nuse core::mem::transmute;\n\n/// The response type from the [`command`](crate::Syscalls::command) syscall.\n/// Can represent a success or a failure with or without associated data.\n///\n/// After a syscall is made, registers `r1`-`r3` contain the output as\n/// described by [TRD 104][trd-104]. Some syscalls only return success/failure,\n/// while others provide associated data. This is done by placing the _return\n/// variant_ in `r0`, which specifies how the output registers should be\n/// interpreted. For syscalls other than `command`, the possible output\n/// variants are fixed; you always know which variants are expected given the\n/// syscall class.\n///\n/// However, the `command` syscall is flexible - there must be one success\n/// variant and one failure variant for a given driver/command ID, but\n/// which variants those are, and what data is expected, cannot be checked\n/// statically. Capsules and userspace APIs must agree on the expected\n/// variants for success and failure.\n///\n/// # Example\n///\n/// This uses the [`to_result`] method to implicitly check variants and convert\n/// to a `Result`.\n///\n/// ```ignore\n/// let res: Result<(u32, u32), ErrorCode> = Syscalls::command(314, 1, 1, 2).to_result();\n/// match res {\n///     Ok((val1, val2)) => {\n///         // Success with associated data in val1, val2.\n///     }\n///     Err(ErrorCode::BadRVal) => {\n///         // Incorrect return variant! We may choose to handle this\n///         // explicitly or propagate upwards without branching.\n///     }\n///     Err(ec) => {\n///         // The driver returned an error (or it doesn't exist).\n///     }\n/// }\n/// ```\n///\n/// This uses the `get_*` methods to check the variants explicitly and extract\n/// the associated data.\n///\n/// ```ignore\n/// let command_return = Syscalls::command(314, 1, 1, 2);\n/// if let Some((val1, val2)) = command_return.get_success_2_u32() {\n///     // If there was a success, there is an associated data (u32, u32).\n/// } else if let Some(error_code) = command_return.get_failure() {\n///     // If there was a failure, there's no associated data and we only\n///     // have an error code.\n/// } else {\n///     // Incorrect return variant! If this occurs, your capsule and userspace\n///     // API do not agree on what the return variants should be.\n///     // An application may want to panic in this case to catch this early.\n/// }\n/// ```\n///\n/// [trd-104]: https://github.com/tock/tock/blob/master/doc/reference/trd104-syscalls.md#32-return-values\n#[must_use = \"this `CommandReturn` may represent an error, which should be handled\"]\n#[derive(Clone, Copy, Debug)]\npub struct CommandReturn {\n    return_variant: ReturnVariant,\n\n    // Safety invariant on r1: If return_variant is failure variant, r1 must be\n    // a valid ErrorCode.\n    r1: u32,\n    r2: u32,\n    r3: u32,\n}\n\nimpl CommandReturn {\n    /// # Safety\n    /// If return_variant is a failure variant, r1 must be a valid ErrorCode.\n    pub unsafe fn new(return_variant: ReturnVariant, r1: u32, r2: u32, r3: u32) -> Self {\n        CommandReturn {\n            return_variant,\n            r1,\n            r2,\n            r3,\n        }\n    }\n\n    /// Returns true if this CommandReturn is of type Failure. Note that this\n    /// does not return true for other failure types, such as Failure with u32.\n    pub fn is_failure(&self) -> bool {\n        self.return_variant == return_variant::FAILURE\n    }\n\n    /// Returns true if this CommandReturn is of type Failure with u32.\n    pub fn is_failure_u32(&self) -> bool {\n        self.return_variant == return_variant::FAILURE_U32\n    }\n\n    /// Returns true if this CommandReturn is of type Failure with 2 u32.\n    pub fn is_failure_2_u32(&self) -> bool {\n        self.return_variant == return_variant::FAILURE_2_U32\n    }\n\n    /// Returns true if this CommandReturn is of type Failure with u64.\n    pub fn is_failure_u64(&self) -> bool {\n        self.return_variant == return_variant::FAILURE_U64\n    }\n\n    /// Returns true if this CommandReturn is of type Success. Note that this\n    /// does not return true for other success types, such as Success with u32.\n    pub fn is_success(&self) -> bool {\n        self.return_variant == return_variant::SUCCESS\n    }\n\n    /// Returns true if this CommandReturn is of type Success with u32.\n    pub fn is_success_u32(&self) -> bool {\n        self.return_variant == return_variant::SUCCESS_U32\n    }\n\n    /// Returns true if this CommandReturn is of type Success with 2 u32.\n    pub fn is_success_2_u32(&self) -> bool {\n        self.return_variant == return_variant::SUCCESS_2_U32\n    }\n\n    /// Returns true if this CommandReturn is of type Success with u64.\n    pub fn is_success_u64(&self) -> bool {\n        self.return_variant == return_variant::SUCCESS_U64\n    }\n\n    /// Returns true if this CommandReturn is of type Success with 3 u32.\n    pub fn is_success_3_u32(&self) -> bool {\n        self.return_variant == return_variant::SUCCESS_3_U32\n    }\n\n    /// Returns true if this CommandReturn is of type Success with u32 and u64.\n    pub fn is_success_u32_u64(&self) -> bool {\n        self.return_variant == return_variant::SUCCESS_U32_U64\n    }\n\n    /// Returns the error code if this CommandReturn is of type Failure.\n    pub fn get_failure(&self) -> Option<ErrorCode> {\n        if !self.is_failure() {\n            return None;\n        }\n        Some(unsafe { transmute::<u32, ErrorCode>(self.r1) })\n    }\n\n    /// Returns the error code and value if this CommandReturn is of type\n    /// Failure with u32.\n    pub fn get_failure_u32(&self) -> Option<(ErrorCode, u32)> {\n        if !self.is_failure_u32() {\n            return None;\n        }\n        Some((unsafe { transmute::<u32, ErrorCode>(self.r1) }, self.r2))\n    }\n\n    /// Returns the error code and return values if this CommandReturn is of\n    /// type Failure with 2 u32.\n    pub fn get_failure_2_u32(&self) -> Option<(ErrorCode, u32, u32)> {\n        if !self.is_failure_2_u32() {\n            return None;\n        }\n        Some((\n            unsafe { transmute::<u32, ErrorCode>(self.r1) },\n            self.r2,\n            self.r3,\n        ))\n    }\n\n    /// Returns the error code and return value if this CommandReturn is of type\n    /// Failure with u64.\n    pub fn get_failure_u64(&self) -> Option<(ErrorCode, u64)> {\n        if !self.is_failure_u64() {\n            return None;\n        }\n        Some((\n            unsafe { transmute::<u32, ErrorCode>(self.r1) },\n            self.r2 as u64 + ((self.r3 as u64) << 32),\n        ))\n    }\n\n    /// Returns the value if this CommandReturn is of type Success with u32.\n    pub fn get_success_u32(&self) -> Option<u32> {\n        if !self.is_success_u32() {\n            return None;\n        }\n        Some(self.r1)\n    }\n\n    /// Returns the values if this CommandReturn is of type Success with 2 u32.\n    pub fn get_success_2_u32(&self) -> Option<(u32, u32)> {\n        if !self.is_success_2_u32() {\n            return None;\n        }\n        Some((self.r1, self.r2))\n    }\n\n    /// Returns the value if this CommandReturn is of type Success with u64.\n    pub fn get_success_u64(&self) -> Option<u64> {\n        if !self.is_success_u64() {\n            return None;\n        }\n        Some(self.r1 as u64 + ((self.r2 as u64) << 32))\n    }\n\n    /// Returns the values if this CommandReturn is of type Success with 3 u32.\n    pub fn get_success_3_u32(&self) -> Option<(u32, u32, u32)> {\n        if !self.is_success_3_u32() {\n            return None;\n        }\n        Some((self.r1, self.r2, self.r3))\n    }\n\n    /// Returns the values if this CommandReturn is of type Success with u32 and\n    /// u64.\n    pub fn get_success_u32_u64(&self) -> Option<(u32, u64)> {\n        if !self.is_success_u32_u64() {\n            return None;\n        }\n        Some((self.r1, self.r2 as u64 + ((self.r3 as u64) << 32)))\n    }\n\n    /// Returns the register values used to create this command.\n    pub fn raw_values(&self) -> (ReturnVariant, u32, u32, u32) {\n        (self.return_variant, self.r1, self.r2, self.r3)\n    }\n\n    /// Returns the return variant of this command.\n    pub fn return_variant(&self) -> ReturnVariant {\n        self.return_variant\n    }\n\n    /// Interprets this `CommandReturn` as a `Result`, checking the success and\n    /// failure variants, as well as extracting the relevant data.\n    ///\n    /// If neither the success or failure variants match what is required by\n    /// `T` and `E`, this function will return `Err(ErrorCode::BadRVal)`.\n    /// If `E` contains non-`ErrorCode` data in this case, the data will be 0.\n    ///\n    /// It is recommended to use type ascription or `::<>` to make the types\n    /// for `T` and `E` explicit at call-site.\n    pub fn to_result<T, E>(self) -> Result<T, E>\n    where\n        T: SuccessData,\n        E: FailureData,\n    {\n        let (return_variant, r1, mut r2, mut r3) = self.raw_values();\n        if return_variant == T::RETURN_VARIANT {\n            return Ok(T::from_raw_values(r1, r2, r3));\n        }\n        let ec: ErrorCode = if return_variant == E::RETURN_VARIANT {\n            // Safety: E::RETURN_VARIANT must be a failure variant, and\n            // failure variants must contain a valid ErrorCode in r1.\n            unsafe { transmute::<u32, ErrorCode>(r1) }\n        } else {\n            r2 = 0;\n            r3 = 0;\n            ErrorCode::BadRVal\n        };\n        Err(E::from_raw_values(ec, r2, r3))\n    }\n}\n\nmod sealed {\n    pub trait Sealed {}\n}\n\n/// Output from a successful `command` syscall.\n///\n/// This trait is [sealed], meaning foreign implementations cannot be defined,\n/// even though it can be referenced by foreign crates.\n///\n/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed\npub trait SuccessData: sealed::Sealed {\n    /// The return variant for this success type, stored in `r0` after\n    /// performing a `command` syscall.\n    const RETURN_VARIANT: ReturnVariant;\n\n    /// Constructs the success data given the raw register values.\n    fn from_raw_values(r1: u32, r2: u32, r3: u32) -> Self;\n}\n\nimpl sealed::Sealed for () {}\nimpl SuccessData for () {\n    const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS;\n\n    fn from_raw_values(_r1: u32, _r2: u32, _r3: u32) -> Self {}\n}\nimpl sealed::Sealed for u32 {}\nimpl SuccessData for u32 {\n    const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_U32;\n\n    fn from_raw_values(r1: u32, _r2: u32, _r3: u32) -> Self {\n        r1\n    }\n}\nimpl sealed::Sealed for u64 {}\nimpl SuccessData for u64 {\n    const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_U64;\n\n    fn from_raw_values(r1: u32, r2: u32, _r3: u32) -> Self {\n        r1 as u64 | ((r2 as u64) << 32)\n    }\n}\nimpl sealed::Sealed for (u32, u32) {}\nimpl SuccessData for (u32, u32) {\n    const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_2_U32;\n\n    fn from_raw_values(r1: u32, r2: u32, _r3: u32) -> Self {\n        (r1, r2)\n    }\n}\nimpl sealed::Sealed for (u32, u64) {}\nimpl SuccessData for (u32, u64) {\n    const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_U32_U64;\n\n    fn from_raw_values(r1: u32, r2: u32, r3: u32) -> Self {\n        (r1, r2 as u64 | ((r3 as u64) << 32))\n    }\n}\nimpl sealed::Sealed for (u32, u32, u32) {}\nimpl SuccessData for (u32, u32, u32) {\n    const RETURN_VARIANT: ReturnVariant = return_variant::SUCCESS_3_U32;\n\n    fn from_raw_values(r1: u32, r2: u32, r3: u32) -> Self {\n        (r1, r2, r3)\n    }\n}\n\n/// Output from a failed `command` syscall.\n///\n/// This trait is [sealed], meaning foreign implementations cannot be defined,\n/// even though it can be referenced by foreign crates.\n///\n/// # Safety\n/// [`RETURN_VARIANT`] must represent a failure variant, such that `r1` will\n/// always be a valid [`ErrorCode`].\n///\n/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed\npub unsafe trait FailureData: sealed::Sealed {\n    /// The return variant for this failure type, stored in `r0` after\n    /// performing a `command` syscall.\n    const RETURN_VARIANT: ReturnVariant;\n\n    /// Constructs the error data given the raw register values.\n    fn from_raw_values(r1: ErrorCode, r2: u32, r3: u32) -> Self;\n}\n\nimpl sealed::Sealed for ErrorCode {}\nunsafe impl FailureData for ErrorCode {\n    const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE;\n\n    fn from_raw_values(r1: ErrorCode, _r2: u32, _r3: u32) -> Self {\n        r1\n    }\n}\nimpl sealed::Sealed for (ErrorCode, u32) {}\nunsafe impl FailureData for (ErrorCode, u32) {\n    const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE_U32;\n\n    fn from_raw_values(r1: ErrorCode, r2: u32, _r3: u32) -> Self {\n        (r1, r2)\n    }\n}\nimpl sealed::Sealed for (ErrorCode, u32, u32) {}\nunsafe impl FailureData for (ErrorCode, u32, u32) {\n    const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE_2_U32;\n\n    fn from_raw_values(r1: ErrorCode, r2: u32, r3: u32) -> Self {\n        (r1, r2, r3)\n    }\n}\nimpl sealed::Sealed for (ErrorCode, u64) {}\nunsafe impl FailureData for (ErrorCode, u64) {\n    const RETURN_VARIANT: ReturnVariant = return_variant::FAILURE_U64;\n\n    fn from_raw_values(r1: ErrorCode, r2: u32, r3: u32) -> Self {\n        (r1, r2 as u64 | ((r3 as u64) << 32))\n    }\n}\n"
  },
  {
    "path": "platform/src/command_return_tests.rs",
    "content": "use crate::{return_variant, CommandReturn, ErrorCode};\n\n#[test]\nfn failure() {\n    let command_return = unsafe {\n        CommandReturn::new(\n            return_variant::FAILURE,\n            ErrorCode::Reserve as u32,\n            1002,\n            1003,\n        )\n    };\n    assert!(command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), Some(ErrorCode::Reserve));\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::FAILURE, 5, 1002, 1003)\n    );\n    assert_eq!(command_return.return_variant(), return_variant::FAILURE);\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::Reserve)\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32)>(),\n        Err((ErrorCode::BadRVal, 0))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32, u32)>(),\n        Err((ErrorCode::BadRVal, 0, 0))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u64)>(),\n        Err((ErrorCode::BadRVal, 0))\n    );\n}\n\n#[test]\nfn failure_u32() {\n    let command_return = unsafe {\n        CommandReturn::new(\n            return_variant::FAILURE_U32,\n            ErrorCode::Off as u32,\n            1002,\n            1003,\n        )\n    };\n    assert!(!command_return.is_failure());\n    assert!(command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(\n        command_return.get_failure_u32(),\n        Some((ErrorCode::Off, 1002))\n    );\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::FAILURE_U32, 4, 1002, 1003)\n    );\n    assert_eq!(command_return.return_variant(), return_variant::FAILURE_U32);\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32)>(),\n        Err((ErrorCode::Off, 1002))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32, u32)>(),\n        Err((ErrorCode::BadRVal, 0, 0))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u64)>(),\n        Err((ErrorCode::BadRVal, 0))\n    );\n}\n\n#[test]\nfn failure_2_u32() {\n    let command_return = unsafe {\n        CommandReturn::new(\n            return_variant::FAILURE_2_U32,\n            ErrorCode::Already as u32,\n            1002,\n            1003,\n        )\n    };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(\n        command_return.get_failure_2_u32(),\n        Some((ErrorCode::Already, 1002, 1003))\n    );\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::FAILURE_2_U32, 3, 1002, 1003)\n    );\n    assert_eq!(\n        command_return.return_variant(),\n        return_variant::FAILURE_2_U32\n    );\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32)>(),\n        Err((ErrorCode::BadRVal, 0))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32, u32)>(),\n        Err((ErrorCode::Already, 1002, 1003))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u64)>(),\n        Err((ErrorCode::BadRVal, 0))\n    );\n}\n\n#[test]\nfn failure_u64() {\n    let command_return = unsafe {\n        CommandReturn::new(\n            return_variant::FAILURE_U64,\n            ErrorCode::Busy as u32,\n            0x1002,\n            0x1003,\n        )\n    };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(\n        command_return.get_failure_u64(),\n        Some((ErrorCode::Busy, 0x0000_1003_0000_1002))\n    );\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::FAILURE_U64, 2, 0x1002, 0x1003)\n    );\n    assert_eq!(command_return.return_variant(), return_variant::FAILURE_U64);\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32)>(),\n        Err((ErrorCode::BadRVal, 0))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u32, u32)>(),\n        Err((ErrorCode::BadRVal, 0, 0))\n    );\n    assert_eq!(\n        command_return.to_result::<(), (ErrorCode, u64)>(),\n        Err((ErrorCode::Busy, 0x0000_1003_0000_1002))\n    );\n}\n\n#[test]\nfn success() {\n    let command_return = unsafe { CommandReturn::new(return_variant::SUCCESS, 1001, 1002, 1003) };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::SUCCESS, 1001, 1002, 1003)\n    );\n    assert_eq!(command_return.return_variant(), return_variant::SUCCESS);\n    assert_eq!(command_return.to_result::<(), ErrorCode>(), Ok(()));\n    assert_eq!(\n        command_return.to_result::<u32, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u64, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u64), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n}\n\n#[test]\nfn success_u32() {\n    let command_return =\n        unsafe { CommandReturn::new(return_variant::SUCCESS_U32, 1001, 1002, 1003) };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), Some(1001));\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::SUCCESS_U32, 1001, 1002, 1003)\n    );\n    assert_eq!(command_return.return_variant(), return_variant::SUCCESS_U32);\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(command_return.to_result::<u32, ErrorCode>(), Ok(1001));\n    assert_eq!(\n        command_return.to_result::<(u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u64, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u64), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n}\n\n#[test]\nfn success_2_u32() {\n    let command_return =\n        unsafe { CommandReturn::new(return_variant::SUCCESS_2_U32, 1001, 1002, 1003) };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), Some((1001, 1002)));\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::SUCCESS_2_U32, 1001, 1002, 1003)\n    );\n    assert_eq!(\n        command_return.return_variant(),\n        return_variant::SUCCESS_2_U32\n    );\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u32, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32), ErrorCode>(),\n        Ok((1001, 1002))\n    );\n    assert_eq!(\n        command_return.to_result::<u64, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u64), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n}\n\n#[test]\nfn success_u64() {\n    let command_return =\n        unsafe { CommandReturn::new(return_variant::SUCCESS_U64, 0x1001, 0x1002, 1003) };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(\n        command_return.get_success_u64(),\n        Some(0x0000_1002_0000_1001)\n    );\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::SUCCESS_U64, 0x1001, 0x1002, 1003)\n    );\n    assert_eq!(command_return.return_variant(), return_variant::SUCCESS_U64);\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u32, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u64, ErrorCode>(),\n        Ok(0x0000_1002_0000_1001)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u64), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n}\n\n#[test]\nfn success_3_u32() {\n    let command_return =\n        unsafe { CommandReturn::new(return_variant::SUCCESS_3_U32, 1001, 1002, 1003) };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(command_return.is_success_3_u32());\n    assert!(!command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), Some((1001, 1002, 1003)));\n    assert_eq!(command_return.get_success_u32_u64(), None);\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::SUCCESS_3_U32, 1001, 1002, 1003)\n    );\n    assert_eq!(\n        command_return.return_variant(),\n        return_variant::SUCCESS_3_U32\n    );\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u32, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u64, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32, u32), ErrorCode>(),\n        Ok((1001, 1002, 1003))\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u64), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n}\n\n#[test]\nfn success_u32_u64() {\n    let command_return =\n        unsafe { CommandReturn::new(return_variant::SUCCESS_U32_U64, 1001, 0x1002, 0x1003) };\n    assert!(!command_return.is_failure());\n    assert!(!command_return.is_failure_u32());\n    assert!(!command_return.is_failure_2_u32());\n    assert!(!command_return.is_failure_u64());\n    assert!(!command_return.is_success());\n    assert!(!command_return.is_success_u32());\n    assert!(!command_return.is_success_2_u32());\n    assert!(!command_return.is_success_u64());\n    assert!(!command_return.is_success_3_u32());\n    assert!(command_return.is_success_u32_u64());\n    assert_eq!(command_return.get_failure(), None);\n    assert_eq!(command_return.get_failure_u32(), None);\n    assert_eq!(command_return.get_failure_2_u32(), None);\n    assert_eq!(command_return.get_failure_u64(), None);\n    assert_eq!(command_return.get_success_u32(), None);\n    assert_eq!(command_return.get_success_2_u32(), None);\n    assert_eq!(command_return.get_success_u64(), None);\n    assert_eq!(command_return.get_success_3_u32(), None);\n    assert_eq!(\n        command_return.get_success_u32_u64(),\n        Some((1001, 0x0000_1003_0000_1002))\n    );\n    assert_eq!(\n        command_return.raw_values(),\n        (return_variant::SUCCESS_U32_U64, 1001, 0x1002, 0x1003)\n    );\n    assert_eq!(\n        command_return.return_variant(),\n        return_variant::SUCCESS_U32_U64\n    );\n    assert_eq!(\n        command_return.to_result::<(), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u32, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<u64, ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u32, u32), ErrorCode>(),\n        Err(ErrorCode::BadRVal)\n    );\n    assert_eq!(\n        command_return.to_result::<(u32, u64), ErrorCode>(),\n        Ok((1001, 0x0000_1003_0000_1002))\n    );\n}\n"
  },
  {
    "path": "platform/src/constants.rs",
    "content": "//! Defines constants shared between multiple `libtock-rs` crates.\n\npub mod exit_id {\n    pub const TERMINATE: u32 = 0;\n    pub const RESTART: u32 = 1;\n}\n\npub mod syscall_class {\n    pub const SUBSCRIBE: usize = 1;\n    pub const COMMAND: usize = 2;\n    pub const ALLOW_RW: usize = 3;\n    pub const ALLOW_RO: usize = 4;\n    pub const MEMOP: usize = 5;\n    pub const EXIT: usize = 6;\n}\n\npub mod yield_id {\n    pub const NO_WAIT: u32 = 0;\n    pub const WAIT: u32 = 1;\n}\n"
  },
  {
    "path": "platform/src/default_config.rs",
    "content": "/// A general purpose syscall configuration, which drivers should use as their\n/// default syscall config.\npub struct DefaultConfig;\n\nimpl crate::allow_ro::Config for DefaultConfig {}\nimpl crate::allow_rw::Config for DefaultConfig {}\nimpl crate::subscribe::Config for DefaultConfig {}\n"
  },
  {
    "path": "platform/src/error_code.rs",
    "content": "use core::{convert::TryFrom, fmt, mem::transmute};\n\n// TODO: Add a ufmt debug implementation for process binaries to use.\n/// An error code that libtock-rs APIs may return, as specified in\n/// [TRD 104][error-codes]. Note that while `BADRVAL` can never be produced by\n/// the kernel, it can be produced by userspace APIs.\n/// \n/// [error-codes]: https://github.com/tock/tock/blob/master/doc/reference/trd104-syscalls.md#33-error-codes\n#[derive(Clone, Copy, PartialEq, Eq)]\n// Explicit repr to use `transmute`. A word-sized error code results in\n// significant code size savings in typical use when compared to `#[repr(u16)]`.\n#[repr(u32)]\n#[rustfmt::skip]\npub enum ErrorCode {\n    Fail = 1,\n    Busy = 2,\n    Already = 3,\n    Off = 4,\n    Reserve = 5,\n    Invalid = 6,\n    Size = 7,\n    Cancel = 8,\n    NoMem = 9,\n    NoSupport = 10,\n    NoDevice = 11,\n    Uninstalled = 12,\n    NoAck = 13,\n    BadRVal = 1024,\n\n    // Error codes reserved for future use. We have to include these for future\n    // compatibility -- this allows process binaries compiled with this version\n    // of libtock-rs to run on future kernel versions that may return a larger\n    // variety of error codes.\n                                                    N00014 =    14, N00015 =    15,\n    N00016 =    16, N00017 =    17, N00018 =    18, N00019 =    19, N00020 =    20,\n    N00021 =    21, N00022 =    22, N00023 =    23, N00024 =    24, N00025 =    25,\n    N00026 =    26, N00027 =    27, N00028 =    28, N00029 =    29, N00030 =    30,\n    N00031 =    31, N00032 =    32, N00033 =    33, N00034 =    34, N00035 =    35,\n    N00036 =    36, N00037 =    37, N00038 =    38, N00039 =    39, N00040 =    40,\n    N00041 =    41, N00042 =    42, N00043 =    43, N00044 =    44, N00045 =    45,\n    N00046 =    46, N00047 =    47, N00048 =    48, N00049 =    49, N00050 =    50,\n    N00051 =    51, N00052 =    52, N00053 =    53, N00054 =    54, N00055 =    55,\n    N00056 =    56, N00057 =    57, N00058 =    58, N00059 =    59, N00060 =    60,\n    N00061 =    61, N00062 =    62, N00063 =    63, N00064 =    64, N00065 =    65,\n    N00066 =    66, N00067 =    67, N00068 =    68, N00069 =    69, N00070 =    70,\n    N00071 =    71, N00072 =    72, N00073 =    73, N00074 =    74, N00075 =    75,\n    N00076 =    76, N00077 =    77, N00078 =    78, N00079 =    79, N00080 =    80,\n    N00081 =    81, N00082 =    82, N00083 =    83, N00084 =    84, N00085 =    85,\n    N00086 =    86, N00087 =    87, N00088 =    88, N00089 =    89, N00090 =    90,\n    N00091 =    91, N00092 =    92, N00093 =    93, N00094 =    94, N00095 =    95,\n    N00096 =    96, N00097 =    97, N00098 =    98, N00099 =    99, N00100 =   100,\n    N00101 =   101, N00102 =   102, N00103 =   103, N00104 =   104, N00105 =   105,\n    N00106 =   106, N00107 =   107, N00108 =   108, N00109 =   109, N00110 =   110,\n    N00111 =   111, N00112 =   112, N00113 =   113, N00114 =   114, N00115 =   115,\n    N00116 =   116, N00117 =   117, N00118 =   118, N00119 =   119, N00120 =   120,\n    N00121 =   121, N00122 =   122, N00123 =   123, N00124 =   124, N00125 =   125,\n    N00126 =   126, N00127 =   127, N00128 =   128, N00129 =   129, N00130 =   130,\n    N00131 =   131, N00132 =   132, N00133 =   133, N00134 =   134, N00135 =   135,\n    N00136 =   136, N00137 =   137, N00138 =   138, N00139 =   139, N00140 =   140,\n    N00141 =   141, N00142 =   142, N00143 =   143, N00144 =   144, N00145 =   145,\n    N00146 =   146, N00147 =   147, N00148 =   148, N00149 =   149, N00150 =   150,\n    N00151 =   151, N00152 =   152, N00153 =   153, N00154 =   154, N00155 =   155,\n    N00156 =   156, N00157 =   157, N00158 =   158, N00159 =   159, N00160 =   160,\n    N00161 =   161, N00162 =   162, N00163 =   163, N00164 =   164, N00165 =   165,\n    N00166 =   166, N00167 =   167, N00168 =   168, N00169 =   169, N00170 =   170,\n    N00171 =   171, N00172 =   172, N00173 =   173, N00174 =   174, N00175 =   175,\n    N00176 =   176, N00177 =   177, N00178 =   178, N00179 =   179, N00180 =   180,\n    N00181 =   181, N00182 =   182, N00183 =   183, N00184 =   184, N00185 =   185,\n    N00186 =   186, N00187 =   187, N00188 =   188, N00189 =   189, N00190 =   190,\n    N00191 =   191, N00192 =   192, N00193 =   193, N00194 =   194, N00195 =   195,\n    N00196 =   196, N00197 =   197, N00198 =   198, N00199 =   199, N00200 =   200,\n    N00201 =   201, N00202 =   202, N00203 =   203, N00204 =   204, N00205 =   205,\n    N00206 =   206, N00207 =   207, N00208 =   208, N00209 =   209, N00210 =   210,\n    N00211 =   211, N00212 =   212, N00213 =   213, N00214 =   214, N00215 =   215,\n    N00216 =   216, N00217 =   217, N00218 =   218, N00219 =   219, N00220 =   220,\n    N00221 =   221, N00222 =   222, N00223 =   223, N00224 =   224, N00225 =   225,\n    N00226 =   226, N00227 =   227, N00228 =   228, N00229 =   229, N00230 =   230,\n    N00231 =   231, N00232 =   232, N00233 =   233, N00234 =   234, N00235 =   235,\n    N00236 =   236, N00237 =   237, N00238 =   238, N00239 =   239, N00240 =   240,\n    N00241 =   241, N00242 =   242, N00243 =   243, N00244 =   244, N00245 =   245,\n    N00246 =   246, N00247 =   247, N00248 =   248, N00249 =   249, N00250 =   250,\n    N00251 =   251, N00252 =   252, N00253 =   253, N00254 =   254, N00255 =   255,\n    N00256 =   256, N00257 =   257, N00258 =   258, N00259 =   259, N00260 =   260,\n    N00261 =   261, N00262 =   262, N00263 =   263, N00264 =   264, N00265 =   265,\n    N00266 =   266, N00267 =   267, N00268 =   268, N00269 =   269, N00270 =   270,\n    N00271 =   271, N00272 =   272, N00273 =   273, N00274 =   274, N00275 =   275,\n    N00276 =   276, N00277 =   277, N00278 =   278, N00279 =   279, N00280 =   280,\n    N00281 =   281, N00282 =   282, N00283 =   283, N00284 =   284, N00285 =   285,\n    N00286 =   286, N00287 =   287, N00288 =   288, N00289 =   289, N00290 =   290,\n    N00291 =   291, N00292 =   292, N00293 =   293, N00294 =   294, N00295 =   295,\n    N00296 =   296, N00297 =   297, N00298 =   298, N00299 =   299, N00300 =   300,\n    N00301 =   301, N00302 =   302, N00303 =   303, N00304 =   304, N00305 =   305,\n    N00306 =   306, N00307 =   307, N00308 =   308, N00309 =   309, N00310 =   310,\n    N00311 =   311, N00312 =   312, N00313 =   313, N00314 =   314, N00315 =   315,\n    N00316 =   316, N00317 =   317, N00318 =   318, N00319 =   319, N00320 =   320,\n    N00321 =   321, N00322 =   322, N00323 =   323, N00324 =   324, N00325 =   325,\n    N00326 =   326, N00327 =   327, N00328 =   328, N00329 =   329, N00330 =   330,\n    N00331 =   331, N00332 =   332, N00333 =   333, N00334 =   334, N00335 =   335,\n    N00336 =   336, N00337 =   337, N00338 =   338, N00339 =   339, N00340 =   340,\n    N00341 =   341, N00342 =   342, N00343 =   343, N00344 =   344, N00345 =   345,\n    N00346 =   346, N00347 =   347, N00348 =   348, N00349 =   349, N00350 =   350,\n    N00351 =   351, N00352 =   352, N00353 =   353, N00354 =   354, N00355 =   355,\n    N00356 =   356, N00357 =   357, N00358 =   358, N00359 =   359, N00360 =   360,\n    N00361 =   361, N00362 =   362, N00363 =   363, N00364 =   364, N00365 =   365,\n    N00366 =   366, N00367 =   367, N00368 =   368, N00369 =   369, N00370 =   370,\n    N00371 =   371, N00372 =   372, N00373 =   373, N00374 =   374, N00375 =   375,\n    N00376 =   376, N00377 =   377, N00378 =   378, N00379 =   379, N00380 =   380,\n    N00381 =   381, N00382 =   382, N00383 =   383, N00384 =   384, N00385 =   385,\n    N00386 =   386, N00387 =   387, N00388 =   388, N00389 =   389, N00390 =   390,\n    N00391 =   391, N00392 =   392, N00393 =   393, N00394 =   394, N00395 =   395,\n    N00396 =   396, N00397 =   397, N00398 =   398, N00399 =   399, N00400 =   400,\n    N00401 =   401, N00402 =   402, N00403 =   403, N00404 =   404, N00405 =   405,\n    N00406 =   406, N00407 =   407, N00408 =   408, N00409 =   409, N00410 =   410,\n    N00411 =   411, N00412 =   412, N00413 =   413, N00414 =   414, N00415 =   415,\n    N00416 =   416, N00417 =   417, N00418 =   418, N00419 =   419, N00420 =   420,\n    N00421 =   421, N00422 =   422, N00423 =   423, N00424 =   424, N00425 =   425,\n    N00426 =   426, N00427 =   427, N00428 =   428, N00429 =   429, N00430 =   430,\n    N00431 =   431, N00432 =   432, N00433 =   433, N00434 =   434, N00435 =   435,\n    N00436 =   436, N00437 =   437, N00438 =   438, N00439 =   439, N00440 =   440,\n    N00441 =   441, N00442 =   442, N00443 =   443, N00444 =   444, N00445 =   445,\n    N00446 =   446, N00447 =   447, N00448 =   448, N00449 =   449, N00450 =   450,\n    N00451 =   451, N00452 =   452, N00453 =   453, N00454 =   454, N00455 =   455,\n    N00456 =   456, N00457 =   457, N00458 =   458, N00459 =   459, N00460 =   460,\n    N00461 =   461, N00462 =   462, N00463 =   463, N00464 =   464, N00465 =   465,\n    N00466 =   466, N00467 =   467, N00468 =   468, N00469 =   469, N00470 =   470,\n    N00471 =   471, N00472 =   472, N00473 =   473, N00474 =   474, N00475 =   475,\n    N00476 =   476, N00477 =   477, N00478 =   478, N00479 =   479, N00480 =   480,\n    N00481 =   481, N00482 =   482, N00483 =   483, N00484 =   484, N00485 =   485,\n    N00486 =   486, N00487 =   487, N00488 =   488, N00489 =   489, N00490 =   490,\n    N00491 =   491, N00492 =   492, N00493 =   493, N00494 =   494, N00495 =   495,\n    N00496 =   496, N00497 =   497, N00498 =   498, N00499 =   499, N00500 =   500,\n    N00501 =   501, N00502 =   502, N00503 =   503, N00504 =   504, N00505 =   505,\n    N00506 =   506, N00507 =   507, N00508 =   508, N00509 =   509, N00510 =   510,\n    N00511 =   511, N00512 =   512, N00513 =   513, N00514 =   514, N00515 =   515,\n    N00516 =   516, N00517 =   517, N00518 =   518, N00519 =   519, N00520 =   520,\n    N00521 =   521, N00522 =   522, N00523 =   523, N00524 =   524, N00525 =   525,\n    N00526 =   526, N00527 =   527, N00528 =   528, N00529 =   529, N00530 =   530,\n    N00531 =   531, N00532 =   532, N00533 =   533, N00534 =   534, N00535 =   535,\n    N00536 =   536, N00537 =   537, N00538 =   538, N00539 =   539, N00540 =   540,\n    N00541 =   541, N00542 =   542, N00543 =   543, N00544 =   544, N00545 =   545,\n    N00546 =   546, N00547 =   547, N00548 =   548, N00549 =   549, N00550 =   550,\n    N00551 =   551, N00552 =   552, N00553 =   553, N00554 =   554, N00555 =   555,\n    N00556 =   556, N00557 =   557, N00558 =   558, N00559 =   559, N00560 =   560,\n    N00561 =   561, N00562 =   562, N00563 =   563, N00564 =   564, N00565 =   565,\n    N00566 =   566, N00567 =   567, N00568 =   568, N00569 =   569, N00570 =   570,\n    N00571 =   571, N00572 =   572, N00573 =   573, N00574 =   574, N00575 =   575,\n    N00576 =   576, N00577 =   577, N00578 =   578, N00579 =   579, N00580 =   580,\n    N00581 =   581, N00582 =   582, N00583 =   583, N00584 =   584, N00585 =   585,\n    N00586 =   586, N00587 =   587, N00588 =   588, N00589 =   589, N00590 =   590,\n    N00591 =   591, N00592 =   592, N00593 =   593, N00594 =   594, N00595 =   595,\n    N00596 =   596, N00597 =   597, N00598 =   598, N00599 =   599, N00600 =   600,\n    N00601 =   601, N00602 =   602, N00603 =   603, N00604 =   604, N00605 =   605,\n    N00606 =   606, N00607 =   607, N00608 =   608, N00609 =   609, N00610 =   610,\n    N00611 =   611, N00612 =   612, N00613 =   613, N00614 =   614, N00615 =   615,\n    N00616 =   616, N00617 =   617, N00618 =   618, N00619 =   619, N00620 =   620,\n    N00621 =   621, N00622 =   622, N00623 =   623, N00624 =   624, N00625 =   625,\n    N00626 =   626, N00627 =   627, N00628 =   628, N00629 =   629, N00630 =   630,\n    N00631 =   631, N00632 =   632, N00633 =   633, N00634 =   634, N00635 =   635,\n    N00636 =   636, N00637 =   637, N00638 =   638, N00639 =   639, N00640 =   640,\n    N00641 =   641, N00642 =   642, N00643 =   643, N00644 =   644, N00645 =   645,\n    N00646 =   646, N00647 =   647, N00648 =   648, N00649 =   649, N00650 =   650,\n    N00651 =   651, N00652 =   652, N00653 =   653, N00654 =   654, N00655 =   655,\n    N00656 =   656, N00657 =   657, N00658 =   658, N00659 =   659, N00660 =   660,\n    N00661 =   661, N00662 =   662, N00663 =   663, N00664 =   664, N00665 =   665,\n    N00666 =   666, N00667 =   667, N00668 =   668, N00669 =   669, N00670 =   670,\n    N00671 =   671, N00672 =   672, N00673 =   673, N00674 =   674, N00675 =   675,\n    N00676 =   676, N00677 =   677, N00678 =   678, N00679 =   679, N00680 =   680,\n    N00681 =   681, N00682 =   682, N00683 =   683, N00684 =   684, N00685 =   685,\n    N00686 =   686, N00687 =   687, N00688 =   688, N00689 =   689, N00690 =   690,\n    N00691 =   691, N00692 =   692, N00693 =   693, N00694 =   694, N00695 =   695,\n    N00696 =   696, N00697 =   697, N00698 =   698, N00699 =   699, N00700 =   700,\n    N00701 =   701, N00702 =   702, N00703 =   703, N00704 =   704, N00705 =   705,\n    N00706 =   706, N00707 =   707, N00708 =   708, N00709 =   709, N00710 =   710,\n    N00711 =   711, N00712 =   712, N00713 =   713, N00714 =   714, N00715 =   715,\n    N00716 =   716, N00717 =   717, N00718 =   718, N00719 =   719, N00720 =   720,\n    N00721 =   721, N00722 =   722, N00723 =   723, N00724 =   724, N00725 =   725,\n    N00726 =   726, N00727 =   727, N00728 =   728, N00729 =   729, N00730 =   730,\n    N00731 =   731, N00732 =   732, N00733 =   733, N00734 =   734, N00735 =   735,\n    N00736 =   736, N00737 =   737, N00738 =   738, N00739 =   739, N00740 =   740,\n    N00741 =   741, N00742 =   742, N00743 =   743, N00744 =   744, N00745 =   745,\n    N00746 =   746, N00747 =   747, N00748 =   748, N00749 =   749, N00750 =   750,\n    N00751 =   751, N00752 =   752, N00753 =   753, N00754 =   754, N00755 =   755,\n    N00756 =   756, N00757 =   757, N00758 =   758, N00759 =   759, N00760 =   760,\n    N00761 =   761, N00762 =   762, N00763 =   763, N00764 =   764, N00765 =   765,\n    N00766 =   766, N00767 =   767, N00768 =   768, N00769 =   769, N00770 =   770,\n    N00771 =   771, N00772 =   772, N00773 =   773, N00774 =   774, N00775 =   775,\n    N00776 =   776, N00777 =   777, N00778 =   778, N00779 =   779, N00780 =   780,\n    N00781 =   781, N00782 =   782, N00783 =   783, N00784 =   784, N00785 =   785,\n    N00786 =   786, N00787 =   787, N00788 =   788, N00789 =   789, N00790 =   790,\n    N00791 =   791, N00792 =   792, N00793 =   793, N00794 =   794, N00795 =   795,\n    N00796 =   796, N00797 =   797, N00798 =   798, N00799 =   799, N00800 =   800,\n    N00801 =   801, N00802 =   802, N00803 =   803, N00804 =   804, N00805 =   805,\n    N00806 =   806, N00807 =   807, N00808 =   808, N00809 =   809, N00810 =   810,\n    N00811 =   811, N00812 =   812, N00813 =   813, N00814 =   814, N00815 =   815,\n    N00816 =   816, N00817 =   817, N00818 =   818, N00819 =   819, N00820 =   820,\n    N00821 =   821, N00822 =   822, N00823 =   823, N00824 =   824, N00825 =   825,\n    N00826 =   826, N00827 =   827, N00828 =   828, N00829 =   829, N00830 =   830,\n    N00831 =   831, N00832 =   832, N00833 =   833, N00834 =   834, N00835 =   835,\n    N00836 =   836, N00837 =   837, N00838 =   838, N00839 =   839, N00840 =   840,\n    N00841 =   841, N00842 =   842, N00843 =   843, N00844 =   844, N00845 =   845,\n    N00846 =   846, N00847 =   847, N00848 =   848, N00849 =   849, N00850 =   850,\n    N00851 =   851, N00852 =   852, N00853 =   853, N00854 =   854, N00855 =   855,\n    N00856 =   856, N00857 =   857, N00858 =   858, N00859 =   859, N00860 =   860,\n    N00861 =   861, N00862 =   862, N00863 =   863, N00864 =   864, N00865 =   865,\n    N00866 =   866, N00867 =   867, N00868 =   868, N00869 =   869, N00870 =   870,\n    N00871 =   871, N00872 =   872, N00873 =   873, N00874 =   874, N00875 =   875,\n    N00876 =   876, N00877 =   877, N00878 =   878, N00879 =   879, N00880 =   880,\n    N00881 =   881, N00882 =   882, N00883 =   883, N00884 =   884, N00885 =   885,\n    N00886 =   886, N00887 =   887, N00888 =   888, N00889 =   889, N00890 =   890,\n    N00891 =   891, N00892 =   892, N00893 =   893, N00894 =   894, N00895 =   895,\n    N00896 =   896, N00897 =   897, N00898 =   898, N00899 =   899, N00900 =   900,\n    N00901 =   901, N00902 =   902, N00903 =   903, N00904 =   904, N00905 =   905,\n    N00906 =   906, N00907 =   907, N00908 =   908, N00909 =   909, N00910 =   910,\n    N00911 =   911, N00912 =   912, N00913 =   913, N00914 =   914, N00915 =   915,\n    N00916 =   916, N00917 =   917, N00918 =   918, N00919 =   919, N00920 =   920,\n    N00921 =   921, N00922 =   922, N00923 =   923, N00924 =   924, N00925 =   925,\n    N00926 =   926, N00927 =   927, N00928 =   928, N00929 =   929, N00930 =   930,\n    N00931 =   931, N00932 =   932, N00933 =   933, N00934 =   934, N00935 =   935,\n    N00936 =   936, N00937 =   937, N00938 =   938, N00939 =   939, N00940 =   940,\n    N00941 =   941, N00942 =   942, N00943 =   943, N00944 =   944, N00945 =   945,\n    N00946 =   946, N00947 =   947, N00948 =   948, N00949 =   949, N00950 =   950,\n    N00951 =   951, N00952 =   952, N00953 =   953, N00954 =   954, N00955 =   955,\n    N00956 =   956, N00957 =   957, N00958 =   958, N00959 =   959, N00960 =   960,\n    N00961 =   961, N00962 =   962, N00963 =   963, N00964 =   964, N00965 =   965,\n    N00966 =   966, N00967 =   967, N00968 =   968, N00969 =   969, N00970 =   970,\n    N00971 =   971, N00972 =   972, N00973 =   973, N00974 =   974, N00975 =   975,\n    N00976 =   976, N00977 =   977, N00978 =   978, N00979 =   979, N00980 =   980,\n    N00981 =   981, N00982 =   982, N00983 =   983, N00984 =   984, N00985 =   985,\n    N00986 =   986, N00987 =   987, N00988 =   988, N00989 =   989, N00990 =   990,\n    N00991 =   991, N00992 =   992, N00993 =   993, N00994 =   994, N00995 =   995,\n    N00996 =   996, N00997 =   997, N00998 =   998, N00999 =   999, N01000 =  1000,\n    N01001 =  1001, N01002 =  1002, N01003 =  1003, N01004 =  1004, N01005 =  1005,\n    N01006 =  1006, N01007 =  1007, N01008 =  1008, N01009 =  1009, N01010 =  1010,\n    N01011 =  1011, N01012 =  1012, N01013 =  1013, N01014 =  1014, N01015 =  1015,\n    N01016 =  1016, N01017 =  1017, N01018 =  1018, N01019 =  1019, N01020 =  1020,\n    N01021 =  1021, N01022 =  1022, N01023 =  1023,\n}\n\n/// The provided value is not a recognized TRD 104 error code.\n#[derive(PartialEq, Eq, Debug)]\npub struct NotAnErrorCode;\n\nimpl ErrorCode {\n    /// Represent this error code as a string, if defined.\n    fn as_str(self) -> Option<&'static str> {\n        match self {\n            Self::Fail => Some(\"FAIL\"),\n            Self::Busy => Some(\"BUSY\"),\n            Self::Already => Some(\"ALREADY\"),\n            Self::Off => Some(\"OFF\"),\n            Self::Reserve => Some(\"RESERVE\"),\n            Self::Invalid => Some(\"INVALID\"),\n            Self::Size => Some(\"SIZE\"),\n            Self::Cancel => Some(\"CANCEL\"),\n            Self::NoMem => Some(\"NOMEM\"),\n            Self::NoSupport => Some(\"NOSUPPORT\"),\n            Self::NoDevice => Some(\"NODEVICE\"),\n            Self::Uninstalled => Some(\"UNINSTALLED\"),\n            Self::NoAck => Some(\"NOACK\"),\n            Self::BadRVal => Some(\"BADRVAL\"),\n            _ => None,\n        }\n    }\n}\n\nimpl fmt::Debug for ErrorCode {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self.as_str() {\n            Some(s) => write!(f, \"{s}\"),\n            None => write!(f, \"code {}\", *self as u16),\n        }\n    }\n}\n\nimpl TryFrom<u32> for ErrorCode {\n    type Error = NotAnErrorCode;\n\n    fn try_from(value: u32) -> Result<Self, Self::Error> {\n        if (1..=1024).contains(&value) {\n            Ok(unsafe { transmute::<u32, ErrorCode>(value) })\n        } else {\n            Err(NotAnErrorCode)\n        }\n    }\n}\n\n#[cfg(feature = \"rust_embedded\")]\nimpl embedded_hal::digital::Error for ErrorCode {\n    fn kind(&self) -> embedded_hal::digital::ErrorKind {\n        use embedded_hal::digital::ErrorKind;\n        ErrorKind::Other\n    }\n}\n\n#[cfg(feature = \"rust_embedded\")]\nimpl embedded_hal::spi::Error for ErrorCode {\n    fn kind(&self) -> embedded_hal::spi::ErrorKind {\n        use embedded_hal::spi::ErrorKind;\n        ErrorKind::Other\n    }\n}\n"
  },
  {
    "path": "platform/src/error_code_tests.rs",
    "content": "use core::convert::TryInto;\n\nuse crate::{error_code::NotAnErrorCode, ErrorCode};\n\n// Verifies that `ErrorCode` represents every valid value in the range\n// [1, 1024].\n#[cfg(miri)]\n#[test]\nfn error_code_range() {\n    for value in 1..=1024u32 {\n        let _ = unsafe { *(&value as *const u32 as *const ErrorCode) };\n    }\n}\n\n#[test]\nfn error_code_try_into() {\n    assert_eq!(TryInto::<ErrorCode>::try_into(0u32), Err(NotAnErrorCode));\n    for value in 1..=1024u32 {\n        assert_eq!(value.try_into().map(|e: ErrorCode| e as u32), Ok(value));\n    }\n    assert_eq!(TryInto::<ErrorCode>::try_into(1025u32), Err(NotAnErrorCode));\n}\n"
  },
  {
    "path": "platform/src/exit_on_drop.rs",
    "content": "/// Calls the Exit system call when dropped. Used to catch panic unwinding from\n/// a `#![no_std]` context. The caller should `core::mem::forget` the\n/// `ExitOnDrop` when it no longer needs to catch unwinding.\n///\n///\n/// # Example\n/// ```\n/// use libtock_platform::exit_on_drop::ExitOnDrop;\n/// fn function_that_must_not_unwind<S: libtock_platform::Syscalls>() {\n///     let exit_on_drop: ExitOnDrop::<S> = Default::default();\n///     /* Do something that might unwind here. */\n///     core::mem::forget(exit_on_drop);\n/// }\n/// ```\npub struct ExitOnDrop<S: crate::Syscalls>(core::marker::PhantomData<S>);\n\nimpl<S: crate::Syscalls> Default for ExitOnDrop<S> {\n    fn default() -> ExitOnDrop<S> {\n        ExitOnDrop(core::marker::PhantomData)\n    }\n}\n\nimpl<S: crate::Syscalls> Drop for ExitOnDrop<S> {\n    fn drop(&mut self) {\n        S::exit_terminate(0);\n    }\n}\n"
  },
  {
    "path": "platform/src/lib.rs",
    "content": "#![cfg_attr(not(test), no_std)]\n#![warn(unsafe_op_in_unsafe_fn)]\n\npub mod allow_ro;\npub mod allow_rw;\npub mod command_return;\nmod constants;\nmod default_config;\nmod error_code;\npub mod exit_on_drop;\nmod raw_syscalls;\nmod register;\npub mod return_variant;\npub mod share;\npub mod subscribe;\nmod syscalls;\nmod syscalls_impl;\nmod termination;\nmod yield_types;\n\npub use allow_ro::AllowRo;\npub use allow_rw::AllowRw;\npub use command_return::CommandReturn;\npub use constants::{exit_id, syscall_class, yield_id};\npub use default_config::DefaultConfig;\npub use error_code::ErrorCode;\npub use raw_syscalls::RawSyscalls;\npub use register::Register;\npub use return_variant::ReturnVariant;\npub use subscribe::{Subscribe, Upcall};\npub use syscalls::Syscalls;\npub use termination::Termination;\npub use yield_types::YieldNoWaitReturn;\n\n#[cfg(test)]\nmod command_return_tests;\n\n#[cfg(test)]\nmod error_code_tests;\n"
  },
  {
    "path": "platform/src/raw_syscalls.rs",
    "content": "use crate::Register;\n\n/// `RawSyscalls` allows a fake Tock kernel to be injected into components for\n/// unit testing. It is implemented by `libtock_runtime::TockSyscalls` and\n/// `libtock_unittest::fake::Kernel`. **Components should not use `RawSyscalls`\n/// directly; instead, use the `Syscalls` trait, which provides higher-level\n/// interfaces to the system calls.**\n///\n/// # Safety\n/// `RawSyscalls` is unsafe because `unsafe` code depends on its methods to\n/// return the correct register values.\n// The RawSyscalls trait is designed to minimize the complexity and size of its\n// implementation, as its implementation is difficult to test (it cannot be used\n// in unit tests, with sanitizers, or in Miri). It is also designed to minimize\n// the number of unnecessary instructions it generates.\n//\n// Convention: This file uses the same register naming conventions as the Tock\n// 2.0 syscall TRD. Registers r0-r4 correspond to ARM registers r0-r4 and RISC-V\n// registers a0-a4.\n//\n// Theoretically, RawSyscalls could consist of a single raw system call. To\n// start, something like this should work:\n//\n//   unsafe fn syscall<const CLASS: usize>([Reg; 4]) -> [Reg; 4];\n//\n// Note: Reg is an abbreviation of Register.\n//\n// Using a single system call has a major inefficiency. The single raw system\n// call would need to clobber every register that any system call can clobber.\n// Yield has a far longer clobber list than most system calls, so this would be\n// inefficient for the majority of system calls. As a result, we can split yield\n// out into its own function, giving the following API:\n//\n//   unsafe fn yield([Reg; 4]) -> [Reg; 4];\n//   unsafe fn syscall<const CLASS: usize>([Reg; 4]) -> [Reg; 4];\n//\n// There is one significant inefficiency remaining. Many system calls, such as\n// memop's \"get RAM start address\" operation, do not need to set all four\n// arguments. The compiler cannot optimize away this inefficiency, so to remove\n// it we need to split the system calls up based on the number of arguments they\n// take:\n//\n//   unsafe fn yield0([Reg; 0]) -> [Reg; 4];\n//   unsafe fn yield1([Reg; 1]) -> [Reg; 4];\n//   unsafe fn yield2([Reg; 2]) -> [Reg; 4];\n//   unsafe fn yield3([Reg; 3]) -> [Reg; 4];\n//   unsafe fn yield4([Reg; 4]) -> [Reg; 4];\n//   unsafe fn syscall0<const CLASS: usize>([Reg; 0]) -> [Reg; 4];\n//   unsafe fn syscall1<const CLASS: usize>([Reg; 1]) -> [Reg; 4];\n//   unsafe fn syscall2<const CLASS: usize>([Reg; 2]) -> [Reg; 4];\n//   unsafe fn syscall3<const CLASS: usize>([Reg; 3]) -> [Reg; 4];\n//   unsafe fn syscall4<const CLASS: usize>([Reg; 4]) -> [Reg; 4];\n//\n// However, not all of these are used! If we remove the system calls that are\n// unused, we are left with the following:\n//\n//   unsafe fn yield1([Reg; 1]) -> [Reg; 4];\n//   unsafe fn yield2([Reg; 2]) -> [Reg; 4];\n//   unsafe fn syscall1<const CLASS: usize>([Reg; 1]) -> [Reg; 4];\n//   unsafe fn syscall2<const CLASS: usize>([Reg; 2]) -> [Reg; 4];\n//   unsafe fn syscall4<const CLASS: usize>([Reg; 4]) -> [Reg; 4];\n//\n// These system calls are refined further individually, which is documented on\n// a per-function basis.\npub unsafe trait RawSyscalls: Sized {\n    // yield1 can only be used to call `yield-wait`, which does not have a\n    // return value. To simplify the assembly implementation, we remove its\n    // return value.\n    //\n    // yield1 should:\n    //     1. Call syscall class 0\n    //     2. Pass in r0 as an inlateout register.\n    //     3. Mark all caller-saved registers as lateout clobbers.\n    //     4. NOT provide any of the following options:\n    //            pure             (yield has side effects)\n    //            nomem            (a callback can read + write globals)\n    //            readonly         (a callback can write globals)\n    //            preserves_flags  (a callback can change flags)\n    //            noreturn         (yield is expected to return)\n    //            nostack          (a callback needs the stack)\n    /// `yield1` should only be called by `libtock_platform`.\n    /// # Safety\n    /// yield1 may only be used for yield operations that do not return a value.\n    /// It is exactly as safe as the underlying system call.\n    unsafe fn yield1(_: [Register; 1]);\n\n    // yield2 can only be used to call `yield-no-wait`. `yield-no-wait` does not\n    // return any values, so to simplify the assembly we omit return arguments.\n    //\n    // yield2 should:\n    //     1. Call syscall class 0\n    //     2. Pass in r0 and r1 as inlateout registers.\n    //     3. Mark all caller-saved registers as lateout clobbers.\n    //     4. NOT provide any of the following options:\n    //            pure             (yield has side effects)\n    //            nomem            (a callback can read + write globals)\n    //            readonly         (a callback can write globals)\n    //            preserves_flags  (a callback can change flags)\n    //            noreturn         (yield is expected to return)\n    //            nostack          (a callback needs the stack)\n    /// `yield2` should only be called by `libtock_platform`.\n    /// # Safety\n    /// yield2 may only be used for yield operations that do not return a value.\n    /// It has the same safety invariants as the underlying system call.\n    unsafe fn yield2(_: [Register; 2]);\n\n    // syscall1 is only used to invoke Memop operations. Because there are no\n    // Memop commands that set r2 or r3, raw_syscall1 only needs to return r0\n    // and r1.\n    //\n    // Memop commands may panic in the unit test environment, as not all memop\n    // calls can be sensibly implemented in that environment.\n    //\n    // syscall1 should:\n    //     1. Call the syscall class specified by CLASS.\n    //     2. Pass r0 as an inlateout register.\n    //     3. Specify r1 as a lateout register and return its value.\n    //     4. Not mark any registers as clobbered.\n    //     5. Have all of the following options:\n    //            preserves_flags\n    //            nostack\n    //            nomem            (it is okay for the compiler to cache globals\n    //                              across memop calls)\n    //     6. NOT have any of the following options:\n    //            pure      (two invocations of the same memop can return\n    //                       different values)\n    //            readonly  (incompatible with nomem)\n    //            noreturn\n    /// `syscall1` should only be called by `libtock_platform`.\n    /// # Safety\n    /// This directly makes a system call. It can only be used for Memop calls\n    /// that accept 1 argument and only overwrite r0 and r1 on return. It is\n    /// unsafe any time the underlying system call is unsafe.\n    unsafe fn syscall1<const CLASS: usize>(_: [Register; 1]) -> [Register; 2];\n\n    // syscall2 is used to invoke Exit as well as Memop operations that take an\n    // argument. Memop does not currently use more than 2 registers for its\n    // return value, and Exit does not return, so syscall2 only returns 2\n    // values.\n    //\n    // syscall2 should:\n    //     1. Call the syscall class specified by CLASS.\n    //     2. Pass r0 and r1 as inlateout registers.\n    //     3. Not mark any registers as clobbered.\n    //     4. Have all of the following options:\n    //            preserves_flags\n    //            nostack\n    //            nomem            (the compiler can cache globals across memop\n    //                              calls)\n    //     5. NOT have any of the following options:\n    //            pure      Two invocations of sbrk can return different values\n    //            readonly  Incompatible with nomem\n    //            noreturn\n    /// `syscall2` should only be called by `libtock_platform`.\n    /// # Safety\n    /// `syscall2` directly makes a system call. It can only be used for core\n    /// kernel system calls that accept 2 arguments and only overwrite r0 and r1\n    /// on return. It is unsafe any time the underlying system call is unsafe.\n    unsafe fn syscall2<const CLASS: usize>(_: [Register; 2]) -> [Register; 2];\n\n    // syscall4 should:\n    //     1. Call the syscall class specified by CLASS.\n    //     2. Pass r0-r3 in the corresponding registers as inlateout registers.\n    //     3. Not mark any registers as clobbered.\n    //     4. Have all of the following options:\n    //            preserves_flags  (these system calls do not touch flags)\n    //            nostack          (these system calls do not touch the stack)\n    //     5. NOT have any of the following options:\n    //            pure      (these system calls have side effects)\n    //            nomem     (the compiler needs to write to globals before allow)\n    //            readonly  (rw allow can modify memory)\n    //            noreturn  (all these system calls are expected to return)\n    //\n    // For subscribe(), the callback pointer should be either 0 (for the null\n    // callback) or an `unsafe extern fn(u32, u32, u32, Register)`.\n    /// `syscall4` should only be called by `libtock_platform`.\n    ///\n    /// # Safety\n    /// `syscall4` must NOT be used to invoke yield. It inherits all safety\n    /// invariants from the underlying system call as described in TRD 104,\n    /// which varies depending on the system call class.\n    ///\n    /// For the Allow system calls, there are some invariants that are stricter\n    /// than TRD 104. These invariants are explicitly allowed by TRD 104.\n    ///\n    /// For Read-Only Allow, the aliasing invariants on the buffer are\n    /// equivalent to passing a `&[u8]` reference across the system call\n    /// boundary. In particular, that means there MUST NOT be a `&mut [u8]`\n    /// reference overlapping the passed buffer, until the buffer has been\n    /// returned by a Read-Only Allow call.\n    ///\n    /// For Read-Write Allow, the aliasing invariants on the buffer are\n    /// equivalent to passing a `&mut [u8]` reference across the system call\n    /// boundary. In particular, that means there MUST NOT be a reference\n    /// overlapping the passed buffer, until the buffer has been returned by a\n    /// Read-Write Allow call.\n    unsafe fn syscall4<const CLASS: usize>(_: [Register; 4]) -> [Register; 4];\n}\n"
  },
  {
    "path": "platform/src/register.rs",
    "content": "/// `Register` represents the value of a register used in Tock's syscall ABI. It\n/// can contain integer values as well as pointer values.\n///\n/// `Register` currently wraps a raw pointer, but that is not a stable guarantee\n/// and users should not rely on it. However, `Register` does guarantee that the\n/// type it wraps is a valid operand type for inline assembly.\n///\n/// If a pointer is converted to a `Register`, that `Register` has that\n/// pointer's provenance. The provenance is not exposed. If an integer is\n/// converted to a `Register`, that `Register` has no provenance. When a\n/// `Register` with provenance is converted into a pointer, that pointer carries\n/// the `Register`'s provenance. When a `Register` without provenance is\n/// converted into a pointer, that pointer has no provenance.\n// Register is repr(transparent) so that an upcall's application data can be\n// soundly passed as a Register.\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(transparent)]\npub struct Register(pub *mut ());\n\n// -----------------------------------------------------------------------------\n// Conversions to Register\n// -----------------------------------------------------------------------------\n\nimpl From<crate::ErrorCode> for Register {\n    fn from(value: crate::ErrorCode) -> Register {\n        (value as usize).into()\n    }\n}\n\nimpl From<u32> for Register {\n    fn from(value: u32) -> Register {\n        (value as usize).into()\n    }\n}\n\nimpl From<i32> for Register {\n    fn from(value: i32) -> Register {\n        (value as usize).into()\n    }\n}\n\nimpl From<usize> for Register {\n    fn from(value: usize) -> Register {\n        // TODO(Rust 1.84): We want to convert using the same semantics as\n        // core::ptr::without_provenance. However, until our MSRV is >= 1.84, we\n        // have to use an `as` cast instead. This may result in this Register\n        // converting into a pointer with provenance later on, but that\n        // shouldn't break any users of Register in practice.\n        #[cfg(not(miri))]\n        {\n            Register(value as *mut ())\n        }\n        // However, on Miri, we cannot do the conversion using an `as` cast.\n        // Fortunately, since Miri runs on nightly Rust, we can use\n        // `without_provenance_mut`.\n        #[cfg(miri)]\n        {\n            Register(core::ptr::without_provenance_mut(value))\n        }\n    }\n}\n\nimpl<T> From<*mut T> for Register {\n    fn from(value: *mut T) -> Register {\n        Register(value.cast())\n    }\n}\n\nimpl<T> From<*const T> for Register {\n    fn from(value: *const T) -> Register {\n        Register(value as *mut ())\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Infallible conversions from Register\n// -----------------------------------------------------------------------------\n\n// If we implement From<u32> on Register, then we automatically get a\n// TryFrom<Error = Infallible> implementation, which conflicts with our fallible\n// TryFrom implementation. We could choose to not implement TryFrom and instead\n// add a fallible accessor (something like \"expect_u32\"), but that seems\n// confusing. Instead, we use an inherent method for the Register -> u32\n// infallible conversion.\nimpl Register {\n    /// Casts this register to a u32, truncating it if it is larger than\n    /// u32::MAX. This conversion should be avoided in host-based test code; use\n    /// the `TryFrom<Register> for u32` implementation instead.\n    pub fn as_u32(self) -> u32 {\n        self.0 as u32\n    }\n\n    /// Casts this register to a i32, truncating it if it is larger than\n    /// 32 bits. This conversion should be avoided in host-based test code; use\n    /// the `TryFrom<Register> for i32` implementation instead.\n    pub fn as_i32(self) -> i32 {\n        self.0 as i32\n    }\n}\n\nimpl From<Register> for usize {\n    fn from(register: Register) -> usize {\n        // TODO(Rust 1.84): We want to convert using the same semantics as\n        // .addr(). Until our MSRV is >= 1.84, we have to convert using an `as`\n        // cast instead. This exposes the provenance of the pointer, which is\n        // not correct but shouldn't break any users in practice.\n        register.0 as usize\n    }\n}\n\nimpl<T> From<Register> for *mut T {\n    fn from(register: Register) -> *mut T {\n        register.0.cast()\n    }\n}\n\nimpl<T> From<Register> for *const T {\n    fn from(register: Register) -> *const T {\n        register.0 as *const T\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Fallible conversions from Register\n// -----------------------------------------------------------------------------\n\n/// Converts a `Register` to a `u32`. Returns an error if the `Register`'s value\n/// is larger than `u32::MAX`. This is intended for use in host-based tests; in\n/// Tock process binary code, use Register::as_u32 instead.\nimpl TryFrom<Register> for u32 {\n    type Error = core::num::TryFromIntError;\n\n    fn try_from(register: Register) -> Result<u32, core::num::TryFromIntError> {\n        usize::from(register).try_into()\n    }\n}\n"
  },
  {
    "path": "platform/src/return_variant.rs",
    "content": "// TODO: Re-evaluate whether u32 is the correct type to wrap. Maybe it should\n// wrap a Register instead? Also, double-check that ReturnVariant is providing\n// useful type-safety.\n\n/// `ReturnVariant` describes what value type the kernel has returned.\n// ReturnVariant is not an enum so that it can be converted from a u32 for free.\n// TODO: Add a ufmt debug implementation for use by process binaries.\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub struct ReturnVariant(u32);\n\nimpl From<u32> for ReturnVariant {\n    fn from(value: u32) -> ReturnVariant {\n        ReturnVariant(value)\n    }\n}\n\nimpl From<ReturnVariant> for crate::Register {\n    fn from(return_variant: ReturnVariant) -> crate::Register {\n        return_variant.0.into()\n    }\n}\n\nimpl From<ReturnVariant> for u32 {\n    fn from(return_variant: ReturnVariant) -> u32 {\n        return_variant.0\n    }\n}\n\npub const FAILURE: ReturnVariant = ReturnVariant(0);\npub const FAILURE_U32: ReturnVariant = ReturnVariant(1);\npub const FAILURE_2_U32: ReturnVariant = ReturnVariant(2);\npub const FAILURE_U64: ReturnVariant = ReturnVariant(3);\npub const SUCCESS: ReturnVariant = ReturnVariant(128);\npub const SUCCESS_U32: ReturnVariant = ReturnVariant(129);\npub const SUCCESS_2_U32: ReturnVariant = ReturnVariant(130);\npub const SUCCESS_U64: ReturnVariant = ReturnVariant(131);\npub const SUCCESS_3_U32: ReturnVariant = ReturnVariant(132);\npub const SUCCESS_U32_U64: ReturnVariant = ReturnVariant(133);\n"
  },
  {
    "path": "platform/src/share/handle.rs",
    "content": "use crate::share::List;\nuse core::marker::PhantomData;\n\n/// A `Handle`'s existence indicates two things:\n///\n/// 1. The specified List exists.\n/// 2. The specified List will be cleaned up (via `Drop::drop`) rather than\n///    leaked or forgotten.\n///\n/// `Handle`s are used to call system calls, and should generally be created by\n/// using `share::scope`.\npub struct Handle<'handle, L: List> {\n    // Handle acts like a &'handle L, so set its variance accordingly. Note that\n    // the most important lifetime -- the lifetime the share can live for -- is\n    // a parameter of L, not Handle.\n    //\n    // Additionally, _list is a private member, which prevents code outside this\n    // module from constructing a Handle without calling Handle's constructors.\n    _list: PhantomData<&'handle L>,\n}\n\n// We can't #[derive(Clone, Copy)] because derive's implementations of Clone and\n// Copy have `L: Clone` and `L: Copy` constraints, respectively. We don't want\n// those constraints, so we manually implement Clone and Copy.\nimpl<'handle, L: List> Clone for Handle<'handle, L> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<'handle, L: List> Copy for Handle<'handle, L> {}\n\nimpl<'handle, L: List> Handle<'handle, L> {\n    /// Constructs a new `Handle`, typing its lifetime to the provided list.\n    ///\n    /// # Safety\n    /// The calling code must guarantee that `Drop::drop` is called on `_list`'s\n    /// pointee before `_list`'s pointee becomes invalid. In other words,\n    /// `_list`'s pointee may not be forgotten or leaked.\n    pub unsafe fn new(_list: &'handle L) -> Self {\n        Handle { _list: PhantomData }\n    }\n\n    /// Converts this `Handle` to a `Handle` of a different type. Used to create\n    /// a handle to a sub-object of this handle's `L`.\n    ///\n    /// # Safety\n    /// The calling code must guarantee that an `Other` exists, and that\n    /// `Drop::drop` will be called on the `Other` before the `Other` becomes\n    /// invalid. In general, the `Other` should be contained inside the `L`, so\n    /// `Drop::drop` is executed on the `Other` when the `L` is dropped.\n    pub unsafe fn change_type<Other: List>(self) -> Handle<'handle, Other> {\n        Handle { _list: PhantomData }\n    }\n\n    /// Splits this `Handle` into a list of handles to sub-lists of `L`. Used\n    /// when `L` is a tuple of shares, to obtain handles to the individual\n    /// shares.\n    pub fn split(self) -> L::SplitHandles\n    where\n        L: SplittableHandle<'handle>,\n    {\n        L::split(self)\n    }\n}\n\n/// A trait implemented by `share::List`s that can be divided into sub-lists.\n/// `SplittableHandle` should not be used directly; instead, callers should use\n/// `Handle::split`.\npub trait SplittableHandle<'handle>: List {\n    /// SplitHandles should be a tuple of Handle types, i.e. (Handle<>,\n    /// Handle<>, ...).\n    type SplitHandles;\n\n    /// Split the specified handle into sub-handles. Implementations of `split`\n    /// should use `Handle::change_type` to create the sub-handles.\n    fn split(handle: Handle<'handle, Self>) -> Self::SplitHandles;\n}\n"
  },
  {
    "path": "platform/src/share/mod.rs",
    "content": "//! `share` contains tools for safely sharing objects (such as buffers and\n//! upcalls) with the Tock kernel.\n\nmod handle;\nmod tuple_impls;\n\npub use handle::{Handle, SplittableHandle};\n\n/// Creates a scope in which objects may safely be shared with the kernel.\npub fn scope<L: List, Output, F: FnOnce(Handle<L>) -> Output>(fcn: F) -> Output {\n    let list = Default::default();\n    // Safety: We do not move the L out of the `list` variable. The `list`\n    // variable will be dropped at the end of the scope, immediately before the\n    // L becomes invalid.\n    fcn(unsafe { Handle::new(&list) })\n}\n\n/// A list of objects that may be shared with the kernel. `List` is implemented\n/// for system call types such as `Subscribe`, as well as (potentially-nested)\n/// tuples of such types.\npub trait List: Default {}\n\n#[cfg(test)]\nmod tests;\n"
  },
  {
    "path": "platform/src/share/tests.rs",
    "content": "use crate::share::{scope, Handle, List};\n\nstd::thread_local! {static INSTANCE_COUNT: core::cell::Cell<u64> = const {core::cell::Cell::new(0)}}\n\n// InstanceCounter increments INSTANCE_COUNT when it is constructed and\n// decrements INSTANCE_COUNT when it is dropped.\nstruct InstanceCounter {\n    _private: (),\n}\n\nimpl Default for InstanceCounter {\n    fn default() -> Self {\n        INSTANCE_COUNT.with(|cell| cell.set(cell.get() + 1));\n        Self { _private: () }\n    }\n}\n\nimpl Drop for InstanceCounter {\n    fn drop(&mut self) {\n        INSTANCE_COUNT.with(|cell| cell.set(cell.get() - 1));\n    }\n}\n\nimpl List for InstanceCounter {}\n\n#[test]\nfn list_lifetime() {\n    // INSTANCE_COUNT *should* be 0 here, but make sure it's zero in case\n    // another test case leaked an instance.\n    INSTANCE_COUNT.with(|cell| cell.set(0));\n\n    scope(|_counter: Handle<InstanceCounter>| {\n        assert_eq!(INSTANCE_COUNT.with(|cell| cell.get()), 1);\n    });\n\n    assert_eq!(INSTANCE_COUNT.with(|cell| cell.get()), 0);\n}\n\n// This test will only compile if the correct trait impls exist for tuples.\n#[test]\nfn tuple_impls() {\n    #[allow(clippy::let_unit_value)]\n    scope(|list: Handle<()>| {\n        let _empty: () = list.split();\n    });\n\n    scope(|list: Handle<((),)>| {\n        let (_empty_handle,): (Handle<()>,) = list.split();\n    });\n\n    scope(|list: Handle<((), InstanceCounter)>| {\n        let (_empty, _counter): (Handle<()>, Handle<InstanceCounter>) = list.split();\n    });\n\n    // Tests a size-12 tuple with varying List types inside it.\n    #[allow(clippy::type_complexity)]\n    scope(\n        |list: Handle<(\n            (),\n            (),\n            (),\n            (),\n            (),\n            (),\n            (),\n            (),\n            (),\n            (),\n            ((), ()),\n            InstanceCounter,\n        )>| {\n            let (\n                _empty1,\n                _empty2,\n                _empty3,\n                _empty4,\n                _empty5,\n                _empty6,\n                _empty7,\n                _empty8,\n                _empty9,\n                _empty10,\n                pair,\n                _counter,\n            ): (\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<()>,\n                Handle<((), ())>,\n                Handle<InstanceCounter>,\n            ) = list.split();\n            let (_empty11, _empty12): (Handle<()>, Handle<()>) = pair.split();\n        },\n    );\n}\n"
  },
  {
    "path": "platform/src/share/tuple_impls.rs",
    "content": "/// Implements `share::List` and `share::SplittableHandle` on tuples of various\n/// sizes.\nuse crate::share::{Handle, List, SplittableHandle};\n\n// Implement List and SplittableHandle on empty tuples, because tuple_impl only\n// works for tuples of size 1 or greater. Empty lists may be useful in generic\n// and/or macro contexts.\nimpl List for () {}\n\nimpl<'handle> SplittableHandle<'handle> for () {\n    type SplitHandles = ();\n\n    fn split(_handle: Handle<'handle, ()>) {}\n}\n\n// Provides `share::List` and `share::SplittableHandle` impls for tuples of a\n// specific size. tuple_impls! must be provided with a list of names, and will\n// generate impls for tuples of the given length.\nmacro_rules! tuple_impls {\n    ($($name:ident),*) => {\n        impl<$($name: List),*> List for ($($name),*,) {}\n\n        impl<'handle, $($name: List + 'handle),*> SplittableHandle<'handle> for ($($name),*,) {\n            type SplitHandles = ($(Handle<'handle, $name>),*,);\n\n            fn split(handle: Handle<'handle, Self>) -> Self::SplitHandles {\n                // Safety: handle guarantees that an instance of Self exists and\n                // will be cleaned up before it becomes invalid. Self is a\n                // tuple, and the types we are changing handle into are elements\n                // of that tuple, so when the tuple is cleaned up they will be\n                // cleaned up as well.\n                ($(unsafe { handle.change_type::<$name>() }),*,)\n            }\n        }\n    }\n}\n\n// Recursively calls tuple_impls for all tuples of a given length or shorter\n// (except the empty tuple, which tuple_impls doesn't support).\nmacro_rules! impl_recursive {\n    // Base case: if provided no names, do nothing.\n    () => {};\n\n    // Recursive case. Calls tuple_impls, then call ourselves with one less\n    // name.\n    ($head_name:ident$(, $($tail_names:ident),*)?) => {\n        tuple_impls!($head_name$(, $($tail_names),*)?);\n        impl_recursive!($($($tail_names),*)?);\n    };\n}\n\n// Because List depends on Default, which is only implemented for tuples of <=\n// 12 elements, we can only implement List for tuples of up to length 12.\nimpl_recursive!(A, B, C, D, E, F, G, H, I, J, K, L);\n"
  },
  {
    "path": "platform/src/subscribe.rs",
    "content": "use crate::share::List;\nuse crate::ErrorCode;\nuse crate::Syscalls;\n\n// -----------------------------------------------------------------------------\n// `Subscribe` struct\n// -----------------------------------------------------------------------------\n\n/// A `Subscribe` instance allows safe code to call Tock's Subscribe system\n/// call, by guaranteeing the upcall will be cleaned up before 'share ends. It\n/// is generally used with the `share::scope` function, which offers a safe\n/// interface for constructing `Subscribe` instances.\npub struct Subscribe<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> {\n    _syscalls: core::marker::PhantomData<S>,\n\n    // Make this struct invariant with respect to the 'share lifetime.\n    //\n    // Covariance would be unsound, as that would allow code with a\n    // `Subscribe<'static, ...>` to register an upcall that lasts for a shorter\n    // lifetime, resulting in use-after-free if the upcall is invoked.\n    // Contravariance would be sound, but is not necessary and may be confusing.\n    //\n    // Additionally, we want to have at least one private member of this struct\n    // so that code outside this module cannot construct a `Subscribe` without\n    // calling `ShareList::new`.\n    _scope: core::marker::PhantomData<core::cell::Cell<&'share ()>>,\n}\n\n// We can't derive(Default) because S is not Default, and derive(Default)\n// generates a Default implementation that requires S to be Default. Instead, we\n// manually implement Default.\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> Default\n    for Subscribe<'share, S, DRIVER_NUM, SUBSCRIBE_NUM>\n{\n    fn default() -> Self {\n        Self {\n            _syscalls: Default::default(),\n            _scope: Default::default(),\n        }\n    }\n}\n\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> Drop\n    for Subscribe<'share, S, DRIVER_NUM, SUBSCRIBE_NUM>\n{\n    fn drop(&mut self) {\n        S::unsubscribe(DRIVER_NUM, SUBSCRIBE_NUM);\n    }\n}\n\nimpl<'share, S: Syscalls, const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> List\n    for Subscribe<'share, S, DRIVER_NUM, SUBSCRIBE_NUM>\n{\n}\n\n// -----------------------------------------------------------------------------\n// `Upcall` trait\n// -----------------------------------------------------------------------------\n\n/// A Tock kernel upcall. Upcalls are registered using the Subscribe system\n/// call, and are invoked during Yield calls.\n///\n/// Each `Upcall` supports one or more subscribe IDs, which are indicated by the\n/// `SupportedIds` parameter. The types `AnySubscribeId` and `OneSubscribeId`\n/// are provided to use as `SupportedIds` parameters in `Upcall`\n/// implementations.\npub trait Upcall<SupportedIds> {\n    fn upcall(&self, arg0: u32, arg1: u32, arg2: u32);\n}\n\npub trait SupportsId<const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> {}\n\npub struct AnyId;\nimpl<const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>\n    for AnyId\n{\n}\n\npub struct OneId<const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32>;\nimpl<const DRIVER_NUM: u32, const SUBSCRIBE_NUM: u32> SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>\n    for OneId<DRIVER_NUM, SUBSCRIBE_NUM>\n{\n}\n\n// -----------------------------------------------------------------------------\n// Upcall implementations that simply store their arguments\n// -----------------------------------------------------------------------------\n\n/// An implementation of `Upcall` that sets the contained boolean value to\n/// `true` when the upcall is invoked.\nimpl Upcall<AnyId> for core::cell::Cell<bool> {\n    fn upcall(&self, _: u32, _: u32, _: u32) {\n        self.set(true);\n    }\n}\n\n/// Implemented for consistency with the other `Cell<Option<...>>` `Upcall`\n/// impls. Most users would prefer the `Cell<bool>` implementation over this\n/// impl, but this may be useful in a generic or macro context.\nimpl Upcall<AnyId> for core::cell::Cell<Option<()>> {\n    fn upcall(&self, _: u32, _: u32, _: u32) {\n        self.set(Some(()));\n    }\n}\n\n/// An `Upcall` implementation that stores its first argument when called.\nimpl Upcall<AnyId> for core::cell::Cell<Option<(u32,)>> {\n    fn upcall(&self, arg0: u32, _: u32, _: u32) {\n        self.set(Some((arg0,)));\n    }\n}\n\n/// An `Upcall` implementation that stores its first two arguments when called.\nimpl Upcall<AnyId> for core::cell::Cell<Option<(u32, u32)>> {\n    fn upcall(&self, arg0: u32, arg1: u32, _: u32) {\n        self.set(Some((arg0, arg1)));\n    }\n}\n\n/// An `Upcall` implementation that stores its arguments when called.\nimpl Upcall<AnyId> for core::cell::Cell<Option<(u32, u32, u32)>> {\n    fn upcall(&self, arg0: u32, arg1: u32, arg2: u32) {\n        self.set(Some((arg0, arg1, arg2)));\n    }\n}\n\n/// An `Upcall` implementation that interprets its first argument as a return\n/// code.\nimpl Upcall<AnyId> for core::cell::Cell<Option<Result<(), ErrorCode>>> {\n    fn upcall(&self, arg0: u32, _: u32, _: u32) {\n        self.set(Some(match arg0 {\n            0 => Ok(()),\n            _ => Err(arg0.try_into().unwrap_or(ErrorCode::Fail)),\n        }));\n    }\n}\n\n/// An `Upcall` implementation that interprets its first argument as a return\n/// code and stores its second argument when called.\nimpl Upcall<AnyId> for core::cell::Cell<Option<Result<(u32,), ErrorCode>>> {\n    fn upcall(&self, arg0: u32, arg1: u32, _: u32) {\n        self.set(Some(match arg0 {\n            0 => Ok((arg1,)),\n            _ => Err(arg0.try_into().unwrap_or(ErrorCode::Fail)),\n        }));\n    }\n}\n\n/// An `Upcall` implementation that interprets its first argument as a return\n/// code and stores its second argument when called.\nimpl Upcall<AnyId> for core::cell::Cell<Option<Result<(u32, u32), ErrorCode>>> {\n    fn upcall(&self, arg0: u32, arg1: u32, arg2: u32) {\n        self.set(Some(match arg0 {\n            0 => Ok((arg1, arg2)),\n            _ => Err(arg0.try_into().unwrap_or(ErrorCode::Fail)),\n        }));\n    }\n}\n\n#[cfg(test)]\n#[test]\nfn upcall_impls() {\n    let cell_bool = core::cell::Cell::new(false);\n    cell_bool.upcall(1, 2, 3);\n    assert!(cell_bool.get());\n\n    let cell_empty = core::cell::Cell::new(None);\n    cell_empty.upcall(1, 2, 3);\n    assert_eq!(cell_empty.get(), Some(()));\n\n    let cell_one = core::cell::Cell::new(None);\n    cell_one.upcall(1, 2, 3);\n    assert_eq!(cell_one.get(), Some((1,)));\n\n    let cell_two = core::cell::Cell::new(None);\n    cell_two.upcall(1, 2, 3);\n    assert_eq!(cell_two.get(), Some((1, 2)));\n\n    let cell_three = core::cell::Cell::new(None);\n    cell_three.upcall(1, 2, 3);\n    assert_eq!(cell_three.get(), Some((1, 2, 3)));\n\n    let cell_returncode_empty_success: core::cell::Cell<Option<Result<(), ErrorCode>>> =\n        core::cell::Cell::new(None);\n    cell_returncode_empty_success.upcall(0, 2, 3);\n    assert_eq!(cell_returncode_empty_success.get(), Some(Ok(())));\n    let cell_returncode_empty_fail: core::cell::Cell<Option<Result<(), ErrorCode>>> =\n        core::cell::Cell::new(None);\n    cell_returncode_empty_fail.upcall(1, 2, 3);\n    assert_eq!(cell_returncode_empty_fail.get(), Some(Err(ErrorCode::Fail)));\n\n    let cell_returncode_one_success: core::cell::Cell<Option<Result<(u32,), ErrorCode>>> =\n        core::cell::Cell::new(None);\n    cell_returncode_one_success.upcall(0, 2, 3);\n    assert_eq!(cell_returncode_one_success.get(), Some(Ok((2,))));\n    let cell_returncode_one_fail: core::cell::Cell<Option<Result<(u32,), ErrorCode>>> =\n        core::cell::Cell::new(None);\n    cell_returncode_one_fail.upcall(1, 2, 3);\n    assert_eq!(cell_returncode_one_fail.get(), Some(Err(ErrorCode::Fail)));\n\n    let cell_returncode_two_success: core::cell::Cell<Option<Result<(u32, u32), ErrorCode>>> =\n        core::cell::Cell::new(None);\n    cell_returncode_two_success.upcall(0, 2, 3);\n    assert_eq!(cell_returncode_two_success.get(), Some(Ok((2, 3))));\n    let cell_returncode_two_fail: core::cell::Cell<Option<Result<(u32, u32), ErrorCode>>> =\n        core::cell::Cell::new(None);\n    cell_returncode_two_fail.upcall(1, 2, 3);\n    assert_eq!(cell_returncode_two_fail.get(), Some(Err(ErrorCode::Fail)));\n}\n\n// -----------------------------------------------------------------------------\n// `Config` trait\n// -----------------------------------------------------------------------------\n\n/// `Config` configures the behavior of the Subscribe system call. It should\n/// generally be passed through by drivers, to allow application code to\n/// configure error handling.\npub trait Config {\n    /// Called if a Subscribe call succeeds and returns a non-null upcall. In\n    /// some applications, this may indicate unexpected reentrance. By default,\n    /// the non-null upcall is ignored.\n    fn returned_nonnull_upcall(_driver_num: u32, _subscribe_num: u32) {}\n}\n"
  },
  {
    "path": "platform/src/syscalls.rs",
    "content": "use crate::{\n    allow_ro, allow_rw, share, subscribe, AllowRo, AllowRw, CommandReturn, ErrorCode, RawSyscalls,\n    Subscribe, Upcall, YieldNoWaitReturn,\n};\n\n/// `Syscalls` provides safe abstractions over Tock's system calls. It is\n/// implemented for `libtock_runtime::TockSyscalls` and\n/// `libtock_unittest::fake::Kernel` (by way of `RawSyscalls`).\npub trait Syscalls: RawSyscalls + Sized {\n    // -------------------------------------------------------------------------\n    // Yield\n    // -------------------------------------------------------------------------\n\n    /// Runs the next pending callback, if a callback is pending. Unlike\n    /// `yield_wait`, `yield_no_wait` returns immediately if no callback is\n    /// pending.\n    fn yield_no_wait() -> YieldNoWaitReturn;\n\n    /// Puts the process to sleep until a callback becomes pending, invokes the\n    /// callback, then returns.\n    fn yield_wait();\n\n    // -------------------------------------------------------------------------\n    // Subscribe\n    // -------------------------------------------------------------------------\n\n    /// Registers an upcall with the kernel.\n    fn subscribe<\n        'share,\n        IDS: subscribe::SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>,\n        U: Upcall<IDS>,\n        CONFIG: subscribe::Config,\n        const DRIVER_NUM: u32,\n        const SUBSCRIBE_NUM: u32,\n    >(\n        subscribe: share::Handle<Subscribe<'share, Self, DRIVER_NUM, SUBSCRIBE_NUM>>,\n        upcall: &'share U,\n    ) -> Result<(), ErrorCode>;\n\n    /// Unregisters the upcall with the given ID. If no upcall is registered\n    /// with the given ID, `unsubscribe` does nothing.\n    fn unsubscribe(driver_num: u32, subscribe_num: u32);\n\n    // -------------------------------------------------------------------------\n    // Command\n    // -------------------------------------------------------------------------\n\n    fn command(driver_id: u32, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn;\n\n    // -------------------------------------------------------------------------\n    // Read-Write Allow\n    // -------------------------------------------------------------------------\n\n    /// Shares a read-write buffer with the kernel.\n    fn allow_rw<'share, CONFIG: allow_rw::Config, const DRIVER_NUM: u32, const BUFFER_NUM: u32>(\n        allow_rw: share::Handle<AllowRw<'share, Self, DRIVER_NUM, BUFFER_NUM>>,\n        buffer: &'share mut [u8],\n    ) -> Result<(), ErrorCode>;\n\n    /// Revokes the kernel's access to the buffer with the given ID, overwriting\n    /// it with a zero buffer. If no buffer is shared with the given ID,\n    /// `unallow_rw` does nothing.\n    fn unallow_rw(driver_num: u32, buffer_num: u32);\n\n    // -------------------------------------------------------------------------\n    // Read-Only Allow\n    // -------------------------------------------------------------------------\n\n    /// Shares a read-only buffer with the kernel.\n    fn allow_ro<'share, CONFIG: allow_ro::Config, const DRIVER_NUM: u32, const BUFFER_NUM: u32>(\n        allow_ro: share::Handle<AllowRo<'share, Self, DRIVER_NUM, BUFFER_NUM>>,\n        buffer: &'share [u8],\n    ) -> Result<(), ErrorCode>;\n\n    /// Revokes the kernel's access to the buffer with the given ID, overwriting\n    /// it with a zero buffer. If no buffer is shared with the given ID,\n    /// `unallow_ro` does nothing.\n    fn unallow_ro(driver_num: u32, buffer_num: u32);\n\n    // -------------------------------------------------------------------------\n    // Memop\n    // -------------------------------------------------------------------------\n\n    /// Changes the location of the program break to the specified address and\n    /// returns an error if it fails to do so.\n    ///\n    /// # Safety\n    /// Callers of this function must ensure that they do not pass an\n    /// address below any address that includes a currently reachable object.\n    unsafe fn memop_brk(addr: *const u8) -> Result<(), ErrorCode>;\n\n    /// Changes the location of the program break by the passed increment,\n    /// and returns the previous break address.\n    ///\n    /// # Safety\n    /// Callers of this function must ensure that they do not pass an\n    /// increment that would deallocate memory containing any currently\n    /// reachable object.\n    unsafe fn memop_sbrk(incr: i32) -> Result<*const u8, ErrorCode>;\n\n    /// Increments the program break by the passed increment,\n    /// and returns the previous break address.\n    fn memop_increment_brk(incr: u32) -> Result<*const u8, ErrorCode>;\n\n    /// Gets the address of the start of this application's RAM allocation.\n    fn memop_app_ram_start() -> Result<*const u8, ErrorCode>;\n\n    /// Tells the kernel where the start of the app stack is, to support\n    /// debugging.\n    fn memop_debug_stack_start(stack_top: *const u8) -> Result<(), ErrorCode>;\n\n    /// Tells the kernel the initial program break, to support debugging.\n    fn memop_debug_heap_start(initial_break: *const u8) -> Result<(), ErrorCode>;\n\n    // TODO: Add remaining memop() methods (3-9).\n\n    // -------------------------------------------------------------------------\n    // Exit\n    // -------------------------------------------------------------------------\n\n    fn exit_terminate(exit_code: u32) -> !;\n\n    fn exit_restart(exit_code: u32) -> !;\n}\n"
  },
  {
    "path": "platform/src/syscalls_impl.rs",
    "content": "//! Implements `Syscalls` for all types that implement `RawSyscalls`.\n\nuse crate::{\n    allow_ro, allow_rw, exit_id, exit_on_drop, return_variant, share, subscribe, syscall_class,\n    yield_id, AllowRo, AllowRw, CommandReturn, ErrorCode, RawSyscalls, Register, ReturnVariant,\n    Subscribe, Syscalls, Upcall, YieldNoWaitReturn,\n};\n\nimpl<S: RawSyscalls> Syscalls for S {\n    // -------------------------------------------------------------------------\n    // Yield\n    // -------------------------------------------------------------------------\n\n    fn yield_no_wait() -> YieldNoWaitReturn {\n        let mut flag = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n\n        unsafe {\n            // Flag can be uninitialized here because the kernel promises to\n            // only write to it, not read from it. MaybeUninit guarantees that\n            // it is safe to write a YieldNoWaitReturn into it.\n            Self::yield2([yield_id::NO_WAIT.into(), flag.as_mut_ptr().into()]);\n\n            // yield-no-wait guarantees it sets (initializes) flag before\n            // returning.\n            flag.assume_init()\n        }\n    }\n\n    fn yield_wait() {\n        // Safety: yield-wait does not return a value, which satisfies yield1's\n        // requirement. The yield-wait system call cannot trigger undefined\n        // behavior on its own in any other way.\n        unsafe {\n            Self::yield1([yield_id::WAIT.into()]);\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Subscribe\n    // -------------------------------------------------------------------------\n\n    fn subscribe<\n        'share,\n        IDS: subscribe::SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>,\n        U: Upcall<IDS>,\n        CONFIG: subscribe::Config,\n        const DRIVER_NUM: u32,\n        const SUBSCRIBE_NUM: u32,\n    >(\n        _subscribe: share::Handle<Subscribe<'share, Self, DRIVER_NUM, SUBSCRIBE_NUM>>,\n        upcall: &'share U,\n    ) -> Result<(), ErrorCode> {\n        // The upcall function passed to the Tock kernel.\n        //\n        // Safety: data must be a reference to a valid instance of U.\n        unsafe extern \"C\" fn kernel_upcall<S: Syscalls, IDS, U: Upcall<IDS>>(\n            arg0: u32,\n            arg1: u32,\n            arg2: u32,\n            data: Register,\n        ) {\n            let exit: exit_on_drop::ExitOnDrop<S> = Default::default();\n            let upcall: *const U = data.into();\n            unsafe { &*upcall }.upcall(arg0, arg1, arg2);\n            core::mem::forget(exit);\n        }\n\n        // Inner function that does the majority of the work. This is not\n        // monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size\n        // small.\n        //\n        // Safety: upcall_fcn must be kernel_upcall<S, IDS, U> and upcall_data\n        // must be a reference to an instance of U that will remain valid as\n        // long as the 'scope lifetime is alive. Can only be called if a\n        // Subscribe<'scope, S, driver_num, subscribe_num> exists.\n        unsafe fn inner<S: Syscalls, CONFIG: subscribe::Config>(\n            driver_num: u32,\n            subscribe_num: u32,\n            upcall_fcn: Register,\n            upcall_data: Register,\n        ) -> Result<(), ErrorCode> {\n            // Safety: syscall4's documentation indicates it can be used to call\n            // Subscribe. These arguments follow TRD104. kernel_upcall has the\n            // required signature. This function's preconditions mean that\n            // upcall is a reference to an instance of U that will remain valid\n            // until the 'scope lifetime is alive The existence of the\n            // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees\n            // that if this Subscribe succeeds then the upcall will be cleaned\n            // up before the 'scope lifetime ends, guaranteeing that upcall is\n            // still alive when kernel_upcall is invoked.\n            let [r0, r1, _, _] = unsafe {\n                S::syscall4::<{ syscall_class::SUBSCRIBE }>([\n                    driver_num.into(),\n                    subscribe_num.into(),\n                    upcall_fcn,\n                    upcall_data,\n                ])\n            };\n\n            let return_variant: ReturnVariant = r0.as_u32().into();\n            // TRD 104 guarantees that Subscribe returns either Success with 2\n            // U32 or Failure with 2 U32. We check the return variant by\n            // comparing against Failure with 2 U32 for 2 reasons:\n            //\n            //   1. On RISC-V with compressed instructions, it generates smaller\n            //      code. FAILURE_2_U32 has value 2, which can be loaded into a\n            //      register with a single compressed instruction, whereas\n            //      loading SUCCESS_2_U32 uses an uncompressed instruction.\n            //   2. In the event the kernel malfuctions and returns a different\n            //      return variant, the success path is actually safer than the\n            //      failure path. The failure path assumes that r1 contains an\n            //      ErrorCode, and produces UB if it has an out of range value.\n            //      Incorrectly assuming the call succeeded will not generate\n            //      unsoundness, and will likely lead to the application\n            //      hanging.\n            if return_variant == return_variant::FAILURE_2_U32 {\n                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,\n                // then r1 will contain a valid error code. ErrorCode is\n                // designed to be safely transmuted directly from a kernel error\n                // code.\n                return Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) });\n            }\n\n            // r0 indicates Success with 2 u32s. Confirm the null upcall was\n            // returned, and it if wasn't then call the configured function.\n            // We're relying on the optimizer to remove this branch if\n            // returned_nonnull_upcall is a no-op.\n            // Note: TRD 104 specifies that the null upcall has address 0,\n            // not necessarily a null pointer.\n            let returned_upcall: usize = r1.into();\n            if returned_upcall != 0usize {\n                CONFIG::returned_nonnull_upcall(driver_num, subscribe_num);\n            }\n            Ok(())\n        }\n\n        let upcall_fcn = (kernel_upcall::<S, IDS, U> as *const ()).into();\n        let upcall_data = (upcall as *const U).into();\n        // Safety: upcall's type guarantees it is a reference to a U that will\n        // remain valid for at least the 'scope lifetime. _subscribe is a\n        // reference to a Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM>,\n        // proving one exists. upcall_fcn and upcall_data are derived in ways\n        // that satisfy inner's requirements.\n        unsafe { inner::<Self, CONFIG>(DRIVER_NUM, SUBSCRIBE_NUM, upcall_fcn, upcall_data) }\n    }\n\n    fn unsubscribe(driver_num: u32, subscribe_num: u32) {\n        unsafe {\n            // syscall4's documentation indicates it can be used to call\n            // Subscribe. The upcall pointer passed is the null upcall, which\n            // cannot cause undefined behavior on its own.\n            Self::syscall4::<{ syscall_class::SUBSCRIBE }>([\n                driver_num.into(),\n                subscribe_num.into(),\n                0usize.into(),\n                0usize.into(),\n            ]);\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Command\n    // -------------------------------------------------------------------------\n\n    fn command(driver_id: u32, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn {\n        unsafe {\n            // syscall4's documentation indicates it can be used to call\n            // Command. The Command system call cannot trigger undefined\n            // behavior on its own.\n            let [r0, r1, r2, r3] = Self::syscall4::<{ syscall_class::COMMAND }>([\n                driver_id.into(),\n                command_id.into(),\n                argument0.into(),\n                argument1.into(),\n            ]);\n\n            // Because r0 and r1 are returned directly from the kernel, we are\n            // guaranteed that if r0 represents a failure variant then r1 is an\n            // error code.\n            CommandReturn::new(r0.as_u32().into(), r1.as_u32(), r2.as_u32(), r3.as_u32())\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Read-Write Allow\n    // -------------------------------------------------------------------------\n\n    fn allow_rw<'share, CONFIG: allow_rw::Config, const DRIVER_NUM: u32, const BUFFER_NUM: u32>(\n        _allow_rw: share::Handle<AllowRw<'share, Self, DRIVER_NUM, BUFFER_NUM>>,\n        buffer: &'share mut [u8],\n    ) -> Result<(), ErrorCode> {\n        // Inner function that does the majority of the work. This is not\n        // monomorphized over DRIVER_NUM and BUFFER_NUM to keep code size small.\n        //\n        // Safety: A share::Handle<AllowRw<'share, S, driver_num, buffer_num>>\n        // must exist, and `buffer` must last for at least the 'share lifetime.\n        unsafe fn inner<S: Syscalls, CONFIG: allow_rw::Config>(\n            driver_num: u32,\n            buffer_num: u32,\n            buffer: &mut [u8],\n        ) -> Result<(), ErrorCode> {\n            // Safety: syscall4's documentation indicates it can be used to call\n            // Read-Write Allow. These arguments follow TRD104.\n            let [r0, r1, r2, _] = unsafe {\n                S::syscall4::<{ syscall_class::ALLOW_RW }>([\n                    driver_num.into(),\n                    buffer_num.into(),\n                    buffer.as_mut_ptr().into(),\n                    buffer.len().into(),\n                ])\n            };\n\n            let return_variant: ReturnVariant = r0.as_u32().into();\n            // TRD 104 guarantees that Read-Write Allow returns either Success\n            // with 2 U32 or Failure with 2 U32. We check the return variant by\n            // comparing against Failure with 2 U32 for 2 reasons:\n            //\n            //   1. On RISC-V with compressed instructions, it generates smaller\n            //      code. FAILURE_2_U32 has value 2, which can be loaded into a\n            //      register with a single compressed instruction, whereas\n            //      loading SUCCESS_2_U32 uses an uncompressed instruction.\n            //   2. In the event the kernel malfuctions and returns a different\n            //      return variant, the success path is actually safer than the\n            //      failure path. The failure path assumes that r1 contains an\n            //      ErrorCode, and produces UB if it has an out of range value.\n            //      Incorrectly assuming the call succeeded will not generate\n            //      unsoundness, and will likely lead to the application\n            //      panicing.\n            if return_variant == return_variant::FAILURE_2_U32 {\n                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,\n                // then r1 will contain a valid error code. ErrorCode is\n                // designed to be safely transmuted directly from a kernel error\n                // code.\n                return Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) });\n            }\n\n            // r0 indicates Success with 2 u32s. Confirm a zero buffer was\n            // returned, and it if wasn't then call the configured function.\n            // We're relying on the optimizer to remove this branch if\n            // returned_nozero_buffer is a no-op.\n            let returned_buffer: (usize, usize) = (r1.into(), r2.into());\n            if returned_buffer != (0, 0) {\n                CONFIG::returned_nonzero_buffer(driver_num, buffer_num);\n            }\n            Ok(())\n        }\n\n        // Safety: The presence of the share::Handle<AllowRw<'share, ...>>\n        // guarantees that an AllowRw exists and will clean up this Allow ID\n        // before the 'share lifetime ends.\n        unsafe { inner::<Self, CONFIG>(DRIVER_NUM, BUFFER_NUM, buffer) }\n    }\n\n    fn unallow_rw(driver_num: u32, buffer_num: u32) {\n        unsafe {\n            // syscall4's documentation indicates it can be used to call\n            // Read-Write Allow. The buffer passed has 0 length, which cannot\n            // cause undefined behavior on its own.\n            Self::syscall4::<{ syscall_class::ALLOW_RW }>([\n                driver_num.into(),\n                buffer_num.into(),\n                0usize.into(),\n                0usize.into(),\n            ]);\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Read-Only Allow\n    // -------------------------------------------------------------------------\n\n    fn allow_ro<'share, CONFIG: allow_ro::Config, const DRIVER_NUM: u32, const BUFFER_NUM: u32>(\n        _allow_ro: share::Handle<AllowRo<'share, Self, DRIVER_NUM, BUFFER_NUM>>,\n        buffer: &'share [u8],\n    ) -> Result<(), ErrorCode> {\n        // Inner function that does the majority of the work. This is not\n        // monomorphized over DRIVER_NUM and BUFFER_NUM to keep code size small.\n        //\n        // Security note: The syscall driver will retain read-only access to\n        // `*buffer` until this Allow ID is unallowed or overwritten via another\n        // Allow call. Therefore the caller must ensure the Allow ID is\n        // unallowed or overwritten before `*buffer` is deallocated, to avoid\n        // leaking newly-allocated information at the same address as `*buffer`.\n        fn inner<S: Syscalls, CONFIG: allow_ro::Config>(\n            driver_num: u32,\n            buffer_num: u32,\n            buffer: &[u8],\n        ) -> Result<(), ErrorCode> {\n            // Safety: syscall4's documentation indicates it can be used to call\n            // Read-Only Allow. These arguments follow TRD104.\n            let [r0, r1, r2, _] = unsafe {\n                S::syscall4::<{ syscall_class::ALLOW_RO }>([\n                    driver_num.into(),\n                    buffer_num.into(),\n                    buffer.as_ptr().into(),\n                    buffer.len().into(),\n                ])\n            };\n\n            let return_variant: ReturnVariant = r0.as_u32().into();\n            // TRD 104 guarantees that Read-Only Allow returns either Success\n            // with 2 U32 or Failure with 2 U32. We check the return variant by\n            // comparing against Failure with 2 U32 for 2 reasons:\n            //\n            //   1. On RISC-V with compressed instructions, it generates smaller\n            //      code. FAILURE_2_U32 has value 2, which can be loaded into a\n            //      register with a single compressed instruction, whereas\n            //      loading SUCCESS_2_U32 uses an uncompressed instruction.\n            //   2. In the event the kernel malfuctions and returns a different\n            //      return variant, the success path is actually safer than the\n            //      failure path. The failure path assumes that r1 contains an\n            //      ErrorCode, and produces UB if it has an out of range value.\n            //      Incorrectly assuming the call succeeded will not generate\n            //      unsoundness, and will likely lead to the application\n            //      panicing.\n            if return_variant == return_variant::FAILURE_2_U32 {\n                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,\n                // then r1 will contain a valid error code. ErrorCode is\n                // designed to be safely transmuted directly from a kernel error\n                // code.\n                return Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) });\n            }\n\n            // r0 indicates Success with 2 u32s. Confirm a zero buffer was\n            // returned, and it if wasn't then call the configured function.\n            // We're relying on the optimizer to remove this branch if\n            // returned_nozero_buffer is a no-op.\n            let returned_buffer: (usize, usize) = (r1.into(), r2.into());\n            if returned_buffer != (0, 0) {\n                CONFIG::returned_nonzero_buffer(driver_num, buffer_num);\n            }\n            Ok(())\n        }\n\n        // Security: The presence of the share::Handle<AllowRo<'share, ...>>\n        // guarantees that an AllowRo exists and will clean up this Allow ID\n        // before the 'share lifetime ends.\n        inner::<Self, CONFIG>(DRIVER_NUM, BUFFER_NUM, buffer)\n    }\n\n    fn unallow_ro(driver_num: u32, buffer_num: u32) {\n        unsafe {\n            // syscall4's documentation indicates it can be used to call\n            // Read-Only Allow. The buffer passed has 0 length, which cannot\n            // cause undefined behavior on its own.\n            Self::syscall4::<{ syscall_class::ALLOW_RO }>([\n                driver_num.into(),\n                buffer_num.into(),\n                0usize.into(),\n                0usize.into(),\n            ]);\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Memop\n    // -------------------------------------------------------------------------\n\n    // Safety: Callers of this function must ensure that they do not pass an\n    // address below any address that includes a currently reachable object.\n    unsafe fn memop_brk(addr: *const u8) -> Result<(), ErrorCode> {\n        // Safety: syscall2's documentation indicates it can be used to call Memop.\n        let [r0, r1] =\n            unsafe { Self::syscall2::<{ syscall_class::MEMOP }>([0u32.into(), addr.into()]) };\n        let return_variant: ReturnVariant = r0.as_u32().into();\n        // TRD 104 guarantees that memop 0, 10, and 11 return either Success\n        // or Failure. We check the return variant by comparing against Failure\n        // for 2 reasons:\n        //\n        //   1. On RISC-V with compressed instructions, it generates smaller\n        //      code. FAILURE has value 0, which can be loaded into a\n        //      register with a single compressed instruction, whereas\n        //      loading SUCCESS uses an uncompressed instruction.\n        //   2. In the event the kernel malfunctions and returns a different\n        //      return variant, the success path is actually safer than the\n        //      failure path. The failure path assumes that r1 contains an\n        //      ErrorCode, and produces UB if it has an out of range value.\n        if return_variant == return_variant::FAILURE {\n            // Safety: TRD 104 guarantees that if r0 is Failure,\n            // then r1 will contain a valid error code. ErrorCode is\n            // designed to be safely transmuted directly from a kernel error\n            // code.\n            Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) })\n        } else {\n            Ok(())\n        }\n    }\n\n    // Safety: Callers of this function must ensure that they do not pass an\n    // increment that would deallocate memory containing any currently\n    // reachable object.\n    unsafe fn memop_sbrk(incr: i32) -> Result<*const u8, ErrorCode> {\n        // Safety: syscall2's documentation indicates it can be used to call Memop.\n        let [r0, r1] =\n            unsafe { Self::syscall2::<{ syscall_class::MEMOP }>([1u32.into(), incr.into()]) };\n        let return_variant: ReturnVariant = r0.as_u32().into();\n        // TRD 104 guarantees that memop 1, returns either Success with U32\n        // or Failure. We check the return variant by comparing against Failure\n        // for 1 reason:\n        //\n        //   1. On RISC-V with compressed instructions, it generates smaller\n        //      code. FAILURE has value 0, which can be loaded into a\n        //      register with a single compressed instruction, whereas\n        //      loading SUCCESS_U32 uses an uncompressed instruction.\n        if return_variant == return_variant::FAILURE {\n            // Safety: TRD 104 guarantees that if r0 is Failure,\n            // then r1 will contain a valid error code. ErrorCode is\n            // designed to be safely transmuted directly from a kernel error\n            // code.\n            Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) })\n        } else {\n            Ok(r1.into())\n        }\n    }\n\n    fn memop_increment_brk(incr: u32) -> Result<*const u8, ErrorCode> {\n        // Safety: memop_sbrk is safe if the passed increment is positive\n        unsafe { Self::memop_sbrk(i32::try_from(incr).map_err(|_| ErrorCode::Invalid)?) }\n    }\n\n    fn memop_app_ram_start() -> Result<*const u8, ErrorCode> {\n        // Safety: syscall1's documentation indicates it can be used to call Memop operations\n        // that only accept a memop operation number.\n        let [r0, r1] = unsafe { Self::syscall1::<{ syscall_class::MEMOP }>([2u32.into()]) };\n        let return_variant: ReturnVariant = r0.as_u32().into();\n        // TRD 104 guarantees that memop 2 returns either Success\n        // or Failure. We check the return variant by comparing against Failure\n        // for 1 reason:\n        //\n        //   1. On RISC-V with compressed instructions, it generates smaller\n        //      code. FAILURE has value 0, which can be loaded into a\n        //      register with a single compressed instruction, whereas\n        //      loading SUCCESS_U32 uses an uncompressed instruction.\n        if return_variant == return_variant::FAILURE {\n            // Safety: TRD 104 guarantees that if r0 is Failure,\n            // then r1 will contain a valid error code. ErrorCode is\n            // designed to be safely transmuted directly from a kernel error\n            // code.\n            Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) })\n        } else {\n            Ok(r1.into())\n        }\n    }\n\n    fn memop_debug_stack_start(stack_top: *const u8) -> Result<(), ErrorCode> {\n        // Safety: syscall2's documentation indicates it can be used to call Memop.\n        let [r0, r1] =\n            unsafe { Self::syscall2::<{ syscall_class::MEMOP }>([10u32.into(), stack_top.into()]) };\n        let return_variant: ReturnVariant = r0.as_u32().into();\n        // TRD 104 guarantees that memop 0, 10, and 11 return either Success\n        // or Failure. We check the return variant by comparing against Failure\n        // for 2 reasons:\n        //\n        //   1. On RISC-V with compressed instructions, it generates smaller\n        //      code. FAILURE has value 0, which can be loaded into a\n        //      register with a single compressed instruction, whereas\n        //      loading SUCCESS uses an uncompressed instruction.\n        //   2. In the event the kernel malfunctions and returns a different\n        //      return variant, the success path is actually safer than the\n        //      failure path. The failure path assumes that r1 contains an\n        //      ErrorCode, and produces UB if it has an out of range value.\n        if return_variant == return_variant::FAILURE {\n            // Safety: TRD 104 guarantees that if r0 is Failure,\n            // then r1 will contain a valid error code. ErrorCode is\n            // designed to be safely transmuted directly from a kernel error\n            // code.\n            Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) })\n        } else {\n            Ok(())\n        }\n    }\n\n    fn memop_debug_heap_start(initial_break: *const u8) -> Result<(), ErrorCode> {\n        // Safety: syscall2's documentation indicates it can be used to call Memop.\n        let [r0, r1] = unsafe {\n            Self::syscall2::<{ syscall_class::MEMOP }>([11u32.into(), initial_break.into()])\n        };\n        let return_variant: ReturnVariant = r0.as_u32().into();\n        // TRD 104 guarantees that memop 0, 10, and 11 return either Success\n        // or Failure. We check the return variant by comparing against Failure\n        // for 2 reasons:\n        //\n        //   1. On RISC-V with compressed instructions, it generates smaller\n        //      code. FAILURE has value 0, which can be loaded into a\n        //      register with a single compressed instruction, whereas\n        //      loading SUCCESS uses an uncompressed instruction.\n        //   2. In the event the kernel malfunctions and returns a different\n        //      return variant, the success path is actually safer than the\n        //      failure path. The failure path assumes that r1 contains an\n        //      ErrorCode, and produces UB if it has an out of range value.\n        if return_variant == return_variant::FAILURE {\n            // Safety: TRD 104 guarantees that if r0 is Failure,\n            // then r1 will contain a valid error code. ErrorCode is\n            // designed to be safely transmuted directly from a kernel error\n            // code.\n            Err(unsafe { core::mem::transmute::<u32, ErrorCode>(r1.as_u32()) })\n        } else {\n            Ok(())\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Exit\n    // -------------------------------------------------------------------------\n\n    fn exit_terminate(exit_code: u32) -> ! {\n        unsafe {\n            // syscall2's documentation indicates it can be used to call Exit.\n            // The exit system call cannot trigger undefined behavior on its\n            // own.\n            Self::syscall2::<{ syscall_class::EXIT }>([\n                exit_id::TERMINATE.into(),\n                exit_code.into(),\n            ]);\n            // TRD104 indicates that exit-terminate MUST always succeed and so\n            // never return.\n            core::hint::unreachable_unchecked()\n        }\n    }\n\n    fn exit_restart(exit_code: u32) -> ! {\n        unsafe {\n            // syscall2's documentation indicates it can be used to call Exit.\n            // The exit system call cannot trigger undefined behavior on its\n            // own.\n            Self::syscall2::<{ syscall_class::EXIT }>([exit_id::RESTART.into(), exit_code.into()]);\n            // TRD104 indicates that exit-restart MUST always succeed and so\n            // never return.\n            core::hint::unreachable_unchecked()\n        }\n    }\n}\n"
  },
  {
    "path": "platform/src/termination.rs",
    "content": "//! Definition of the Termination trait. The main() function (set using set_main!())\n//! must return a type that implements Termination.\n\nuse crate::{ErrorCode, Syscalls};\n\npub trait Termination {\n    fn complete<S: Syscalls>(self) -> !;\n}\n\nimpl Termination for () {\n    fn complete<S: Syscalls>(self) -> ! {\n        S::exit_terminate(0)\n    }\n}\n\nimpl Termination for Result<(), ErrorCode> {\n    fn complete<S: Syscalls>(self) -> ! {\n        let exit_code = match self {\n            Ok(()) => 0,\n            Err(ec) => ec as u32,\n        };\n        S::exit_terminate(exit_code);\n    }\n}\n"
  },
  {
    "path": "platform/src/yield_types.rs",
    "content": "/// The return value from a yield_no_wait call.\n// Calling yield-no-wait passes a *mut YieldNoWaitReturn to the kernel, which\n// the kernel writes to. We cannot safely pass a `*mut bool` to the kernel,\n// because the representation of `bool` in Rust is undefined (although it is\n// likely false == 0, true == 1, based on `bool`'s conversions). Using *mut\n// YieldNoWaitReturn rather than a *mut u8 allows the compiler to assume the\n// kernel will never write a value other than 0 or 1 into the pointee. Assuming\n// the likely representation of `bool`, this makes the conversion into `bool`\n// free.\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(u8)]\npub enum YieldNoWaitReturn {\n    NoUpcall = 0,\n    Upcall = 1,\n}\n"
  },
  {
    "path": "runner/Cargo.toml",
    "content": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ndescription = \"\"\"Tool used to run libtock-rs process binaries.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nname = \"runner\"\npublish = false\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[dependencies]\nclap = { features = [\"derive\"], version = \"3.2.6\" }\nelf = \"0.0.10\"\nlibc = \"0.2.113\"\ntermion = \"1.5.6\"\n"
  },
  {
    "path": "runner/src/elf2tab.rs",
    "content": "use super::Cli;\nuse std::fs::{metadata, remove_file};\nuse std::io::ErrorKind;\nuse std::path::PathBuf;\nuse std::process::Command;\n\nfn get_platform_architecture(platform: &str) -> Option<&'static str> {\n    match platform {\n        \"raspberry_pi_pico\" | \"pico_explorer_base\" | \"nano_rp2040_connect\" => Some(\"cortex-m0\"),\n        \"apollo3\"\n        | \"clue_nrf52840\"\n        | \"hail\"\n        | \"imix\"\n        | \"microbit_v2\"\n        | \"msp432\"\n        | \"nano33ble\"\n        | \"nrf52\"\n        | \"nrf52840\"\n        | \"nucleo_f429zi\"\n        | \"nucleo_f446re\"\n        | \"stm32f3discovery\"\n        | \"stm32f412gdiscovery\" => Some(\"cortex-m4\"),\n        \"imxrt1050\" | \"teensy40\" => Some(\"cortex-m7\"),\n        \"opentitan\" | \"esp32_c3_devkitm_1\" => Some(\"riscv32imc\"),\n        \"hifive1\" | \"qemu_rv32_virt\" => Some(\"riscv32imac\"),\n        _ => None,\n    }\n}\n\n// Converts the ELF file specified on the command line into TBF and TAB files,\n// and returns the paths to those files.\npub fn convert_elf(cli: &Cli, platform: &str) -> OutFiles {\n    let package_name = cli.elf.file_stem().expect(\"ELF must be a file\");\n    let mut tab_path = cli.elf.clone();\n    tab_path.set_extension(\"tab\");\n    if cli.verbose {\n        println!(\"Package name: {package_name:?}\");\n        println!(\"TAB path: {}\", tab_path.display());\n    }\n    let stack_size = read_stack_size(cli);\n    let elf = cli.elf.as_os_str();\n    let mut tbf_path = cli.elf.clone();\n    tbf_path.set_extension(\"tbf\");\n    let architecture =\n        get_platform_architecture(platform).expect(\"Failed to determine ELF's architecture\");\n    if cli.verbose {\n        println!(\"ELF file: {elf:?}\");\n        println!(\"TBF path: {}\", tbf_path.display());\n    }\n\n    // If elf2tab returns a successful status but does not write to the TBF\n    // file, then we run the risk of using an outdated TBF file, creating a\n    // hard-to-debug situation. Therefore, we delete the TBF file, forcing\n    // elf2tab to create it, and later verify that it exists.\n    if let Err(io_error) = remove_file(&tbf_path) {\n        // Ignore file-no-found errors, panic on any other error.\n        if io_error.kind() != ErrorKind::NotFound {\n            panic!(\"Unable to remove the TBF file. Error: {io_error}\");\n        }\n    }\n\n    let mut command = Command::new(\"elf2tab\");\n    #[rustfmt::skip]\n    command.args([\n        // TODO: libtock-rs' crates are designed for Tock 2.1's Allow interface,\n        // so we should increment this as soon as the Tock kernel will accept a\n        // 2.1 app.\n        \"--kernel-major\".as_ref(), \"2\".as_ref(),\n        \"--kernel-minor\".as_ref(), \"0\".as_ref(),\n        \"-n\".as_ref(), package_name,\n        \"-o\".as_ref(), tab_path.as_os_str(),\n        \"--stack\".as_ref(), stack_size.as_ref(),\n        format!(\"{},{}\", elf.to_str().unwrap(), architecture).as_ref(),\n    ]);\n    if cli.verbose {\n        command.arg(\"-v\");\n        println!(\"elf2tab command: {command:?}\");\n        println!(\"Spawning elf2tab\");\n    }\n    let mut child = command.spawn().expect(\"failed to spawn elf2tab\");\n    let status = child.wait().expect(\"failed to wait for elf2tab\");\n    if cli.verbose {\n        println!(\"elf2tab finished. {status}\");\n    }\n    assert!(status.success(), \"elf2tab returned an error. {status}\");\n\n    // Verify that elf2tab created the TBF file, and that it is a file.\n    match metadata(&tbf_path) {\n        Err(io_error) => {\n            if io_error.kind() == ErrorKind::NotFound {\n                panic!(\"elf2tab did not create {}\", tbf_path.display());\n            }\n            panic!(\n                \"Unable to query metadata for {}: {}\",\n                tbf_path.display(),\n                io_error\n            );\n        }\n        Ok(metadata) => {\n            assert!(metadata.is_file(), \"{} is not a file\", tbf_path.display());\n        }\n    }\n\n    OutFiles { tab_path, tbf_path }\n}\n\n// Paths to the files output by elf2tab.\npub struct OutFiles {\n    pub tab_path: PathBuf,\n    pub tbf_path: PathBuf,\n}\n\n// Reads the stack size, and returns it as a String for use on elf2tab's command\n// line.\nfn read_stack_size(cli: &Cli) -> String {\n    let file = elf::File::open_path(&cli.elf).expect(\"Unable to open ELF\");\n    for section in file.sections {\n        // This section name comes from runtime/libtock_layout.ld, and it\n        // matches the size (and location) of the process binary's stack.\n        if section.shdr.name == \".stack\" {\n            let stack_size = section.shdr.size.to_string();\n            if cli.verbose {\n                println!(\"Found .stack section, size: {stack_size}\");\n            }\n            return stack_size;\n        }\n    }\n\n    panic!(\"Unable to find the .stack section in {}\", cli.elf.display());\n}\n"
  },
  {
    "path": "runner/src/main.rs",
    "content": "mod elf2tab;\nmod output_processor;\nmod qemu;\nmod tockloader;\n\nuse clap::{Parser, ValueEnum};\nuse std::env::{var, VarError};\nuse std::path::PathBuf;\n\n/// Converts ELF binaries into Tock Binary Format binaries and runs them on a\n/// Tock system.\n#[derive(Debug, Parser)]\npub struct Cli {\n    /// Where to deploy the process binary. If not specified, runner will only\n    /// make a TBF file and not attempt to run it.\n    #[clap(action, long, short, value_enum)]\n    deploy: Option<Deploy>,\n\n    /// The executable to convert into Tock Binary Format and run.\n    #[clap(action)]\n    elf: PathBuf,\n\n    /// Whether to output verbose debugging information to the console.\n    #[clap(long, short, action)]\n    verbose: bool,\n}\n\n#[derive(ValueEnum, Clone, Copy, Debug)]\npub enum Deploy {\n    Qemu,\n    Tockloader,\n}\n\nfn main() {\n    let cli = Cli::parse();\n    let platform = match var(\"LIBTOCK_PLATFORM\") {\n        Err(VarError::NotPresent) => {\n            panic!(\"LIBTOCK_PLATFORM must be specified to deploy\")\n        }\n        Err(VarError::NotUnicode(platform)) => {\n            panic!(\"Non-UTF-8 LIBTOCK_PLATFORM value: {platform:?}\")\n        }\n        Ok(platform) => platform,\n    };\n    if cli.verbose {\n        println!(\"Detected platform {platform}\");\n    }\n    let paths = elf2tab::convert_elf(&cli, &platform);\n    let deploy = match cli.deploy {\n        None => return,\n        Some(deploy) => deploy,\n    };\n    let child = match deploy {\n        Deploy::Qemu => qemu::deploy(&cli, platform, paths.tbf_path),\n        Deploy::Tockloader => tockloader::deploy(&cli, platform, paths.tab_path),\n    };\n    output_processor::process(&cli, child);\n}\n"
  },
  {
    "path": "runner/src/output_processor.rs",
    "content": "use super::Cli;\nuse libc::{kill, pid_t, SIGINT};\nuse std::io::{stderr, stdin, stdout, BufRead, BufReader, ErrorKind, Stdout, Write};\nuse std::process::Child;\nuse std::thread::spawn;\nuse termion::raw::{IntoRawMode, RawTerminal};\n\n/// Reads the console messages from `child`'s standard output, sending SIGTERM\n/// to the child when the process is terminated.\npub fn process(cli: &Cli, mut child: Child) {\n    let raw_mode = forward_stdin_if_piped(&mut child);\n    forward_stderr_if_piped(&mut child, raw_mode.is_some());\n    let mut to_print = Vec::new();\n    let mut reader = BufReader::new(child.stdout.as_mut().expect(\"Child's stdout not piped.\"));\n    loop {\n        let buffer = reader\n            .fill_buf()\n            .expect(\"Unable to read from child process.\");\n        if buffer.is_empty() {\n            // The child process has closed its stdout, likely by exiting.\n            break;\n        }\n        // Print the bytes received over stdout. If the terminal is in raw mode,\n        // translate '\\n' into '\\r\\n'.\n        for &byte in buffer {\n            if raw_mode.is_some() && byte == b'\\n' {\n                to_print.push(b'\\r');\n            }\n            to_print.push(byte);\n        }\n        let stdout = stdout();\n        let mut lock = stdout.lock();\n        lock.write_all(&to_print)\n            .expect(\"Unable to echo child's stdout.\");\n        let _ = lock.flush();\n        drop(lock);\n        to_print.clear();\n\n        let buffer_len = buffer.len();\n        reader.consume(buffer_len);\n    }\n    if cli.verbose {\n        println!(\"Waiting for child process.\\r\");\n    }\n    let status = child.wait().expect(\"Unable to wait for child process\");\n    drop(raw_mode);\n    assert!(\n        status.success(),\n        \"Child process did not exit successfully. {status}\"\n    );\n}\n\n// If child's stdin is piped, this sets the terminal to raw mode and spawns a\n// thread that forwards our stdin to child's stdin. The thread sends SIGINT to\n// the child if Ctrl+C is pressed. Returns a RawTerminal, which reverts the\n// terminal to its previous configuration on drop.\nfn forward_stdin_if_piped(child: &mut Child) -> Option<RawTerminal<Stdout>> {\n    let mut child_stdin = child.stdin.take()?;\n    let child_id = child.id();\n    spawn(move || {\n        let our_stdin = stdin();\n        let mut our_stdin = our_stdin.lock();\n        loop {\n            let buffer = our_stdin.fill_buf().expect(\"Failed to read stdin.\");\n            if buffer.is_empty() {\n                // Our stdin was closed. We interpret this as a signal to exit,\n                // because pressing Ctrl+C to trigger an exit is no longer\n                // possible.\n                break;\n            }\n            // In raw mode, pressing Ctrl+C will send a '3' byte to stdin (\"end\n            // of message\" ASCII value) instead of sending SIGINT. Identify that\n            // case, and exit if it occurs.\n            if buffer.contains(&3) {\n                break;\n            }\n            match child_stdin.write(buffer) {\n                // A BrokenPipe error occurs when the child has exited. Exit\n                // without sending SIGINT.\n                Err(error) if error.kind() == ErrorKind::BrokenPipe => return,\n\n                Err(error) => panic!(\"Failed to forward stdin: {error}\"),\n                Ok(bytes) => our_stdin.consume(bytes),\n            }\n        }\n        // Send SIGINT to the child, telling it to exit. After the child exits,\n        // the main loop will detect the exit and we will shut down cleanly.\n        //\n        // Safety: Sending SIGINT to a process is a safe operation -- kill is\n        // marked unsafe because it is a FFI function.\n        unsafe {\n            kill(child_id as pid_t, SIGINT);\n        }\n    });\n    Some(\n        stdout()\n            .into_raw_mode()\n            .expect(\"Failed to set terminal to raw mode.\"),\n    )\n}\n\n// Forwards child's stderr to our stderr if child's stderr is piped, converting\n// line endings to CRLF if raw_mode is true.\nfn forward_stderr_if_piped(child: &mut Child, raw_mode: bool) {\n    let child_stderr = match child.stderr.take() {\n        None => return,\n        Some(child_stderr) => child_stderr,\n    };\n    spawn(move || {\n        let mut to_print = Vec::new();\n        let mut reader = BufReader::new(child_stderr);\n        loop {\n            let buffer = reader.fill_buf().expect(\"Unable to read child's stderr.\");\n            if buffer.is_empty() {\n                return;\n            }\n            for &byte in buffer {\n                if raw_mode && byte == b'\\n' {\n                    to_print.push(b'\\r');\n                }\n                to_print.push(byte);\n            }\n            stderr()\n                .write_all(&to_print)\n                .expect(\"Unable to echo child's stderr.\");\n            to_print.clear();\n            let buffer_len = buffer.len();\n            reader.consume(buffer_len);\n        }\n    });\n}\n"
  },
  {
    "path": "runner/src/qemu.rs",
    "content": "use super::Cli;\nuse std::path::PathBuf;\nuse std::process::{Child, Command, Stdio};\n\n// Spawns a QEMU VM with a simulated Tock system and the process binary. Returns\n// the handle for the spawned QEMU process.\npub fn deploy(cli: &Cli, platform: String, tbf_path: PathBuf) -> Child {\n    let platform_args = get_platform_args(platform);\n    let device = format!(\n        \"loader,file={},addr={}\",\n        tbf_path\n            .into_os_string()\n            .into_string()\n            .expect(\"Non-UTF-8 path\"),\n        platform_args.process_binary_load_address,\n    );\n    let mut qemu = Command::new(\"tock/tools/qemu/build/qemu-system-riscv32\");\n    qemu.args([\"-device\", &device, \"-nographic\", \"-serial\", \"mon:stdio\"]);\n    qemu.args(platform_args.fixed_args);\n    // If we let QEMU inherit its stdin from us, it will set it to raw mode,\n    // which prevents Ctrl+C from generating SIGINT. QEMU will not exit when\n    // Ctrl+C is entered, making our runner hard to close. Instead, we forward\n    // stdin to QEMU ourselves -- see output_processor.rs for more details.\n    qemu.stdin(Stdio::piped());\n    qemu.stdout(Stdio::piped());\n    // Because we set the terminal to raw mode while running QEMU, but QEMU's\n    // stdin is not connected to a terminal, QEMU does not know it needs to use\n    // CRLF line endings when printing to stderr. To convert, we also pipe\n    // QEMU's stderr through us and output_processor converts the line endings.\n    qemu.stderr(Stdio::piped());\n    if cli.verbose {\n        println!(\"QEMU command: {qemu:?}\");\n        println!(\"Spawning QEMU\")\n    }\n    qemu.spawn().expect(\"failed to spawn QEMU\")\n}\n\n// Returns the command line arguments for the given platform to qemu. Panics if\n// an unknown platform is passed.\nfn get_platform_args(platform: String) -> PlatformConfig {\n    match platform.as_str() {\n        \"hifive1\" => PlatformConfig {\n            #[rustfmt::skip]\n            fixed_args: &[\n                \"-kernel\", \"tock/target/riscv32imac-unknown-none-elf/release/hifive1\",\n                \"-M\", \"sifive_e,revb=true\",\n            ],\n            process_binary_load_address: \"0x20040000\",\n        },\n        \"opentitan\" => PlatformConfig {\n            #[rustfmt::skip]\n            fixed_args: &[\n                \"-bios\", \"tock/tools/qemu-runner/opentitan-boot-rom.elf\",\n                \"-kernel\", \"tock/target/riscv32imc-unknown-none-elf/release/earlgrey-cw310\",\n                \"-M\", \"opentitan\",\n            ],\n            process_binary_load_address: \"0x20030000\",\n        },\n        _ => panic!(\"Cannot deploy to platform {platform} via QEMU.\"),\n    }\n}\n\n// QEMU configuration information that is specific to each platform.\nstruct PlatformConfig {\n    fixed_args: &'static [&'static str],\n    process_binary_load_address: &'static str,\n}\n"
  },
  {
    "path": "runner/src/tockloader.rs",
    "content": "use super::Cli;\nuse std::path::PathBuf;\nuse std::process::{Child, Command, Stdio};\n\n// Uses tockloader to deploy the provided TAB file to a Tock system. Returns the\n// handle for the spawned 'tockloader listen' process.\n// Note: This function is untested, as its author does not have hardware that\n// works with tockloader. If you use it, please report back on how it works so\n// we can fix it or remove this notice!\npub fn deploy(cli: &Cli, platform: String, tab_path: PathBuf) -> Child {\n    let flags: &[_] = match platform.as_str() {\n        \"clue_nrf52840\" => &[],\n        \"hail\" | \"imix\" => &[],\n        \"microbit_v2\" => &[\"--bundle-apps\"],\n        \"nrf52\" | \"nrf52840\" => &[\n            \"--jlink\",\n            \"--arch\",\n            \"cortex-m4\",\n            \"--board\",\n            \"nrf52dk\",\n            \"--jtag-device\",\n            \"nrf52\",\n        ],\n        _ => panic!(\"Cannot deploy to platform {platform} via tockloader\"),\n    };\n    if cli.verbose {\n        println!(\"Tockloader flags: {flags:?}\");\n    }\n\n    // Tockloader listen's ability to receive every message from the Tock system\n    // varies from platform to platform. We look up the platform, and if it is\n    // not satisfactorily reliable we output a warning for the user.\n    let reliable_listen = match platform.as_str() {\n        // tockloader listen will reset the Hail/Imix, allowing it to capture all\n        // printed messages.\n        \"hail\" | \"imix\" => true,\n\n        // Microbit uses CDC over USB, which buffers messages so that tockloader\n        // listen can receive messages sent before it was started. As long as\n        // tockloader listen launches before the timeout, there will not be\n        // dropped messages. This is good enough for our purposes.\n        \"microbit_v2\" => true,\n\n        // tockloader listen doesn't reset the nrf52, and there's no message\n        // queueing mechanism. Therefore, tockloader listen will likely miss\n        // messages printed quickly after the process binary is deployed.\n        \"nrf52\" | \"nrf52840\" => false,\n\n        // We shouldn't hit this case, because the flag determination code above\n        // should error out on unknown platforms.\n        _ => panic!(\"Unknown reliability for {platform}\"),\n    };\n    if !reliable_listen {\n        println!(\"Warning: tockloader listen may miss early messages on platform {platform}\");\n    }\n\n    // Invoke tockloader uninstall to remove the process binary, if present.\n    let mut uninstall = Command::new(\"tockloader\");\n    uninstall.arg(\"uninstall\");\n    uninstall.args(flags);\n    if cli.verbose {\n        println!(\"tockloader uninstall command: {uninstall:?}\");\n    }\n    let mut child = uninstall\n        .spawn()\n        .expect(\"failed to spawn tockloader uninstall\");\n    let status = child\n        .wait()\n        .expect(\"failed to wait for tockloader uninstall\");\n    if cli.verbose {\n        println!(\"tockloader uninstall finished. {status}\");\n    }\n\n    // Invoke tockloader install to deploy the new process binary.\n    let mut install = Command::new(\"tockloader\");\n    install.arg(\"install\");\n    install.args(flags);\n    install.arg(tab_path);\n    if cli.verbose {\n        println!(\"tockloader install command: {install:?}\");\n    }\n    let mut child = install.spawn().expect(\"failed to spawn tockloader install\");\n    let status = child.wait().expect(\"failed to wait for tockloader install\");\n    if cli.verbose {\n        println!(\"tockloader install finished. {status}\");\n    }\n    assert!(\n        status.success(),\n        \"tockloader install returned unsuccessful status {status}\"\n    );\n\n    // Invoke tockloader listen to receive messages from the Tock system.\n    let mut listen = Command::new(\"tockloader\");\n    listen.arg(\"listen\");\n    listen.args(flags);\n    listen.stdout(Stdio::piped());\n    if cli.verbose {\n        println!(\"tockloader listen command: {listen:?}\");\n    }\n    listen.spawn().expect(\"failed to spawn tockloader listen\")\n}\n"
  },
  {
    "path": "runtime/Cargo.toml",
    "content": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ncategories = [\"embedded\", \"no-std\", \"os\"]\ndescription = \"\"\"libtock-rs runtime. Provides raw system call implementations \\\n                 and language items necessary for Tock apps.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nname = \"libtock_runtime\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[dependencies]\nlibtock_platform = { path = \"../platform\" }\n\n[features]\n\n# By default, libtock_runtime calls Memop to tell the Tock kernel where the\n# stack and heap begin. The kernel uses those addresses to specify the stack and\n# heap address ranges if the process faults. Those calls cost 22 bytes on ARM\n# and 28 bytes on RISC-V. To remove them (for the purpose of minimizing code\n# size), enable the no_debug_memop feature.\nno_debug_memop = []\n"
  },
  {
    "path": "runtime/src/lib.rs",
    "content": "//! `libtock_runtime` provides the runtime for Tock process binaries written in\n//! Rust as well as interfaces to Tock's system calls.\n//!\n//! `libtock_runtime` is designed for statically-compiled binaries, and needs to\n//! know the location (in non-volatile memory and RAM) at which the process will\n//! execute. It reads the `LIBTOCK_PLATFORM` variable to determine what location\n//! to build for (see the `layouts/` directory to see what platforms are\n//! available). It expects the following cargo config options to be set (e.g. in\n//! `.cargo/config.toml`):\n//! ```\n//! [build]\n//! rustflags = [\n//!     \"-C\", \"relocation-model=static\",\n//!     \"-C\", \"link-arg=-Tlayout.ld\",\n//! ]\n//! ```\n//! If a process binary wants to support another platform, it can set the\n//! `no_auto_layout` feature on `libtock_runtime` to disable this functionality\n//! and provide its own layout file.\n\n#![no_std]\n#![warn(unsafe_op_in_unsafe_fn)]\n\npub mod startup;\n\n/// TockSyscalls implements `libtock_platform::Syscalls`.\npub struct TockSyscalls;\n\n#[cfg(target_arch = \"arm\")]\nmod syscalls_impl_arm;\n#[cfg(target_arch = \"riscv32\")]\nmod syscalls_impl_riscv;\n#[cfg(target_arch = \"x86\")]\nmod syscalls_impl_x86;\n"
  },
  {
    "path": "runtime/src/startup/asm_arm.s",
    "content": "/* rt_header is defined by the general linker script (libtock_layout.ld). It has\n * the following layout:\n *\n *     Field                       | Offset\n *     ------------------------------------\n *     Address of the start symbol |      0\n *     Initial process break       |      4\n *     Top of the stack            |      8\n *     Size of .data               |     12\n *     Start of .data in flash     |     16\n *     Start of .data in ram       |     20\n *     Size of .bss                |     24\n *     Start of .bss in ram        |     28\n */\n\n/* start is the entry point -- the first code executed by the kernel. The kernel\n * passes arguments through 4 registers:\n *\n *     r0  Pointer to beginning of the process binary's code. The linker script\n *         locates rt_header at this address.\n *\n *     r1  Address of the beginning of the process's usable memory region.\n *     r2  Size of the process' allocated memory region (including grant region)\n *     r3  Process break provided by the kernel.\n *\n * We currently only use the value in r0. It is copied into r5 early on because\n * r0 is needed to invoke system calls.\n *\n * To be compatible with ARMv6 Thumb-1, we the cmp and beq instructions\n * instead of cbz in two places. This increases the code size with 4 bytes,\n * but allows us to use it on Cortex-M0+ processors.\n */\n.section .start, \"ax\"\n.global start\n.thumb_func\nstart:\n\t/* First, verify the process binary was loaded at the correct address. The\n\t * check is performed by comparing the program counter at the start to the\n\t * address of `start`, which is stored in rt_header. */\n\tmov r4, pc        /* r4 = address of .start + 4 (Thumb bit unset) */\n\tmov r5, r0        /* Save rt_header; we use r0 for syscalls */\n\tldr r0, [r5, #0]  /* r0 = rt_header.start */\n\tadds r0, #4       /* r0 = rt_header.start + 4 */\n\tcmp r0, r4        /* Skip error handling if pc correct */\n\tbeq .Lset_brk     \n\t/* If the beq on the previous line did not jump, then the binary is not at\n\t * the correct location. Report the error via LowLevelDebug then exit. */\n\tmovs r0, #8  /* LowLevelDebug driver number */\n\tmovs r1, #1  /* Command: print alert code */\n\tmovs r2, #2  /* Alert code 2 (incorrect location */\n\tsvc 2        /* Execute `command` */\n\tmovs r0, #0  /* Operation: exit-terminate */\n\tmovs r1, #1  /* Completion code: FAIL */\n\tsvc 6        /* Execute `exit` */\n\n.Lset_brk:\n\t/* memop(): set brk to rt_header's initial break value */\n\tmovs r0, #0       /* operation: set break */\n\tldr r1, [r5, #4]  /* rt_header`s initial process break */\n\tsvc 5             /* call `memop` */\n\n\t/* Set the stack pointer */\n\tldr r0, [r5, #8]  /* r0 = rt_header._stack_top */\n\tmov sp, r0\n\n\t/* Copy .data into place */\n\tldr r0, [r5, #12]          /* remaining = rt_header.data_size */\n\tcmp r0, #0                 /* Jump to zero_bss if remaining == 0 */\t\n\tbeq .Lzero_bss         \n\tldr r1, [r5, #16]          /* src = rt_header.data_flash_start */\n\tldr r2, [r5, #20]          /* dest = rt_header.data_ram_start */\n.Ldata_loop_body:\n\tldr r3, [r1]               /* r3 = *src */\n\tstr r3, [r2]               /* *(dest) = r3 */\n\tsubs r0, #4                /* remaining -= 4 */\n\tadds r1, #4                /* src += 4 */\n\tadds r2, #4                /* dest += 4 */\n\tcmp r0, #0\n\tbne .Ldata_loop_body       /* Iterate again if remaining != 0 */\n\n.Lzero_bss:\n\tldr r0, [r5, #24]          /* remaining = rt_header.bss_size */\n\tcmp r0, #0                 /* Jump to call_rust_start if remaining == 0 */\n\tbeq .Lcall_rust_start  \n\tldr r1, [r5, #28]          /* dest = rt_header.bss_start */\n\tmovs r2, #0                /* r2 = 0 */\n.Lbss_loop_body:\n\tstrb r2, [r1]              /* *(dest) = r2 = 0 */\n\tsubs r0, #1                /* remaining -= 1 */\n\tadds r1, #1                /* dest += 1 */\n\tcmp r0, #0\n\tbne .Lbss_loop_body        /* Iterate again if remaining != 0 */\n\n.Lcall_rust_start:\n\tbl rust_start\n"
  },
  {
    "path": "runtime/src/startup/asm_riscv32.s",
    "content": "/* rt_header is defined by the general linker script (libtock_layout.ld). It has\n * the following layout:\n *\n *     Field                       | Offset\n *     ------------------------------------\n *     Address of the start symbol |      0\n *     Initial process break       |      4\n *     Top of the stack            |      8\n *     Size of .data               |     12\n *     Start of .data in flash     |     16\n *     Start of .data in ram       |     20\n *     Size of .bss                |     24\n *     Start of .bss in ram        |     28\n */\n\n/* start is the entry point -- the first code executed by the kernel. The kernel\n * passes arguments through 4 registers:\n *\n *     a0  Pointer to beginning of the process binary's code. The linker script\n *         locates rt_header at this address.\n *\n *     a1  Address of the beginning of the process's usable memory region.\n *     a2  Size of the process' allocated memory region (including grant region)\n *     a3  Process break provided by the kernel.\n *\n * We currently only use the value in a0. It is copied into a5 early on because\n * a0-a4 are needed to invoke system calls.\n */\n.section .start, \"ax\"\n.globl start\nstart:\n\t/* First, verify the process binary was loaded at the correct address. The\n\t * check is performed by comparing the program counter at the start to the\n\t * address of `start`, which is stored in rt_header. */\n\tauipc s0, 0            /* s0 = pc */\n\tmv a5, a0;             /* Save rt_header so syscalls don't overwrite it */\n\tlw s1, 0(a5)           /* s1 = rt_header.start */\n\tbeq s0, s1, .Lset_brk  /* Skip error handling code if pc is correct */\n\t/* If the beq on the previous line did not jump, then the binary is not at\n\t * the correct location. Report the error via LowLevelDebug then exit. */\n\tli a0, 8  /* LowLevelDebug driver number */\n\tli a1, 1  /* Command: Print alert code */\n\tli a2, 2  /* Alert code 2 (incorrect location) */\n\tli a4, 2  /* `command` class */\n\tecall\n\tli a0, 0  /* exit-terminate */\n\tli a1, 1  /* Completion code: FAIL */\n\tli a4, 6  /* `exit` class */\n\tecall\n\n.Lset_brk:\n\t/* memop(): set brk to rt_header's initial break value */\n\tli a0, 0      /* operation: set break */\n\tlw a1, 4(a5)  /* rt_header's initial process break */\n\tli a4, 5      /* `memop` class */\n\tecall\n\n\t/* Set the stack pointer */\n\tlw sp, 8(a5)  /* sp = rt_header._stack_top */\n\n\t/* Copy .data into place. */\n\tlw a0, 12(a5)              /* remaining = rt_header.data_size */\n\tbeqz a0, .Lzero_bss        /* Jump to zero_bss if remaining is zero */\n\tlw a1, 16(a5)              /* src = rt_header.data_flash_start */\n\tlw a2, 20(a5)              /* dest = rt_header.data_ram_start */\n.Ldata_loop_body:\n\tlw a3, 0(a1)               /* a3 = *src */\n\tsw a3, 0(a2)               /* *dest = a3 */\n\taddi a0, a0, -4            /* remaining -= 4 */\n\taddi a1, a1, 4             /* src += 4 */\n\taddi a2, a2, 4             /* dest += 4 */\n\tbnez a0, .Ldata_loop_body  /* Iterate again if remaining != 0 */\n\n.Lzero_bss:\n\tlw a0, 24(a5)               /* remaining = rt_header.bss_size */\n\tbeqz a0, .Lcall_rust_start  /* Jump to call_Main if remaining is zero */\n\tlw a1, 28(a5)               /* dest = rt_header.bss_start */\n.Lbss_loop_body:\n\tsb zero, 0(a1)              /* *dest = zero */\n\taddi a0, a0, -1             /* remaining -= 1 */\n\taddi a1, a1, 1              /* dest += 1 */\n\tbnez a0, .Lbss_loop_body    /* Iterate again if remaining != 0 */\n\n.Lcall_rust_start:\n\t/* Note: rust_start must be a diverging function (i.e. return `!`) */\n\tjal rust_start\n"
  },
  {
    "path": "runtime/src/startup/asm_x86.s",
    "content": "/* rt_header is defined by the general linker script (libtock_layout.ld). It has\n * the following layout:\n *\n *     Field                       | Offset\n *     ------------------------------------\n *     Address of the start symbol |      0\n *     Initial process break       |      4\n *     Top of the stack            |      8\n *     Size of .data               |     12\n *     Start of .data in flash     |     16\n *     Start of .data in ram       |     20\n *     Size of .bss                |     24\n *     Start of .bss in ram        |     28\n */\n\n/* start is the entry point -- the first code executed by the kernel. The kernel\n * passes the following arguments onto the stack:\n *\n *  esp+4  Pointer to beginning of the process binary's code. The linker script\n *         locates rt_header at this address.\n *\n *     +8  Address of the beginning of the process's usable memory region.\n *     +12 Size of the process' allocated memory region (including grant region)\n *     +16 Process break provided by the kernel.\n *\n * We currently only use the value in esp+4.\n */\n\n/* int 0x03 is used to trigger a breakpoint which is promoted to a hard fault in the\n   absence of a debugger. This is useful to fault at failure cases where there is no\n   recovery path.\n */\n\n/* Specify that the start code is allocated and executable (ax),\n * and that it should be placed in the .start section of the binary.\n */\n\n.section .start, \"ax\"\n.globl start\nstart:\n   /*\n    * Verify that the binary was loaded to the correct\n    * address. We can do this by using the call command\n    * and grabbing the EIP off of the stack. The eip\n    * will be the \"length of the call instruction\" (5 bytes) \n    * ahead of the actual start of the program.\n    */\n\n    call .Lget_eip          // 1 byte for the opcode + 4 bytes for the relative offset\n                            // = 5 byte long instruction\n.Lget_eip:\n    popl %eax               // eax = eip\n    subl $5, %eax           // eax = eip - 5 byte instruction\n    movl 4(%esp), %ebx      // ebx = rt_header (top of memory)\n    movl 0(%ebx), %ecx      // ecx = rt_header.start\n    cmpl %ecx, %eax\n    je .Lset_brk\n    /* If the binary is not at the correct location, report the error via LowLevelDebug\n     * then exit. */\n    pushl %eax             // eip, not consumed by the syscall, but is seen in trace\n    pushl $2               // Code 0x02 (app was not installed in the correct location)\n    pushl $1               // Minor number: Alert code \n    pushl $8               // Major number: LowLevelDebug driver\n    mov $2, %eax           // Command syscall\n    int $0x40\n    addl $16, %esp\n    pushl $0\n    pushl $0\n    pushl $1              // Completion code: FAIL\n    pushl $0              // exit-terminate\n    mov $6, %eax          // Exit syscall\n    int $0x40\n    addl $16, %esp\n    int $0x03              // If we return, trigger a fault\n    \n\n    /* Set brk to rt_header initial break value */\n.Lset_brk:\n    movl 4(%ebx), %ecx      // ecx = initial process break\n    pushl $0\n    pushl $0\n    pushl %ecx              // push initial process break\n    pushl $0\n    movl  $5, %eax          // memop\n    int $0x40\n\n    /* Set the stack pointer */\n    mov 8(%ebx), %esp\n\n.Lzero_bss:\n    /* Zero out .bss */\n    movl 24(%ebx), %ecx     // ecx = remaining = rt_header.bss_size\n    cmpl $0, %ecx\n    je .Lcopy_data          // If there is no .bss, jump to copying .data\n    movl 28(%ebx), %edi     // edi = dst = rt_header.bss_start\n    shrl $2, %ecx           // ecx = remaining / 4 = number of words to zero\n    cld                     // Clear the direction flag\n    xorl %eax, %eax         // eax = 0, value to set .bss to\n    rep stosl               // Zero out the .bss_size\n    movl 24(%ebx), %ecx     // ecx = remaining = rt_header.bss_size\n    andl $3, %ecx           // ecx = remaining % 4 = number of bytes to zero\n    rep stosb               // Zero out the remaining bytes\n\n.Lcopy_data:\n    /* Copy .data into place */\n    movl 12(%ebx), %ecx     // ecx = rt_header.data_size\n    cmpl $0, %ecx\n    je .Lcall_rust_start\n    movl 16(%ebx), %esi     // esi = src = rt_header.data_flash_start\n    movl 20(%ebx), %edi     // edi = dst = rt_header.data_ram_start\n    shrl $2, %ecx           // ecx = rt_header.data_size / 4 = number of words to copy\n    cld                     // Clear the direction flag\n    rep movsl               // Copy data from flash to ram\n    movl 12(%ebx), %ecx     // ecx = rt_header.data_size\n    andl $3, %ecx           // ecx = rt_header.data_size % 4 = number of bytes to copy\n    rep movsb               // Copy the remaining bytes\n    \n.Lcall_rust_start:\n    jmp rust_start\n    int $0x03               // If we return, trigger a fault"
  },
  {
    "path": "runtime/src/startup/mod.rs",
    "content": "//! Runtime components related to process startup.\n\nuse crate::TockSyscalls;\nuse libtock_platform::{Syscalls, Termination};\n\n// Include the correct `start` symbol (the program entry point) for the\n// architecture.\n#[cfg(target_arch = \"arm\")]\ncore::arch::global_asm!(include_str!(\"asm_arm.s\"));\n#[cfg(target_arch = \"riscv32\")]\ncore::arch::global_asm!(include_str!(\"asm_riscv32.s\"));\n#[cfg(target_arch = \"x86\")]\ncore::arch::global_asm!(include_str!(\"asm_x86.s\"), options(att_syntax));\n\n/// `set_main!` is used to tell `libtock_runtime` where the process binary's\n/// `main` function is. The process binary's `main` function must have the\n/// signature `FnOnce() -> T`, where T is some concrete type that implements\n/// `libtock_platform::Termination`.\n///\n/// # Example\n/// ```\n/// libtock_runtime::set_main!{main};\n///\n/// fn main() -> () { /* Omitted */ }\n/// ```\n// set_main! generates a function called `libtock_unsafe_main`, which is called\n// by `rust_start`. The function has `unsafe` in its name because implementing\n// it is `unsafe` (it *must* have the signature `libtock_unsafe_main() -> !`),\n// but there is no way to enforce the use of `unsafe` through the type system.\n// This function calls the client-provided function, which enforces its type\n// signature.\n#[macro_export]\nmacro_rules! set_main {\n    {$name:ident} => {\n        #[no_mangle]\n        fn libtock_unsafe_main() -> ! {\n            #[allow(unreachable_code)] // so that fn main() -> ! does not produce a warning.\n            $crate::startup::handle_main_return($name())\n        }\n    }\n}\n\n/// Executables must specify their stack size by using the `stack_size!` macro.\n/// It takes a single argument, the desired stack size in bytes. Example:\n/// ```\n/// stack_size!{0x400}\n/// ```\n// stack_size works by putting a symbol equal to the size of the stack in the\n// .stack_buffer section. The linker script uses the .stack_buffer section to\n// size the stack. flash.sh looks for the symbol by name (hence #[no_mangle]) to\n// determine the size of the stack to pass to elf2tab.\n#[macro_export]\nmacro_rules! stack_size {\n    {$size:expr} => {\n        #[no_mangle]\n        #[link_section = \".stack_buffer\"]\n        pub static mut STACK_MEMORY: [u8; $size] = [0; $size];\n    }\n}\n\n/// This is public for the sake of making `set_main!` usable in other crates.\n/// It doesn't have another function.\npub fn handle_main_return<T: Termination>(result: T) -> ! {\n    Termination::complete::<TockSyscalls>(result)\n}\n\n// The runtime header, which is generated by the linker script and placed at the\n// beginning of the app binary.\n#[repr(C)]\nstruct RtHeader {\n    start: usize,\n    initial_break: *mut (),\n    stack_top: *mut (),\n    data_size: usize,\n    data_flash_start: *const u8,\n    data_ram_start: *mut u8,\n    bss_size: usize,\n    bss_start: *mut u8,\n}\n\n// rust_start is the first Rust code to execute in the process. It is called\n// from start, which is written directly in assembly.\n#[no_mangle]\nextern \"C\" fn rust_start() -> ! {\n    extern \"Rust\" {\n        fn libtock_unsafe_main() -> !;\n        static rt_header: RtHeader;\n    }\n\n    #[cfg(not(feature = \"no_debug_memop\"))]\n    // Safety: rt_header is defined in the linker script, valid for its type,\n    // and not modified anywhere\n    unsafe {\n        let _ = TockSyscalls::memop_debug_stack_start(rt_header.stack_top as *const u8);\n        let _ = TockSyscalls::memop_debug_heap_start(rt_header.initial_break as *const u8);\n    }\n\n    // Safety: libtock_unsafe_main is defined by the set_main! macro, and its\n    // signature matches the signature in the `extern` block in this function.\n    unsafe {\n        libtock_unsafe_main();\n    }\n}\n\n/// Function which an allocator can call to learn the initial\n/// start of the heap region\npub fn get_heap_start() -> *mut () {\n    extern \"Rust\" {\n        static rt_header: RtHeader;\n    }\n    // Safety: rt_header is defined in the linker script, valid for its type,\n    // and not modified anywhere\n    unsafe { rt_header.initial_break }\n}\n"
  },
  {
    "path": "runtime/src/startup/start_prototype.rs",
    "content": "// This file is not compiled or tested! It is kept in this repository in case\n// future libtock_runtime developers want to use it. To use this file, add\n// `mod start_prototype;` to mod.rs.\n\n// The `start` symbol must be written purely in assembly, because it has an ABI\n// that the Rust compiler doesn't know (e.g. it does not expect the stack to be\n// set up). One way to write a correct `start` implementation is to write it in\n// Rust using the C ABI, compile that implementation, then tweak the assembly by\n// hand. This is a Rust version of `start` for developers who are working on\n// `start`.\n\nuse super::RtHeader;\nuse core::arch::asm;\n\n#[link_section = \".start\"]\n#[no_mangle]\nextern \"C\" fn start_prototype(\n    rt_header: &RtHeader,\n    _memory_start: usize,\n    _memory_len: usize,\n    _app_break: usize,\n) -> ! {\n    use crate::TockSyscalls;\n    use libtock_platform::{syscall_class, RawSyscalls};\n\n    let pc: usize;\n    unsafe {\n        #[cfg(target_arch = \"arm\")]\n        asm!(\"mov {}, pc\", lateout(reg) pc, options(nomem, nostack, preserves_flags));\n        #[cfg(target_arch = \"riscv32\")]\n        asm!(\"auipc {}, 0\", lateout(reg) pc, options(nomem, nostack, preserves_flags));\n    }\n    if pc != rt_header.start {\n        // Binary is in an incorrect location: report an error via\n        // LowLevelDebug then exit.\n        unsafe {\n            TockSyscalls::syscall4::<{ syscall_class::COMMAND }>([\n                8u32.into(),\n                1u32.into(),\n                2u32.into(),\n                0u32.into(),\n            ]);\n            TockSyscalls::syscall2::<{ syscall_class::EXIT }>([0u32.into(), 0u32.into()]);\n        }\n    }\n\n    // Set the app break.\n    // TODO: Replace with Syscalls::memop_brk() when that is implemented.\n    unsafe {\n        TockSyscalls::syscall2::<{ syscall_class::MEMOP }>([\n            0u32.into(),\n            rt_header.initial_break.into(),\n        ]);\n    }\n\n    // Set the stack pointer.\n    unsafe {\n        #[cfg(target_arch = \"arm\")]\n        asm!(\"mov sp, {}\", in(reg) rt_header.stack_top, options(nomem, preserves_flags));\n        #[cfg(target_arch = \"riscv32\")]\n        asm!(\"mv sp, {}\", in(reg) rt_header.stack_top, options(nomem, preserves_flags));\n    }\n\n    // Copy .data into place. Uses a manual loop rather than\n    // `core::ptr::copy*()` to avoid relying on `memcopy` or `memmove`.\n    let mut remaining = rt_header.data_size;\n    let mut src = rt_header.data_flash_start as *const u32;\n    let mut dest = rt_header.data_ram_start as *mut u32;\n    while remaining > 0 {\n        unsafe {\n            core::ptr::write(dest, *(src));\n            src = src.add(1);\n            dest = dest.add(1);\n        }\n        remaining -= 4;\n    }\n\n    // Zero .bss. Uses a manual loop and volatile write to avoid relying on\n    // `memset`.\n    let mut remaining = rt_header.bss_size;\n    let mut dest = rt_header.bss_start;\n    while remaining > 0 {\n        unsafe {\n            core::ptr::write_volatile(dest, 0);\n            dest = dest.add(1);\n        }\n        remaining -= 1;\n    }\n\n    extern \"C\" {\n        fn rust_start() -> !;\n    }\n\n    unsafe {\n        rust_start();\n    }\n}\n"
  },
  {
    "path": "runtime/src/syscalls_impl_arm.rs",
    "content": "use core::arch::asm;\nuse libtock_platform::{RawSyscalls, Register};\n\nunsafe impl RawSyscalls for crate::TockSyscalls {\n    unsafe fn yield1([Register(r0)]: [Register; 1]) {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::yield1\n        // the use of `clobber_abi` allows us this to run on both Thumb-1 and Thumb-2\n        unsafe {\n            asm!(\"svc 0\",\n                 inlateout(\"r0\") r0 => _, // a1\n                 // r4-r8 are callee-saved.\n                 // r9 is platform-specific. We don't use it in libtock_runtime,\n                 // so it is either unused or used as a callee-saved register.\n                 // r10 and r11 are callee-saved.\n\n                 // r13 is the stack pointer and must be restored by the callee.\n                 // r15 is the program counter.\n\n                 clobber_abi(\"C\"), // a2, a3, a4, ip (r12), lr (r14)\n            );\n        }\n    }\n\n    unsafe fn yield2([Register(r0), Register(r1)]: [Register; 2]) {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::yield2\n        // the use of `clobber_abi` allows us this to run on both Thumb-1 and Thumb-2\n        unsafe {\n            asm!(\"svc 0\",\n                 inlateout(\"r0\") r0 => _, // a1\n                 inlateout(\"r1\") r1 => _, // a2\n                 // r4-r8 are callee-saved.\n                 // r9 is platform-specific. We don't use it in libtock_runtime,\n                 // so it is either unused or used as a callee-saved register.\n                 // r10 and r11 are callee-saved.\n\n                 // r13 is the stack pointer and must be restored by the callee.\n                 // r15 is the program counter.\n\n                 clobber_abi(\"C\"), // a3, a4, ip (r12), lr (r14)\n            );\n        }\n    }\n\n    unsafe fn syscall1<const SYSCALL_CLASS_NUMBER: usize>(\n        [Register(mut r0)]: [Register; 1],\n    ) -> [Register; 2] {\n        let r1;\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::syscall1\n        #[allow(clippy::pointers_in_nomem_asm_block)]\n        unsafe {\n            asm!(\n                \"svc {SYSCALL_CLASS_NUMBER}\",\n                inlateout(\"r0\") r0,\n                lateout(\"r1\") r1,\n                options(preserves_flags, nostack, nomem),\n                SYSCALL_CLASS_NUMBER = const SYSCALL_CLASS_NUMBER,\n            );\n        }\n        [Register(r0), Register(r1)]\n    }\n\n    unsafe fn syscall2<const SYSCALL_CLASS_NUMBER: usize>(\n        [Register(mut r0), Register(mut r1)]: [Register; 2],\n    ) -> [Register; 2] {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::syscall2\n        #[allow(clippy::pointers_in_nomem_asm_block)]\n        unsafe {\n            asm!(\n                \"svc {SYSCALL_CLASS_NUMBER}\",\n                 inlateout(\"r0\") r0,\n                 inlateout(\"r1\") r1,\n                 options(preserves_flags, nostack, nomem),\n                 SYSCALL_CLASS_NUMBER = const SYSCALL_CLASS_NUMBER,\n            );\n        }\n        [Register(r0), Register(r1)]\n    }\n\n    unsafe fn syscall4<const SYSCALL_CLASS_NUMBER: usize>(\n        [Register(mut r0), Register(mut r1), Register(mut r2), Register(mut r3)]: [Register; 4],\n    ) -> [Register; 4] {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::syscall4\n        unsafe {\n            asm!(\n                \"svc {SYSCALL_CLASS_NUMBER}\",\n                inlateout(\"r0\") r0,\n                inlateout(\"r1\") r1,\n                inlateout(\"r2\") r2,\n                inlateout(\"r3\") r3,\n                options(preserves_flags, nostack),\n                SYSCALL_CLASS_NUMBER = const SYSCALL_CLASS_NUMBER,\n            );\n        }\n        [Register(r0), Register(r1), Register(r2), Register(r3)]\n    }\n}\n"
  },
  {
    "path": "runtime/src/syscalls_impl_riscv.rs",
    "content": "use core::arch::asm;\nuse libtock_platform::{RawSyscalls, Register};\n\nunsafe impl RawSyscalls for crate::TockSyscalls {\n    // This yield implementation is currently limited to RISC-V versions without\n    // floating-point registers, as it does not mark them clobbered.\n    #[cfg(not(any(target_feature = \"d\", target_feature = \"f\")))]\n    unsafe fn yield1([Register(r0)]: [Register; 1]) {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::yield1\n        unsafe {\n            asm!(\"ecall\",\n                 // x0 is the zero register.\n                 lateout(\"x1\") _, // Return address\n                 // x2-x4 are stack, global, and thread pointers. sp is\n                 // callee-saved.\n                 lateout(\"x5\") _, // t0\n                 lateout(\"x6\") _, // t1\n                 lateout(\"x7\") _, // t2\n                 // x8 and x9 are s0 and s1 and are callee-saved.\n                 inlateout(\"x10\") r0 => _, // a0\n                 lateout(\"x11\") _,         // a1\n                 lateout(\"x12\") _,         // a2\n                 lateout(\"x13\") _,         // a3\n                 inlateout(\"x14\") 0 => _,  // a4\n                 lateout(\"x15\") _,         // a5\n                 lateout(\"x16\") _,         // a6\n                 lateout(\"x17\") _,         // a7\n                 // x18-27 are s2-s11 and are callee-saved\n                 lateout(\"x28\") _, // t3\n                 lateout(\"x29\") _, // t4\n                 lateout(\"x30\") _, // t5\n                 lateout(\"x31\") _, // t6\n            );\n        }\n    }\n\n    // This yield implementation is currently limited to RISC-V versions without\n    // floating-point registers, as it does not mark them clobbered.\n    #[cfg(not(any(target_feature = \"d\", target_feature = \"f\")))]\n    unsafe fn yield2([Register(r0), Register(r1)]: [Register; 2]) {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::yield2\n        unsafe {\n            asm!(\"ecall\",\n                 // x0 is the zero register.\n                 lateout(\"x1\") _, // Return address\n                 // x2-x4 are stack, global, and thread pointers. sp is\n                 // callee-saved.\n                 lateout(\"x5\") _, // t0\n                 lateout(\"x6\") _, // t1\n                 lateout(\"x7\") _, // t2\n                 // x8 and x9 are s0 and s1 and are callee-saved.\n                 inlateout(\"x10\") r0 => _, // a0\n                 inlateout(\"x11\") r1 => _, // a1\n                 lateout(\"x12\") _,         // a2\n                 lateout(\"x13\") _,         // a3\n                 inlateout(\"x14\") 0 => _,  // a4\n                 lateout(\"x15\") _,         // a5\n                 lateout(\"x16\") _,         // a6\n                 lateout(\"x17\") _,         // a7\n                 // x18-27 are s2-s11 and are callee-saved\n                 lateout(\"x28\") _, // t3\n                 lateout(\"x29\") _, // t4\n                 lateout(\"x30\") _, // t5\n                 lateout(\"x31\") _, // t6\n            );\n        }\n    }\n\n    unsafe fn syscall1<const CLASS: usize>([Register(mut r0)]: [Register; 1]) -> [Register; 2] {\n        let r1;\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::syscall1\n        #[allow(clippy::pointers_in_nomem_asm_block)]\n        unsafe {\n            asm!(\"ecall\",\n                 inlateout(\"a0\") r0,\n                 lateout(\"a1\") r1,\n                 in(\"a4\") CLASS,\n                 options(preserves_flags, nostack, nomem),\n            );\n        }\n        [Register(r0), Register(r1)]\n    }\n\n    unsafe fn syscall2<const CLASS: usize>(\n        [Register(mut r0), Register(mut r1)]: [Register; 2],\n    ) -> [Register; 2] {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::syscall2\n        #[allow(clippy::pointers_in_nomem_asm_block)]\n        unsafe {\n            asm!(\"ecall\",\n                 inlateout(\"a0\") r0,\n                 inlateout(\"a1\") r1,\n                 in(\"a4\") CLASS,\n                 options(preserves_flags, nostack, nomem)\n            );\n        }\n        [Register(r0), Register(r1)]\n    }\n\n    unsafe fn syscall4<const CLASS: usize>(\n        [Register(mut r0), Register(mut r1), Register(mut r2), Register(mut r3)]: [Register; 4],\n    ) -> [Register; 4] {\n        // Safety: This matches the invariants required by the documentation on\n        // RawSyscalls::syscall4\n        unsafe {\n            asm!(\"ecall\",\n                 inlateout(\"a0\") r0,\n                 inlateout(\"a1\") r1,\n                 inlateout(\"a2\") r2,\n                 inlateout(\"a3\") r3,\n                 in(\"a4\") CLASS,\n                 options(preserves_flags, nostack),\n            );\n        }\n        [Register(r0), Register(r1), Register(r2), Register(r3)]\n    }\n}\n"
  },
  {
    "path": "runtime/src/syscalls_impl_x86.rs",
    "content": "use core::arch::asm;\nuse libtock_platform::{syscall_class, RawSyscalls, Register};\n\nunsafe impl RawSyscalls for crate::TockSyscalls {\n    // Yield 1 is used for yield_wait\n    unsafe fn yield1([Register(r0)]: [Register; 1]) {\n        unsafe {\n            asm!(\n                \"pushl $0\",\n                \"pushl $0\",\n                \"pushl $0\",\n                \"pushl {0}\", // r0\n                \"movl $0, %eax\",\n                \"int $0x40\",\n                \"addl  $16, %esp\",\n\n                in(reg) r0,\n\n                // The following registers are clobbered by the syscall\n                out(\"eax\") _,\n                out(\"ecx\") _,\n                out(\"edx\") _,\n                options(att_syntax),\n            );\n        }\n    }\n\n    // Yield 2 is used for yield_no_wait\n    unsafe fn yield2([Register(r0), Register(r1)]: [Register; 2]) {\n        unsafe {\n            asm!(\n                \"pushl $0\",\n                \"pushl $0\",\n                \"pushl {0}\", // r1\n                \"pushl {1}\", // r0\n                \"movl  $0, %eax\",\n                \"int $0x40\",\n                \"addl  $16, %esp\",\n\n                in(reg) r1,\n                in(reg) r0,\n\n                // The following registers are clobbered by the syscall\n                out(\"eax\") _,\n                out(\"ecx\") _,\n                out(\"edx\") _,\n                options(att_syntax)\n            );\n        }\n    }\n\n    unsafe fn syscall1<const CLASS: usize>([Register(mut r0)]: [Register; 1]) -> [Register; 2] {\n        // This is memop, the only syscall class that syscall1 supports\n        let r1;\n        unsafe {\n            asm!(\n                \"push $0\",\n                \"push $0\",\n                \"push $0\",\n                \"push {0}\", // r0\n                \"movl  $5, %eax\",\n                \"int $0x40\",\n                \"popl {0:e}\", // r1\n                \"popl {1:e}\", // r0\n                \"addl  $8, %esp\",\n\n                inlateout(reg) r0,\n                out(reg) r1,\n\n                // The following registers are clobbered by the syscall\n                out(\"eax\") _,\n                options(att_syntax),\n            );\n        }\n        [Register(r0), Register(r1)]\n    }\n\n    unsafe fn syscall2<const CLASS: usize>(\n        [Register(mut r0), Register(mut r1)]: [Register; 2],\n    ) -> [Register; 2] {\n        let cmd: u32 = match CLASS {\n            syscall_class::MEMOP => 5,\n            syscall_class::EXIT => 6,\n            _ => unreachable!(),\n        };\n\n        unsafe {\n            asm!(\n                \"pushl $0\",\n                \"pushl $0\",\n                \"pushl {0}\", // r1\n                \"pushl {1}\", // r0\n                \"movl  {2}, %eax\", // cmd\n                \"int $0x40\",\n                \"popl {1:e}\", // r0\n                \"popl {0:e}\", // r1\n                \"addl  $8, %esp\",\n\n                inlateout(reg) r1,\n                inlateout(reg) r0,\n                in(reg) cmd,\n\n                // The following registers are clobbered by the syscall\n                out(\"eax\") _,\n                options(att_syntax),\n            );\n        }\n\n        [Register(r0), Register(r1)]\n    }\n\n    unsafe fn syscall4<const CLASS: usize>(\n        [Register(mut r0), Register(mut r1), Register(mut r2), Register(mut r3)]: [Register; 4],\n    ) -> [Register; 4] {\n        let cmd: u32 = match CLASS {\n            syscall_class::SUBSCRIBE => 1,\n            syscall_class::COMMAND => 2,\n            syscall_class::ALLOW_RW => 3,\n            syscall_class::ALLOW_RO => 4,\n            _ => unreachable!(),\n        };\n        unsafe {\n            asm!(\n                \"pushl {3}\", // r3\n                \"pushl {2}\", // r2\n                \"pushl {1}\", // r1\n                \"pushl {0}\", // r0\n                \"movl  {4:e}, %eax\",\n                \"int $0x40\",\n                \"popl {0:e}\", // r0\n                \"popl {1:e}\", // r1\n                \"popl {2:e}\", // r2\n                \"popl {3:e}\", // r3\n\n                inlateout(reg) r0,\n                inlateout(reg) r1,\n                inlateout(reg) r2,\n                inlateout(reg) r3,\n\n                in(reg) cmd,\n\n                // The following registers are clobbered by the syscall\n                out(\"eax\") _,\n                options(att_syntax),\n            );\n        }\n\n        [Register(r0), Register(r1), Register(r2), Register(r3)]\n    }\n}\n"
  },
  {
    "path": "rust-toolchain.toml",
    "content": "[toolchain]\n# This is libtock-rs' Minimum Supported Rust Version (MSRV).\n#\n# Update policy: Update this if doing so allows you to use a Rust feature that\n# you'd like to use. When you do so, update this to the first Rust version that\n# includes that feature. Whenever this value is updated, the rust-version field\n# in Cargo.toml must be updated as well.\nchannel = \"1.88\"\ncomponents = [\"clippy\", \"rustfmt\", \"rust-analyzer\"]\ntargets = [\n    \"thumbv6m-none-eabi\",\n    \"thumbv7em-none-eabi\",\n    \"thumbv8m.main-none-eabi\",\n    \"riscv32imac-unknown-none-elf\",\n    \"riscv32imc-unknown-none-elf\",\n]\n"
  },
  {
    "path": "rustfmt.toml",
    "content": "use_field_init_shorthand = true\n"
  },
  {
    "path": "src/lib.rs",
    "content": "#![forbid(unsafe_code)]\n#![no_std]\n\n#[cfg(debug_assertions)]\nextern crate libtock_debug_panic;\n#[cfg(not(debug_assertions))]\nextern crate libtock_small_panic;\n\npub use libtock_platform as platform;\npub use libtock_runtime as runtime;\n\npub mod adc {\n    use libtock_adc as adc;\n    pub type Adc = adc::Adc<super::runtime::TockSyscalls>;\n    pub use adc::ADCListener;\n}\npub mod display {\n    use libtock_screen as screen;\n    pub type Screen = screen::Screen<super::runtime::TockSyscalls>;\n}\npub mod air_quality {\n    use libtock_air_quality as air_quality;\n    pub type AirQuality = air_quality::AirQuality<super::runtime::TockSyscalls>;\n    pub use air_quality::AirQualityListener;\n}\n\npub mod alarm {\n    use libtock_alarm as alarm;\n    pub type Alarm = alarm::Alarm<super::runtime::TockSyscalls>;\n    pub use alarm::{Convert, Hz, Milliseconds, Ticks};\n}\npub mod ambient_light {\n    use libtock_ambient_light as ambient_light;\n    pub type AmbientLight = ambient_light::AmbientLight<super::runtime::TockSyscalls>;\n    pub use ambient_light::IntensityListener;\n}\npub mod buttons {\n    use libtock_buttons as buttons;\n    pub type Buttons = buttons::Buttons<super::runtime::TockSyscalls>;\n    pub use buttons::{ButtonListener, ButtonState};\n}\npub mod buzzer {\n    use libtock_buzzer as buzzer;\n    pub type Buzzer = buzzer::Buzzer<super::runtime::TockSyscalls>;\n    pub use buzzer::Note;\n}\npub mod console {\n    use libtock_console as console;\n    pub type Console = console::Console<super::runtime::TockSyscalls>;\n    pub use console::ConsoleWriter;\n}\npub mod gpio {\n    use libtock_gpio as gpio;\n    pub type Gpio = gpio::Gpio<super::runtime::TockSyscalls>;\n    pub use gpio::{\n        Error, GpioInterruptListener, GpioState, InputPin, OutputPin, PinInterruptEdge, Pull,\n        PullDown, PullNone, PullUp,\n    };\n}\npub mod i2c_master {\n    use libtock_i2c_master as i2c_master;\n    pub type I2CMaster = i2c_master::I2CMaster<super::runtime::TockSyscalls>;\n}\npub mod i2c_master_slave {\n    use libtock_i2c_master_slave as i2c_master_slave;\n    pub type I2CMasterSlave = i2c_master_slave::I2CMasterSlave<super::runtime::TockSyscalls>;\n}\npub mod ieee802154 {\n    use libtock_ieee802154 as ieee802154;\n    pub type Ieee802154 = ieee802154::Ieee802154<super::runtime::TockSyscalls>;\n    pub use ieee802154::{Frame, RxOperator, RxRingBuffer};\n    pub type RxSingleBufferOperator<'buf, const N: usize> =\n        ieee802154::RxSingleBufferOperator<'buf, N, super::runtime::TockSyscalls>;\n}\npub mod leds {\n    use libtock_leds as leds;\n    pub type Leds = leds::Leds<super::runtime::TockSyscalls>;\n}\npub mod low_level_debug {\n    use libtock_low_level_debug as lldb;\n    pub type LowLevelDebug = lldb::LowLevelDebug<super::runtime::TockSyscalls>;\n    pub use lldb::AlertCode;\n}\npub mod ninedof {\n    use libtock_ninedof as ninedof;\n    pub type NineDof = ninedof::NineDof<super::runtime::TockSyscalls>;\n    pub use ninedof::NineDofListener;\n}\npub mod proximity {\n    use libtock_proximity as proximity;\n    pub type Proximity = proximity::Proximity<super::runtime::TockSyscalls>;\n}\npub mod rng {\n    use libtock_rng as rng;\n    pub type Rng = rng::Rng<super::runtime::TockSyscalls>;\n    pub use rng::RngListener;\n}\npub mod sound_pressure {\n    use libtock_sound_pressure as sound_pressure;\n    pub type SoundPressure = sound_pressure::SoundPressure<super::runtime::TockSyscalls>;\n}\n#[cfg(feature = \"rust_embedded\")]\npub mod spi_controller;\n#[cfg(not(feature = \"rust_embedded\"))]\npub mod spi_controller {\n    use libtock_spi_controller as spi_controller;\n    pub type SpiController = spi_controller::SpiController<super::runtime::TockSyscalls>;\n}\npub mod temperature {\n    use libtock_temperature as temperature;\n    pub type Temperature = temperature::Temperature<super::runtime::TockSyscalls>;\n    pub use temperature::TemperatureListener;\n}\npub mod key_value {\n    use libtock_key_value as key_value;\n    pub type KeyValue = key_value::KeyValue<super::runtime::TockSyscalls>;\n}\n"
  },
  {
    "path": "src/spi_controller.rs",
    "content": "use crate::alarm::{Alarm, Milliseconds};\nuse crate::platform::ErrorCode;\nuse libtock_spi_controller as spi_controller;\n\npub type SpiController = spi_controller::SpiController<super::runtime::TockSyscalls>;\n\npub struct EmbeddedHalSpi;\n\nimpl embedded_hal::spi::ErrorType for EmbeddedHalSpi {\n    type Error = ErrorCode;\n}\n\nimpl embedded_hal::spi::SpiDevice for EmbeddedHalSpi {\n    fn transaction(\n        &mut self,\n        operations: &mut [embedded_hal::spi::Operation<'_, u8>],\n    ) -> Result<(), Self::Error> {\n        for operation in operations {\n            match operation {\n                embedded_hal::spi::Operation::Read(read_buf) => {\n                    SpiController::spi_controller_read_sync(read_buf, read_buf.len() as u32)?\n                }\n                embedded_hal::spi::Operation::Write(write_buf) => {\n                    // writeln!(Console::writer(), \"Write: write_buf: {:x?}\\r\", write_buf).unwrap();\n                    SpiController::spi_controller_write_sync(write_buf, write_buf.len() as u32)\n                        .unwrap();\n                }\n                embedded_hal::spi::Operation::Transfer(read_buf, write_buf) => {\n                    // writeln!(Console::writer(), \"Transfer: write_buf: {:x?}\\r\", write_buf).unwrap();\n                    SpiController::spi_controller_write_read_sync(\n                        write_buf,\n                        read_buf,\n                        write_buf.len() as u32,\n                    )?\n                }\n                embedded_hal::spi::Operation::TransferInPlace(read_write_buf) => {\n                    // writeln!(Console::writer(), \"TransferInPlace: read_write_buf: {:x?}\\r\", read_write_buf).unwrap();\n                    SpiController::spi_controller_inplace_write_read_sync(\n                        read_write_buf,\n                        read_write_buf.len() as u32,\n                    )?\n                }\n                embedded_hal::spi::Operation::DelayNs(time) => {\n                    Alarm::sleep_for(Milliseconds(*time / 1000)).unwrap();\n                }\n            }\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "syscalls_tests/Cargo.toml",
    "content": "[package]\nedition = \"2021\"\nname = \"syscalls_tests\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[dependencies]\nlibtock_platform = { path = \"../platform\" }\nlibtock_unittest = { path = \"../unittest\" }\n"
  },
  {
    "path": "syscalls_tests/src/allow_ro.rs",
    "content": "use libtock_platform::{allow_ro, share, CommandReturn, ErrorCode, Syscalls};\nuse libtock_unittest::{command_return, fake, DriverInfo, RoAllowBuffer, SyscallLogEntry};\nuse std::cell::Cell;\nuse std::rc::Rc;\nuse std::thread_local;\n\n#[derive(Default)]\nstruct TestDriver {\n    buffer_0: Cell<RoAllowBuffer>,\n}\n\nimpl fake::SyscallDriver for TestDriver {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(42)\n    }\n\n    fn command(&self, _command_num: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        command_return::failure(ErrorCode::NoSupport)\n    }\n\n    fn allow_readonly(\n        &self,\n        buffer_num: u32,\n        buffer: RoAllowBuffer,\n    ) -> Result<RoAllowBuffer, (RoAllowBuffer, ErrorCode)> {\n        if buffer_num != 0 {\n            return Err((buffer, ErrorCode::NoSupport));\n        }\n        Ok(self.buffer_0.replace(buffer))\n    }\n}\n\nstruct TestConfig;\n\n// CALLED is set to true when returned_nonzero_buffer is called.\nthread_local! {static CALLED: Cell<bool> = const {Cell::new(false)} }\n\nimpl allow_ro::Config for TestConfig {\n    fn returned_nonzero_buffer(driver_num: u32, buffer_num: u32) {\n        assert_eq!(driver_num, 42);\n        assert_eq!(buffer_num, 0);\n        CALLED.with(|cell| cell.set(true));\n    }\n}\n\n#[test]\nfn allow_ro() {\n    let kernel = fake::Kernel::new();\n    let driver = Rc::new(TestDriver::default());\n    kernel.add_driver(&driver);\n    let buffer1 = [1, 2, 3, 4];\n    let buffer2 = [5, 6];\n    share::scope(|allow_ro| {\n        // Tests a call that should fail because it has an incorrect buffer\n        // number.\n        let result = fake::Syscalls::allow_ro::<TestConfig, 42, 1>(allow_ro, &buffer1);\n        assert!(!CALLED.with(|c| c.get()));\n        assert_eq!(result, Err(ErrorCode::NoSupport));\n        assert_eq!(\n            kernel.take_syscall_log(),\n            [SyscallLogEntry::AllowRo {\n                driver_num: 42,\n                buffer_num: 1,\n                len: 4,\n            }]\n        );\n    });\n\n    // Verify that share::scope unallowed the buffer.\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRo {\n            driver_num: 42,\n            buffer_num: 1,\n            len: 0,\n        }]\n    );\n\n    share::scope(|allow_ro| {\n        // Tests a call that should succeed and return a zero buffer.\n        let result = fake::Syscalls::allow_ro::<TestConfig, 42, 0>(allow_ro, &buffer1);\n        assert!(!CALLED.with(|c| c.get()));\n        assert_eq!(result, Ok(()));\n        assert_eq!(\n            kernel.take_syscall_log(),\n            [SyscallLogEntry::AllowRo {\n                driver_num: 42,\n                buffer_num: 0,\n                len: 4,\n            }]\n        );\n\n        // Tests a call that should succeed and return a nonzero buffer.\n        let result = fake::Syscalls::allow_ro::<TestConfig, 42, 0>(allow_ro, &buffer2);\n        assert!(CALLED.with(|c| c.get()));\n        assert_eq!(result, Ok(()));\n        assert_eq!(\n            kernel.take_syscall_log(),\n            [SyscallLogEntry::AllowRo {\n                driver_num: 42,\n                buffer_num: 0,\n                len: 2,\n            }]\n        );\n    });\n\n    // Verify that share::scope unallowed the buffer, but only once.\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRo {\n            driver_num: 42,\n            buffer_num: 0,\n            len: 0,\n        }]\n    );\n}\n"
  },
  {
    "path": "syscalls_tests/src/allow_rw.rs",
    "content": "use libtock_platform::{allow_rw, share, CommandReturn, ErrorCode, Syscalls};\nuse libtock_unittest::{command_return, fake, DriverInfo, RwAllowBuffer, SyscallLogEntry};\nuse std::cell::Cell;\nuse std::rc::Rc;\nuse std::thread_local;\n\n#[derive(Default)]\nstruct TestDriver {\n    buffer_0: Cell<RwAllowBuffer>,\n}\n\nimpl fake::SyscallDriver for TestDriver {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(42)\n    }\n\n    fn command(&self, _command_num: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        command_return::failure(ErrorCode::NoSupport)\n    }\n\n    fn allow_readwrite(\n        &self,\n        buffer_num: u32,\n        buffer: RwAllowBuffer,\n    ) -> Result<RwAllowBuffer, (RwAllowBuffer, ErrorCode)> {\n        if buffer_num != 0 {\n            return Err((buffer, ErrorCode::NoSupport));\n        }\n        Ok(self.buffer_0.replace(buffer))\n    }\n}\n\nstruct TestConfig;\n\n// CALLED is set to true when returned_nonzero_buffer is called.\nthread_local! {static CALLED: Cell<bool> = const {Cell::new(false)} }\n\nimpl allow_rw::Config for TestConfig {\n    fn returned_nonzero_buffer(driver_num: u32, buffer_num: u32) {\n        assert_eq!(driver_num, 42);\n        assert_eq!(buffer_num, 0);\n        CALLED.with(|cell| cell.set(true));\n    }\n}\n\n#[test]\nfn allow_rw() {\n    let kernel = fake::Kernel::new();\n    let driver = Rc::new(TestDriver::default());\n    kernel.add_driver(&driver);\n    let mut buffer1 = [1, 2, 3, 4];\n    let mut buffer2 = [5, 6];\n    share::scope(|allow_rw| {\n        // Tests a call that should fail because it has an incorrect buffer\n        // number.\n        let result = fake::Syscalls::allow_rw::<TestConfig, 42, 1>(allow_rw, &mut buffer1);\n        assert!(!CALLED.with(|c| c.get()));\n        assert_eq!(result, Err(ErrorCode::NoSupport));\n        assert_eq!(\n            kernel.take_syscall_log(),\n            [SyscallLogEntry::AllowRw {\n                driver_num: 42,\n                buffer_num: 1,\n                len: 4,\n            }]\n        );\n    });\n\n    // Verify that share::scope unallowed the buffer.\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRw {\n            driver_num: 42,\n            buffer_num: 1,\n            len: 0,\n        }]\n    );\n\n    share::scope(|allow_rw| {\n        // Tests a call that should succeed and return a zero buffer.\n        let result = fake::Syscalls::allow_rw::<TestConfig, 42, 0>(allow_rw, &mut buffer1);\n        assert!(!CALLED.with(|c| c.get()));\n        assert_eq!(result, Ok(()));\n        assert_eq!(\n            kernel.take_syscall_log(),\n            [SyscallLogEntry::AllowRw {\n                driver_num: 42,\n                buffer_num: 0,\n                len: 4,\n            }]\n        );\n\n        // Tests a call that should succeed and return a nonzero buffer.\n        let result = fake::Syscalls::allow_rw::<TestConfig, 42, 0>(allow_rw, &mut buffer2);\n        assert!(CALLED.with(|c| c.get()));\n        assert_eq!(result, Ok(()));\n        assert_eq!(\n            kernel.take_syscall_log(),\n            [SyscallLogEntry::AllowRw {\n                driver_num: 42,\n                buffer_num: 0,\n                len: 2,\n            }]\n        );\n\n        // Mutate the buffer, which under Miri will verify the buffer has been\n        // shared with the kernel properly.\n        let mut buffer = driver.buffer_0.take();\n        buffer[1] = 31;\n        driver.buffer_0.set(buffer);\n    });\n\n    // Verify that share::scope unallowed the buffer, but only once.\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRw {\n            driver_num: 42,\n            buffer_num: 0,\n            len: 0,\n        }]\n    );\n\n    // Verify the buffer write occurred.\n    assert_eq!(buffer2, [5, 31]);\n}\n"
  },
  {
    "path": "syscalls_tests/src/command_tests.rs",
    "content": "//! Tests for the Command system call implementation in\n//! `libtock_platform::Syscalls`.\n\nuse libtock_platform::Syscalls;\nuse libtock_unittest::{command_return, fake, ExpectedSyscall, SyscallLogEntry};\n\n#[test]\nfn command() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: 1,\n        command_id: 2,\n        argument0: 3,\n        argument1: 4,\n        override_return: Some(command_return::success_3_u32(1, 2, 3)),\n    });\n    assert_eq!(\n        fake::Syscalls::command(1, 2, 3, 4).get_success_3_u32(),\n        Some((1, 2, 3))\n    );\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Command {\n            driver_id: 1,\n            command_id: 2,\n            argument0: 3,\n            argument1: 4,\n        }]\n    );\n}\n"
  },
  {
    "path": "syscalls_tests/src/exit_on_drop.rs",
    "content": "use libtock_platform::exit_on_drop::ExitOnDrop;\nuse libtock_unittest::fake;\n\n// Unwinds if `unwind` is true, otherwise just returns.\nfn maybe_unwind(unwind: bool) {\n    if unwind {\n        panic!(\"Triggering stack unwinding.\");\n    }\n}\n\n#[cfg(not(miri))]\n#[test]\nfn exit() {\n    let exit = libtock_unittest::exit_test(\"exit_on_drop::exit\", || {\n        let exit_on_drop: ExitOnDrop<fake::Syscalls> = Default::default();\n        maybe_unwind(true);\n        core::mem::forget(exit_on_drop);\n    });\n    assert_eq!(exit, libtock_unittest::ExitCall::Terminate(0));\n}\n\n#[test]\nfn no_exit() {\n    let exit_on_drop: ExitOnDrop<fake::Syscalls> = Default::default();\n    maybe_unwind(false);\n    core::mem::forget(exit_on_drop);\n}\n"
  },
  {
    "path": "syscalls_tests/src/lib.rs",
    "content": "//! This crate contains tests for `libtock_platform` functionality that use the\n//! `Syscalls` implementation.\n//!\n//! These tests are not in `libtock_platform` because adding them to\n//! `libtock_platform causes two incompatible copies of `libtock_platform` to be\n//! compiled:\n//!   1. The `libtock_platform` with `cfg(test)` enabled\n//!   2. The `libtock_platform` that `libtock_unittest` depends on, which has\n//!      `cfg(test)` disabled.\n//!\n//! Mixing types from the two `libtock_platform` instantiations in tests results\n//! in confusing error messages, so instead those tests live in this crate.\n\n#[cfg(test)]\nmod allow_ro;\n\n#[cfg(test)]\nmod allow_rw;\n\n#[cfg(test)]\nmod command_tests;\n\n#[cfg(test)]\nmod exit_on_drop;\n\n// TODO: Add Exit.\n\n#[cfg(test)]\nmod memop_tests;\n\n#[cfg(test)]\nmod subscribe_tests;\n\n#[cfg(test)]\nmod yield_tests;\n"
  },
  {
    "path": "syscalls_tests/src/memop_tests.rs",
    "content": "//! Tests for the Memop system call implementation in\n//! `libtock_platform::Syscalls`.\n\nuse libtock_platform::{ErrorCode, Syscalls};\nuse libtock_unittest::{fake, ExpectedSyscall, SyscallLogEntry};\n\n#[test]\nfn memop() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 1,\n        argument0: 3.into(),\n        return_error: Some(ErrorCode::NoMem),\n    });\n    assert_eq!(\n        unsafe { fake::Syscalls::memop_sbrk(3) },\n        Err(ErrorCode::NoMem)\n    );\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Memop {\n            memop_num: 1,\n            argument0: 3.into(),\n        }]\n    );\n}\n\n#[test]\nfn brk_test() {\n    let kernel = fake::Kernel::new();\n    let fake_mem_buf = [0; 8];\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 0,\n        argument0: fake_mem_buf.as_ptr().into(),\n        return_error: None,\n    });\n    assert_eq!(\n        unsafe { fake::Syscalls::memop_brk(fake_mem_buf.as_ptr()) },\n        Ok(())\n    );\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Memop {\n            memop_num: 0,\n            argument0: fake_mem_buf.as_ptr().into(),\n        }]\n    );\n}\n\n#[test]\nfn sbrk_test() {\n    let kernel = fake::Kernel::new();\n    let fake_mem_buf = [0; 8];\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 0,\n        argument0: fake_mem_buf.as_ptr().into(),\n        return_error: None,\n    });\n    assert_eq!(\n        unsafe { fake::Syscalls::memop_brk(fake_mem_buf.as_ptr()) },\n        Ok(())\n    );\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 1,\n        argument0: 4.into(),\n        return_error: None,\n    });\n    assert_eq!(\n        unsafe { fake::Syscalls::memop_sbrk(4) },\n        Ok((&fake_mem_buf[4]) as *const u8)\n    );\n}\n\n#[test]\nfn increment_brk_test() {\n    let kernel = fake::Kernel::new();\n    let fake_mem_buf = [0; 8];\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 0,\n        argument0: fake_mem_buf.as_ptr().into(),\n        return_error: None,\n    });\n    assert_eq!(\n        unsafe { fake::Syscalls::memop_brk(fake_mem_buf.as_ptr()) },\n        Ok(())\n    );\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 1,\n        argument0: 4.into(),\n        return_error: None,\n    });\n    assert_eq!(\n        fake::Syscalls::memop_increment_brk(4),\n        Ok((&fake_mem_buf[4]) as *const u8)\n    );\n}\n\n#[test]\nfn app_ram_start_test() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 2,\n        argument0: 0.into(),\n        return_error: None,\n    });\n    assert!(fake::Syscalls::memop_app_ram_start().is_ok());\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Memop {\n            memop_num: 2,\n            argument0: 0.into(),\n        }]\n    );\n}\n\n#[test]\nfn debug_stack_start_test() {\n    let kernel = fake::Kernel::new();\n    let fake_stack = [0; 8];\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 10,\n        argument0: fake_stack.as_ptr().into(),\n        return_error: None,\n    });\n    assert!(fake::Syscalls::memop_debug_stack_start(fake_stack.as_ptr()).is_ok());\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Memop {\n            memop_num: 10,\n            argument0: fake_stack.as_ptr().into(),\n        }]\n    );\n}\n\n#[test]\nfn debug_heap_start_test() {\n    let kernel = fake::Kernel::new();\n    let fake_heap = [0; 8];\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 11,\n        argument0: fake_heap.as_ptr().into(),\n        return_error: None,\n    });\n    assert!(fake::Syscalls::memop_debug_heap_start(fake_heap.as_ptr()).is_ok());\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Memop {\n            memop_num: 11,\n            argument0: fake_heap.as_ptr().into(),\n        }]\n    );\n}\n"
  },
  {
    "path": "syscalls_tests/src/subscribe_tests.rs",
    "content": "use libtock_platform::{\n    share, subscribe, CommandReturn, DefaultConfig, ErrorCode, Syscalls, YieldNoWaitReturn,\n};\nuse libtock_unittest::{command_return, fake, DriverInfo, DriverShareRef, SyscallLogEntry};\nuse std::{cell::Cell, rc::Rc};\n\n// Fake driver that accepts an upcall.\n#[derive(Default)]\nstruct MockDriver {\n    share_ref: DriverShareRef,\n}\n\nimpl fake::SyscallDriver for MockDriver {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(1).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, _: u32, _: u32, _: u32) -> CommandReturn {\n        command_return::failure(ErrorCode::NoSupport)\n    }\n}\n\n#[test]\nfn config() {\n    // Thread local used by TestConfig to indicate that returned_nonnull_upcall\n    // has been called.\n    std::thread_local! {static CALLED: core::cell::Cell<Option<(u32, u32)>> = const {Cell::new(None)} }\n    struct TestConfig;\n    impl subscribe::Config for TestConfig {\n        fn returned_nonnull_upcall(driver_num: u32, subscribe_num: u32) {\n            CALLED.with(|cell| cell.set(Some((driver_num, subscribe_num))));\n        }\n    }\n\n    let kernel = fake::Kernel::new();\n    kernel.add_driver(&std::rc::Rc::new(MockDriver::default()));\n    let called = core::cell::Cell::new(false);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, TestConfig, 1, 0>(subscribe, &called),\n            Ok(())\n        );\n        assert_eq!(CALLED.with(|cell| cell.get()), None);\n\n        // Repeat the subscribe, which will make the kernel return the previous\n        // upcall. subscribe should invoke TestConfig::returned_nonnull_upcall.\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, TestConfig, 1, 0>(subscribe, &called),\n            Ok(())\n        );\n        assert_eq!(CALLED.with(|cell| cell.get()), Some((1, 0)));\n    });\n}\n\n#[test]\nfn failed() {\n    let _kernel = fake::Kernel::new();\n    let done = core::cell::Cell::new(false);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, 1, 2>(subscribe, &done),\n            Err(ErrorCode::NoDevice)\n        );\n    });\n}\n\n#[test]\nfn success() {\n    let driver = Rc::new(MockDriver::default());\n    let kernel = fake::Kernel::new();\n    kernel.add_driver(&driver);\n    let called = core::cell::Cell::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, 1, 0>(subscribe, &called),\n            Ok(())\n        );\n        assert_eq!(\n            kernel.take_syscall_log(),\n            [SyscallLogEntry::Subscribe {\n                driver_num: 1,\n                subscribe_num: 0\n            }]\n        );\n        driver.share_ref.schedule_upcall(0, (2, 3, 4)).unwrap();\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(called.get(), Some((2, 3, 4)));\n        // Clear the syscall log.\n        kernel.take_syscall_log();\n    });\n    // Verify the upcall was cleaned up correctly.\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Subscribe {\n            driver_num: 1,\n            subscribe_num: 0\n        }]\n    );\n    driver.share_ref.schedule_upcall(0, (2, 3, 4)).unwrap();\n    assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n}\n\n#[cfg(not(miri))]\n#[test]\nfn unwinding_upcall() {\n    struct BadUpcall;\n\n    impl libtock_platform::Upcall<subscribe::AnyId> for BadUpcall {\n        fn upcall(&self, _: u32, _: u32, _: u32) {\n            panic!(\"Beginning stack unwinding\");\n        }\n    }\n\n    let exit = libtock_unittest::exit_test(\"subscribe_tests::unwinding_upcall\", || {\n        let driver = Rc::new(MockDriver::default());\n        let kernel = fake::Kernel::new();\n        kernel.add_driver(&driver);\n        let upcall = BadUpcall;\n        share::scope(|subscribe| {\n            assert_eq!(\n                fake::Syscalls::subscribe::<_, _, DefaultConfig, 1, 0>(subscribe, &upcall),\n                Ok(())\n            );\n            driver.share_ref.schedule_upcall(0, (2, 3, 4)).unwrap();\n            assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        });\n    });\n    assert_eq!(exit, libtock_unittest::ExitCall::Terminate(0));\n}\n"
  },
  {
    "path": "syscalls_tests/src/yield_tests.rs",
    "content": "//! Tests for implementations of Yield system calls in\n//! `libtock_platform::Syscalls`.\n\nuse libtock_platform::{Syscalls, YieldNoWaitReturn};\nuse libtock_unittest::{fake, ExpectedSyscall, SyscallLogEntry};\n\n// Tests yield_no_wait with an upcall executed.\n#[test]\nfn no_wait_upcall() {\n    use YieldNoWaitReturn::Upcall;\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::YieldNoWait {\n        override_return: Some(Upcall),\n    });\n    assert_eq!(fake::Syscalls::yield_no_wait(), Upcall);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n}\n\n// Tests yield_no_wait with no upcall executed.\n#[test]\nfn no_wait_no_upcall() {\n    use YieldNoWaitReturn::NoUpcall;\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::YieldNoWait {\n        override_return: Some(NoUpcall),\n    });\n    assert_eq!(fake::Syscalls::yield_no_wait(), NoUpcall);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n}\n\n// Tests yield_wait.\n#[test]\nfn wait() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::YieldWait { skip_upcall: true });\n    fake::Syscalls::yield_wait();\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldWait]);\n}\n"
  },
  {
    "path": "tools/print_sizes/Cargo.toml",
    "content": "# Finds all the libtock_core and libtock examples and prints the sizes of\n# several of their sections. Searches the target/$ARCH/release directory. Note\n# that print_sizes will not build the examples; that is done by the\n# `print-sizes` Makefile action.\n\n[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\nedition = \"2018\"\nname = \"print_sizes\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[dependencies]\nelf = \"0.0.10\"\n"
  },
  {
    "path": "tools/print_sizes/src/main.rs",
    "content": "// Architectures that we expect the examples to be built for.\nconst ARCHITECTURES: [&str; 2] = [\"riscv32imc-unknown-none-elf\", \"thumbv7em-none-eabi\"];\n\n// The order of these fields actually matters, because it affects the derived\n// Ord impl. I have a suspicion that when I introduce size diffs into the CI,\n// this order will make the eventual diffs easier to understand than other\n// orderings.\n#[derive(Eq, PartialEq, PartialOrd, Ord)]\nstruct Example {\n    name: String,\n    arch: &'static str,\n    path: std::path::PathBuf,\n}\n\n// Finds the example binaries and returns a list of their paths.\nfn find_examples() -> Vec<Example> {\n    // Find target/ using std::env::current_exe().\n    let exe_dir = std::env::current_exe().expect(\"Unable to find executable location\");\n    let target_dir = exe_dir\n        .parent()\n        .expect(\"Unable to find target/ directory\")\n        .parent()\n        .expect(\"Unable to find target/ directory\");\n\n    let mut examples = Vec::new();\n\n    for arch in &ARCHITECTURES {\n        // Set examples_dir to target/$ARCH/examples/\n        let mut examples_dir = target_dir.to_path_buf();\n        examples_dir.push(arch);\n        examples_dir.push(\"release\");\n        examples_dir.push(\"examples\");\n\n        // If the architecture's examples directory exists, iterate through the\n        // files through it and search for examples. If the directory doesn't\n        // exist we skip this architecture.\n        if let Ok(read_dir) = examples_dir.read_dir() {\n            for file in read_dir.filter_map(Result::ok) {\n                use std::os::unix::ffi::OsStrExt;\n\n                // Skip entries that are not files. If file_type() returns\n                // Err(_) we skip the entry as well.\n                if !file.file_type().is_ok_and(|t| t.is_file()) {\n                    continue;\n                }\n\n                // Skip files with dots (*.d files) and hyphens (-$HASH) in\n                // them.\n                if file.file_name().as_bytes().contains(&b'.')\n                    || file.file_name().as_bytes().contains(&b'-')\n                {\n                    continue;\n                }\n\n                examples.push(Example {\n                    name: file.file_name().to_string_lossy().into_owned(),\n                    arch,\n                    path: file.path(),\n                });\n            }\n        }\n    }\n\n    examples\n}\n\nstruct ElfSizes {\n    bss: u64,\n    data: u64,\n    rodata: u64,\n    text: u64,\n}\n\nfn get_sizes(path: &std::path::Path) -> ElfSizes {\n    let file = elf::File::open_path(path).expect(\"Unable to open example binary\");\n    let mut sizes = ElfSizes {\n        bss: 0,\n        data: 0,\n        rodata: 0,\n        text: 0,\n    };\n    for section in file.sections {\n        match section.shdr.name.as_ref() {\n            \".bss\" => sizes.bss = section.shdr.size,\n            \".data\" => sizes.data = section.shdr.size,\n            \".rodata\" => sizes.rodata = section.shdr.size,\n            \".text\" => sizes.text = section.shdr.size,\n            _ => {}\n        }\n    }\n    sizes\n}\n\nstruct ExampleData {\n    name: String,\n    arch: &'static str,\n    sizes: ElfSizes,\n}\n\nfn main() {\n    let mut examples = find_examples();\n    examples.sort_unstable();\n    let example_data: Vec<_> = examples\n        .drain(..)\n        .map(|example| ExampleData {\n            name: example.name,\n            arch: example.arch,\n            sizes: get_sizes(&example.path),\n        })\n        .collect();\n\n    let name_width = 20;\n    let arch_width = example_data\n        .iter()\n        .map(|a| a.arch.len())\n        .max()\n        .expect(\"No examples found\");\n    let section_width = 7;\n\n    println!(\n        \"{0:1$} {2:3$} {4:>8$} {5:>8$} {6:>8$} {7:>8$}\",\n        \"Example\",\n        name_width,\n        \"Architecture\",\n        arch_width,\n        \".bss\",\n        \".data\",\n        \".text\",\n        \".rodata\",\n        section_width\n    );\n    for data in example_data {\n        println!(\n            \"{0:1$} {2:3$} {4:8$} {5:8$} {6:8$} {7:8$}\",\n            data.name,\n            name_width,\n            data.arch,\n            arch_width,\n            data.sizes.bss,\n            data.sizes.data,\n            data.sizes.text,\n            data.sizes.rodata,\n            section_width\n        );\n    }\n}\n"
  },
  {
    "path": "ufmt/Cargo.toml",
    "content": "[package]\nauthors = [\"Jorge Aparicio <jorge@japaric.io>\"]\ncategories = [\"embedded\", \"no-std\"]\ndescription = \"A (6-40x) smaller, (2-9x) faster and panic-free alternative to `core::fmt`\"\ndocumentation = \"https://docs.rs/ufmt\"\nedition = \"2021\"\nkeywords = [\"Debug\", \"Display\", \"Write\", \"format\"]\nlicense = \"MIT OR Apache-2.0\"\nname = \"ufmt\"\nreadme = \"README.md\"\nrepository = \"https://github.com/japaric/ufmt\"\nversion = \"0.1.0\"\n\n[dependencies]\nproc-macro-hack = \"0.5.11\"\nufmt-macros = { path = \"macros\", version = \"0.1.0\" }\nufmt-write = { path = \"write\", version = \"0.1.0\" }\n\n# NOTE do NOT add an `alloc` feature before the alloc crate can be used in\n# no-std BINARIES\n[features]\n# NOTE do NOT turn `std` into a default feature; this is a no-std first crate\nstd = [\"ufmt-write/std\"]\n\n[[test]]\nname = \"vs-std-write\"\nrequired-features = [\"std\"]\n"
  },
  {
    "path": "ufmt/LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "ufmt/LICENSE-MIT",
    "content": "Copyright (c) 2019 Jorge Aparicio\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "ufmt/README.md",
    "content": "# Tock fork of `ufmt`\n\n**This is a fork of the [ufmt](https://github.com/japaric/ufmt) crate.** We are\ncurrently evaluating whether `libtock-rs` should use `ufmt` for its debug\nformatting functionality. Because `ufmt` has unfixed bugs (and appears to be\nunmaintained), we have forked it here and are making bugfixes.\n\nThis fork is temporary and will be removed when one of the following happens:\n\n1. We decide that `ufmt` is the right solution for `libtock-rs`. If this\n   happens, we will work to restore the maintenance of `ufmt`.\n2. We decide that `ufmt` is not the right solution for `libtock-rs`, at which\n   point we will replace it with an alternative.\n\nWe did the following to create this fork:\n\n1. `wget 'https://github.com/japaric/ufmt/archive/fe817a3cd5d1a3f4edaf8828193519069f2901ec.zip'`\n1. `unzip fe817a3cd5d1a3f4edaf8828193519069f2901ec.zip`\n1. `mv ufmt-fe817a3cd5d1a3f4edaf8828193519069f2901ec ufmt`\n1. Changed the wording of the License section of `libtock-rs`' `README.md` to\n   mention that `ufmt` has its own license.\n1. cd `ufmt`\n1. Removed CI infrastructure and tools that aren't used now that this is in a\n   subdirectory of `libtock-rs`:\n   `rm -r cg.png ci .github .gitignore nopanic .travis.yml`\n1. Committed, creating commit\n   [5163051a2d7fefbe4c9b1c6ba62b79fa07c324e7](https://github.com/tock/libtock-rs/commit/5163051a2d7fefbe4c9b1c6ba62b79fa07c324e7).\n\nFurther changes beyond the commit mentioned above are in separate commits so\ntheir diffs are readable.\n\n# `μfmt`\n\n> A (6-40x) smaller, (2-9x) faster and panic-free alternative to `core::fmt`\n\n![Call graph of formatting structs](cg.png)\n\nCall graph of a program that formats some structs (generated using\n[`cargo-call-stack`]). Source code can be found at the bottom of this file. The\nprogram was compiled with `-C opt-level=z`.\n\n[`cargo-call-stack`]: https://crates.io/crates/cargo-call-stack\n\n## [API docs](https://docs.rs/ufmt)\n\n## Design goals\n\nFrom highest priority to lowest priority\n\n- Optimized for binary size and speed (rather than for compilation time)\n\n- No dynamic dispatch in generated code\n\n- No panicking branches in generated code, when optimized\n\n- No recursion where possible\n\n## Features\n\n- `Debug` and `Display`-like traits\n\n- `core::write!`-like macro\n\n- A generic `Formatter<'_, impl uWrite>` instead of a single `core::Formatter`;\n  the `uWrite` trait has an associated error type so each writer can choose its\n  error type. For example, the implementation for `std::String` uses\n  `Infallible` as its error type.\n\n- `core::fmt::Formatter::debug_struct`-like API\n\n- `#[derive(uDebug)]`\n\n- Pretty formatting (`{:#?}`) for `uDebug`\n\n# Minimum Supported Rust Version (MSRV)\n\nThis crate is guaranteed to compile on stable Rust 1.34 and up. It *might*\ncompile on older versions but that may change in any new patch release.\n\n## License\n\nAll source code (including code snippets) is licensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or\n  [https://www.apache.org/licenses/LICENSE-2.0][L1])\n\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or\n  [https://opensource.org/licenses/MIT][L2])\n\n[L1]: https://www.apache.org/licenses/LICENSE-2.0\n[L2]: https://opensource.org/licenses/MIT\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\nlicensed as above, without any additional terms or conditions.\n\n## Appendix\n\n### Formatting structs (snippet)\n\nFull source code in [nopanic/examples/struct.rs](nopanic/examples/struct.rs).\n\n``` rust\n// ..\n\n#[derive(Clone, Copy, uDebug)]\nstruct Pair {\n    x: i32,\n    y: i32,\n}\n\nstatic X: AtomicI32 = AtomicI32::new(0);\nstatic Y: AtomicI32 = AtomicI32::new(0);\n\n#[exception]\nfn PendSV() {\n    let x = X.load(Ordering::Relaxed);\n    let y = Y.load(Ordering::Relaxed);\n\n    uwrite!(&mut W, \"{:?}\", Braces {}).unwrap();\n    uwrite!(&mut W, \"{:#?}\", Braces {}).unwrap();\n\n    uwrite!(&mut W, \"{:?}\", Parens()).unwrap();\n    uwrite!(&mut W, \"{:#?}\", Parens()).unwrap();\n\n    uwrite!(&mut W, \"{:?}\", I32(x)).unwrap();\n    uwrite!(&mut W, \"{:#?}\", I32(x)).unwrap();\n\n    uwrite!(&mut W, \"{:?}\", Tuple(x, y)).unwrap();\n    uwrite!(&mut W, \"{:#?}\", Tuple(x, y)).unwrap();\n\n    let pair = Pair { x, y };\n    uwrite!(&mut W, \"{:?}\", pair).unwrap();\n    uwrite!(&mut W, \"{:#?}\", pair).unwrap();\n\n    let first = pair;\n    let second = pair;\n    uwrite!(&mut W, \"{:?}\", Nested { first, second }).unwrap();\n    uwrite!(&mut W, \"{:#?}\", Nested { first, second }).unwrap();\n}\n\n// ..\n```\n"
  },
  {
    "path": "ufmt/macros/Cargo.toml",
    "content": "[package]\nauthors = [\"Jorge Aparicio <jorge@japaric.io>\"]\ncategories = [\"embedded\", \"no-std\"]\ndescription = \"`μfmt` macros\"\nedition = \"2021\"\nkeywords = [\"Debug\", \"Display\", \"Write\", \"format\"]\nlicense = \"MIT OR Apache-2.0\"\nname = \"ufmt-macros\"\nrepository = \"https://github.com/japaric/ufmt\"\nversion = \"0.1.1\"\n\n[lib]\nproc-macro = true\n\n[dependencies]\nproc-macro-hack = \"0.5.11\"\nproc-macro2 = \"1\"\nquote = \"1\"\nregex = \"1.5.4\"\nlazy_static = \"1.4.0\"\n\n[dependencies.syn]\nfeatures = [\"full\"]\nversion = \"1\"\n"
  },
  {
    "path": "ufmt/macros/src/lib.rs",
    "content": "//! `μfmt` macros\n\n// Added when we vendored ufmt into libtock-rs to avoid needing to immediately\n// make many changes.\n#![allow(clippy::all)]\n#![deny(warnings)]\n\nextern crate proc_macro;\n\nuse core::mem;\nuse proc_macro::TokenStream;\nuse std::borrow::Cow;\n\nuse lazy_static::lazy_static;\nuse proc_macro2::{Literal, Span};\nuse proc_macro_hack::proc_macro_hack;\nuse quote::quote;\nuse syn::{\n    parse::{self, Parse, ParseStream},\n    parse_macro_input, parse_quote,\n    punctuated::Punctuated,\n    spanned::Spanned,\n    Data, DeriveInput, Expr, Fields, GenericParam, Ident, LitStr, Token,\n};\n\n/// Automatically derive the `uDebug` trait for a `struct` or `enum`\n///\n/// Supported items\n///\n/// - all kind of `struct`-s\n/// - all kind of `enum`-s\n///\n/// `union`-s are not supported\n#[proc_macro_derive(uDebug)]\npub fn debug(input: TokenStream) -> TokenStream {\n    let input = parse_macro_input!(input as DeriveInput);\n\n    let mut generics = input.generics;\n\n    for param in &mut generics.params {\n        if let GenericParam::Type(type_param) = param {\n            type_param.bounds.push(parse_quote!(ufmt::uDebug));\n        }\n    }\n\n    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();\n\n    let ident = &input.ident;\n    let ts = match input.data {\n        Data::Struct(data) => {\n            let ident_s = ident.to_string();\n\n            let body = match data.fields {\n                Fields::Named(fields) => {\n                    let fields = fields\n                        .named\n                        .iter()\n                        .map(|field| {\n                            let ident = field.ident.as_ref().expect(\"UNREACHABLE\");\n                            let name = ident.to_string();\n\n                            quote!(field(#name, &self.#ident)?)\n                        })\n                        .collect::<Vec<_>>();\n\n                    quote!(f.debug_struct(#ident_s)?#(.#fields)*.finish())\n                }\n\n                Fields::Unnamed(fields) => {\n                    let fields = (0..fields.unnamed.len())\n                        .map(|i| {\n                            let i = Literal::u64_unsuffixed(i as u64);\n\n                            quote!(field(&self.#i)?)\n                        })\n                        .collect::<Vec<_>>();\n\n                    quote!(f.debug_tuple(#ident_s)?#(.#fields)*.finish())\n                }\n\n                Fields::Unit => quote!(f.write_str(#ident_s)),\n            };\n\n            quote!(\n                impl #impl_generics ufmt::uDebug for #ident #ty_generics #where_clause {\n                    fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> core::result::Result<(), W::Error>\n                    where\n                        W: ufmt::uWrite + ?Sized,\n                    {\n                        #body\n                    }\n                }\n\n            )\n        }\n\n        Data::Enum(data) => {\n            let arms = data\n                .variants\n                .iter()\n                .map(|var| {\n                    let variant = &var.ident;\n                    let variant_s = variant.to_string();\n\n                    match &var.fields {\n                        Fields::Named(fields) => {\n                            let mut pats = Vec::with_capacity(fields.named.len());\n                            let mut methods = Vec::with_capacity(fields.named.len());\n                            for field in &fields.named {\n                                let ident = field.ident.as_ref().unwrap();\n                                let ident_s = ident.to_string();\n\n                                pats.push(quote!(#ident));\n                                methods.push(quote!(field(#ident_s, #ident)?));\n                            }\n\n                            quote!(\n                                #ident::#variant { #(#pats),* } => {\n                                    f.debug_struct(#variant_s)?#(.#methods)*.finish()\n                                }\n                            )\n                        }\n\n                        Fields::Unnamed(fields) => {\n                            let pats = &(0..fields.unnamed.len())\n                                .map(|i| Ident::new(&format!(\"_{}\", i), Span::call_site()))\n                                .collect::<Vec<_>>();\n\n                            quote!(\n                                #ident::#variant(#(#pats),*) => {\n                                    f.debug_tuple(#variant_s)?#(.field(#pats)?)*.finish()\n                                }\n                            )\n                        }\n\n                        Fields::Unit => quote!(\n                            #ident::#variant => {\n                                f.write_str(#variant_s)\n                            }\n                        ),\n                    }\n                })\n                .collect::<Vec<_>>();\n\n            quote!(\n                impl #impl_generics ufmt::uDebug for #ident #ty_generics #where_clause {\n                    fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> core::result::Result<(), W::Error>\n                        where\n                        W: ufmt::uWrite + ?Sized,\n                    {\n                        match self {\n                            #(#arms),*\n                        }\n                    }\n                }\n            )\n        }\n\n        Data::Union(..) => {\n            return parse::Error::new(Span::call_site(), \"this trait cannot be derived for unions\")\n                .to_compile_error()\n                .into();\n        }\n    };\n\n    ts.into()\n}\n\n#[proc_macro_hack]\npub fn uwrite(input: TokenStream) -> TokenStream {\n    write(input, false)\n}\n\n#[proc_macro_hack]\npub fn uwriteln(input: TokenStream) -> TokenStream {\n    write(input, true)\n}\n\nfn write(input: TokenStream, newline: bool) -> TokenStream {\n    let input = parse_macro_input!(input as Input);\n\n    let formatter = &input.formatter;\n    let literal = input.literal;\n\n    let mut format = literal.value();\n    if newline {\n        format.push('\\n');\n    }\n    let pieces = match parse(&format, literal.span()) {\n        Err(e) => return e.to_compile_error().into(),\n        Ok(pieces) => pieces,\n    };\n\n    let required_args = pieces.iter().filter(|piece| !piece.is_str()).count();\n    let supplied_args = input.args.len();\n    if supplied_args < required_args {\n        return parse::Error::new(\n            literal.span(),\n            &format!(\n                \"format string requires {} arguments but {} {} supplied\",\n                required_args,\n                supplied_args,\n                if supplied_args == 1 { \"was\" } else { \"were\" }\n            ),\n        )\n        .to_compile_error()\n        .into();\n    } else if supplied_args > required_args {\n        return parse::Error::new(\n            input.args[required_args].span(),\n            &format!(\"argument never used\"),\n        )\n        .to_compile_error()\n        .into();\n    }\n\n    let mut args = vec![];\n    let mut pats = vec![];\n    let mut exprs = vec![];\n    let mut i = 0;\n    for piece in pieces {\n        if let Piece::Str(s) = piece {\n            exprs.push(quote!(f.write_str(#s)?;))\n        } else {\n            let pat = mk_ident(i);\n            let arg = &input.args[i];\n            i += 1;\n\n            args.push(quote!(&(#arg)));\n            pats.push(quote!(#pat));\n\n            match piece {\n                Piece::Display {\n                    pretty,\n                    hex,\n                    width,\n                    pad,\n                } => {\n                    exprs.push(if let Some(w) = width {\n                        if let Some(case) = hex {\n                            if case == Hex::Lower {\n                                quote!(f.fixed_width(#pretty, Some(true), Some(#w), #pad, |f| ufmt::uDisplay::fmt(#pat, f))?;)\n                            } else {\n                                quote!(f.fixed_width(#pretty, Some(false), Some(#w), #pad, |f| ufmt::uDisplay::fmt(#pat, f))?;)\n                            }\n                        } else {\n                            quote!(f.fixed_width(#pretty, None, Some(#w), #pad, |f| ufmt::uDisplay::fmt(#pat, f))?;)\n                        }\n                    } else if hex == Some(Hex::Lower) && pretty {\n                        quote!(f.hex(true, true, |f| ufmt::uDisplay::fmt(#pat, f))?;)\n                    } else if hex == Some(Hex::Upper) && pretty {\n                        quote!(f.hex(false, true, |f| ufmt::uDisplay::fmt(#pat, f))?;)\n                    } else if hex == Some(Hex::Lower) {\n                        quote!(f.hex(true, false, |f| ufmt::uDisplay::fmt(#pat, f))?;)\n                    } else if hex == Some(Hex::Upper) {\n                        quote!(f.hex(false, false, |f| ufmt::uDisplay::fmt(#pat, f))?;)\n                    } else if pretty {\n                        quote!(f.pretty(|f| ufmt::uDisplay::fmt(#pat, f))?;)\n                    } else {\n                        quote!(ufmt::uDisplay::fmt(#pat, f)?;)\n                    });\n                }\n\n                Piece::Debug { pretty } => {\n                    exprs.push(if pretty {\n                        quote!(f.pretty(|f| ufmt::uDebug::fmt(#pat, f))?;)\n                    } else {\n                        quote!(ufmt::uDebug::fmt(#pat, f)?;)\n                    });\n                }\n\n                _ => unreachable!(),\n            }\n        }\n    }\n\n    quote!(match (#(#args),*) {\n        (#(#pats),*) => {\n            use ufmt::UnstableDoAsFormatter as _;\n\n            (#formatter).do_as_formatter(|f| {\n                #(#exprs)*\n                Ok(())\n            })\n        }\n    })\n    .into()\n}\n\nstruct Input {\n    formatter: Expr,\n    _comma: Token![,],\n    literal: LitStr,\n    _comma2: Option<Token![,]>,\n    args: Punctuated<Expr, Token![,]>,\n}\n\nimpl Parse for Input {\n    fn parse(input: ParseStream) -> parse::Result<Self> {\n        let formatter = input.parse()?;\n        let _comma = input.parse()?;\n        let literal = input.parse()?;\n\n        if input.is_empty() {\n            Ok(Input {\n                formatter,\n                _comma,\n                literal,\n                _comma2: None,\n                args: Punctuated::new(),\n            })\n        } else {\n            Ok(Input {\n                formatter,\n                _comma,\n                literal,\n                _comma2: input.parse()?,\n                args: Punctuated::parse_terminated(input)?,\n            })\n        }\n    }\n}\n\n#[derive(Debug, PartialEq)]\npub(crate) enum Hex {\n    Upper,\n    Lower,\n}\n\n#[derive(Debug, PartialEq)]\nenum Piece<'a> {\n    Debug {\n        pretty: bool,\n    },\n    Display {\n        pretty: bool,\n        hex: Option<Hex>,\n        width: Option<u8>,\n        pad: char,\n    },\n    Str(Cow<'a, str>),\n}\n\nimpl Piece<'_> {\n    fn is_str(&self) -> bool {\n        match self {\n            Piece::Str(_) => true,\n            _ => false,\n        }\n    }\n}\n\nfn mk_ident(i: usize) -> Ident {\n    Ident::new(&format!(\"__{}\", i), Span::call_site())\n}\n\n// `}}` -> `}`\nfn unescape<'l>(mut literal: &'l str, span: Span) -> parse::Result<Cow<'l, str>> {\n    if literal.contains('}') {\n        let mut buf = String::new();\n\n        while literal.contains('}') {\n            const ERR: &str = \"format string contains an unmatched right brace\";\n            let mut parts = literal.splitn(2, '}');\n\n            match (parts.next(), parts.next()) {\n                (Some(left), Some(right)) => {\n                    const ESCAPED_BRACE: &str = \"}\";\n\n                    if right.starts_with(ESCAPED_BRACE) {\n                        buf.push_str(left);\n                        buf.push('}');\n\n                        literal = &right[ESCAPED_BRACE.len()..];\n                    } else {\n                        return Err(parse::Error::new(span, ERR));\n                    }\n                }\n\n                _ => unreachable!(),\n            }\n        }\n\n        buf.push_str(literal);\n\n        Ok(buf.into())\n    } else {\n        Ok(Cow::Borrowed(literal))\n    }\n}\n\nfn parse<'l>(mut literal: &'l str, span: Span) -> parse::Result<Vec<Piece<'l>>> {\n    let mut pieces = vec![];\n\n    let mut buf = String::new();\n    loop {\n        let mut parts = literal.splitn(2, '{');\n        match (parts.next(), parts.next()) {\n            // empty string literal\n            (None, None) => break,\n\n            // end of the string literal\n            (Some(s), None) => {\n                if buf.is_empty() {\n                    if !s.is_empty() {\n                        pieces.push(Piece::Str(unescape(s, span)?));\n                    }\n                } else {\n                    buf.push_str(&unescape(s, span)?);\n\n                    pieces.push(Piece::Str(Cow::Owned(buf)));\n                }\n\n                break;\n            }\n\n            (head, Some(tail)) => {\n                const DEBUG: &str = \":?}\";\n                const DEBUG_PRETTY: &str = \":#?}\";\n                const DISPLAY: &str = \"}\";\n                const ESCAPED_BRACE: &str = \"{\";\n\n                use regex::Regex;\n                lazy_static! {\n                    static ref WIDTH_REGEX: Regex =\n                        Regex::new(r\"^:(#?)(0?)([0-9]*)([x|X]?)}\").unwrap();\n                }\n                let head = head.unwrap_or(\"\");\n                if tail.starts_with(DEBUG)\n                    || tail.starts_with(DEBUG_PRETTY)\n                    || tail.starts_with(DISPLAY)\n                    || WIDTH_REGEX.is_match(tail)\n                // for width specifiers\n                {\n                    if buf.is_empty() {\n                        if !head.is_empty() {\n                            pieces.push(Piece::Str(unescape(head, span)?));\n                        }\n                    } else {\n                        buf.push_str(&unescape(head, span)?);\n\n                        pieces.push(Piece::Str(Cow::Owned(mem::replace(\n                            &mut buf,\n                            String::new(),\n                        ))));\n                    }\n\n                    if tail.starts_with(DEBUG) {\n                        pieces.push(Piece::Debug { pretty: false });\n\n                        literal = &tail[DEBUG.len()..];\n                    } else if tail.starts_with(DEBUG_PRETTY) {\n                        pieces.push(Piece::Debug { pretty: true });\n\n                        literal = &tail[DEBUG_PRETTY.len()..];\n                    } else if let Some(cap) = WIDTH_REGEX.captures(tail) {\n                        let leading_pound = cap[1].eq(\"#\");\n                        let leading_zero = cap[2].eq(\"0\");\n                        let width = if cap[3].len() > 0 {\n                            Some(cap[3].parse::<u8>().map_err(|_| {\n                                parse::Error::new(\n                                    span,\n                                    \"invalid width specifier: expected valid u8\",\n                                )\n                            })?)\n                        } else {\n                            None\n                        };\n                        // 18 is the smallest buffer used by any numeric uDebug impl\n                        // By increasing that buffer size, we could increase this maximum value,\n                        // at the cost of cycles and a small amount of size\n                        if let Some(w) = width {\n                            if w > 18 {\n                                return Err(parse::Error::new(\n                                    span,\n                                    \"invalid width specifier: maximum allowed specifier is 18\",\n                                ));\n                            }\n                        }\n                        let hex = if cap[4].eq(\"x\") {\n                            Some(Hex::Lower)\n                        } else if cap[4].eq(\"X\") {\n                            Some(Hex::Upper)\n                        } else {\n                            None\n                        };\n                        pieces.push(Piece::Display {\n                            pretty: leading_pound,\n                            hex,\n                            width,\n                            pad: if leading_zero { '0' } else { ' ' },\n                        });\n\n                        // first capture is entire match\n                        literal = &tail[cap[0].len()..];\n                    } else {\n                        pieces.push(Piece::Display {\n                            pretty: false,\n                            hex: None,\n                            width: None,\n                            pad: ' ',\n                        });\n\n                        literal = &tail[DISPLAY.len()..];\n                    }\n                } else if tail.starts_with(ESCAPED_BRACE) {\n                    buf.push_str(&unescape(head, span)?);\n                    buf.push('{');\n\n                    literal = &tail[ESCAPED_BRACE.len()..];\n                } else {\n                    return Err(parse::Error::new(\n                        span,\n                        \"invalid format string: expected `{{`, `{}`, `{:?}`, `{:#?}`, `{:x}`, `{:#x}`, or a width specifier}\",\n                    ));\n                }\n            }\n        }\n    }\n\n    Ok(pieces)\n}\n\n#[cfg(test)]\nmod tests {\n    use std::borrow::Cow;\n\n    use proc_macro2::Span;\n\n    use crate::Hex;\n    use crate::Piece;\n\n    #[test]\n    fn pieces() {\n        let span = Span::call_site();\n\n        // string interpolation\n        assert_eq!(\n            super::parse(\"The answer is {}\", span).ok(),\n            Some(vec![\n                Piece::Str(Cow::Borrowed(\"The answer is \")),\n                Piece::Display {\n                    pretty: false,\n                    hex: None,\n                    width: None,\n                    pad: ' '\n                }\n            ]),\n        );\n\n        assert_eq!(\n            super::parse(\"{:?}\", span).ok(),\n            Some(vec![Piece::Debug { pretty: false }]),\n        );\n\n        assert_eq!(\n            super::parse(\"{:#?}\", span).ok(),\n            Some(vec![Piece::Debug { pretty: true }]),\n        );\n\n        assert_eq!(\n            super::parse(\"{:x}\", span).ok(),\n            Some(vec![Piece::Display {\n                pretty: false,\n                hex: Some(Hex::Lower),\n                width: None,\n                pad: ' ',\n            }]),\n        );\n\n        assert_eq!(\n            super::parse(\"{:X}\", span).ok(),\n            Some(vec![Piece::Display {\n                pretty: false,\n                hex: Some(Hex::Upper),\n                width: None,\n                pad: ' ',\n            }]),\n        );\n\n        assert_eq!(\n            super::parse(\"{:10x}\", span).ok(),\n            Some(vec![Piece::Display {\n                pretty: false,\n                hex: Some(Hex::Lower),\n                width: Some(10),\n                pad: ' ',\n            }]),\n        );\n\n        assert_eq!(\n            super::parse(\"{:08x}\", span).ok(),\n            Some(vec![Piece::Display {\n                pretty: false,\n                hex: Some(Hex::Lower),\n                width: Some(8),\n                pad: '0',\n            }]),\n        );\n\n        assert_eq!(\n            super::parse(\"{:#08x}\", span).ok(),\n            Some(vec![Piece::Display {\n                pretty: true,\n                hex: Some(Hex::Lower),\n                width: Some(8),\n                pad: '0',\n            }]),\n        );\n\n        // escaped braces\n        assert_eq!(\n            super::parse(\"{{}} is not an argument\", span).ok(),\n            Some(vec![Piece::Str(Cow::Borrowed(\"{} is not an argument\"))]),\n        );\n\n        // left brace & junk\n        assert!(super::parse(\"{\", span).is_err());\n        assert!(super::parse(\" {\", span).is_err());\n        assert!(super::parse(\"{ \", span).is_err());\n        assert!(super::parse(\"{ {\", span).is_err());\n    }\n\n    #[test]\n    fn unescape() {\n        let span = Span::call_site();\n\n        // no right brace\n        assert_eq!(super::unescape(\"\", span).ok(), Some(Cow::Borrowed(\"\")));\n        assert_eq!(\n            super::unescape(\"Hello\", span).ok(),\n            Some(Cow::Borrowed(\"Hello\"))\n        );\n\n        // unmatched right brace\n        assert!(super::unescape(\" }\", span).is_err());\n        assert!(super::unescape(\"} \", span).is_err());\n        assert!(super::unescape(\"}\", span).is_err());\n\n        // escaped right brace\n        assert_eq!(super::unescape(\"}}\", span).ok(), Some(Cow::Borrowed(\"}\")));\n        assert_eq!(super::unescape(\"}} \", span).ok(), Some(Cow::Borrowed(\"} \")));\n    }\n}\n"
  },
  {
    "path": "ufmt/src/helpers.rs",
    "content": "use crate::{uDebug, uWrite, Formatter};\n\nimpl<'w, W> Formatter<'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    /// Creates a `DebugList` builder designed to assist with creation of `uDebug` implementations\n    /// for list-like structures.\n    pub fn debug_list(&mut self) -> Result<DebugList<'_, 'w, W>, W::Error> {\n        self.write_str(\"[\")?;\n\n        if self.pretty {\n            self.indentation += 1;\n        }\n\n        Ok(DebugList {\n            first: true,\n            formatter: self,\n        })\n    }\n\n    /// Creates a `DebugMap` builder designed to assist with creation of `uDebug` implementations\n    /// for map-like structures.\n    pub fn debug_map(&mut self) -> Result<DebugMap<'_, 'w, W>, W::Error> {\n        self.write_str(\"{\")?;\n\n        if self.pretty {\n            self.indentation += 1;\n        }\n\n        Ok(DebugMap {\n            first: true,\n            formatter: self,\n        })\n    }\n\n    /// Creates a `DebugSet` builder designed to assist with creation of `uDebug` implementations\n    /// for set-like structures.\n    pub fn debug_set(&mut self) -> Result<DebugSet<'_, 'w, W>, W::Error> {\n        self.write_str(\"{\")?;\n\n        if self.pretty {\n            self.indentation += 1;\n        }\n\n        Ok(DebugSet {\n            first: true,\n            formatter: self,\n        })\n    }\n\n    /// Creates a `DebugStruct` builder designed to assist with creation of `uDebug` implementations\n    /// for structs.\n    pub fn debug_struct(&mut self, name: &str) -> Result<DebugStruct<'_, 'w, W>, W::Error> {\n        self.write_str(name)?;\n\n        if self.pretty {\n            self.indentation += 1;\n        }\n\n        Ok(DebugStruct {\n            first: true,\n            formatter: self,\n        })\n    }\n\n    /// Creates a `DebugTuple` builder designed to assist with creation of `uDebug` implementations\n    /// for tuple structs.\n    pub fn debug_tuple(&mut self, name: &str) -> Result<DebugTuple<'_, 'w, W>, W::Error> {\n        self.write_str(name)?;\n\n        if self.pretty {\n            self.indentation += 1;\n        }\n\n        Ok(DebugTuple {\n            fields: 0,\n            first: true,\n            formatter: self,\n            unnamed: name.is_empty(),\n        })\n    }\n}\n\n/// A struct to help with [`uDebug`] implementations.\n///\n/// This is useful when you wish to output a formatted list of items as a part of your\n/// [`uDebug::fmt`] implementation.\n///\n/// This can be constructed by the [`Formatter::debug_list`] method.\npub struct DebugList<'f, 'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    first: bool,\n    formatter: &'f mut Formatter<'w, W>,\n}\n\nimpl<W> DebugList<'_, '_, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    /// Adds a new entry to the list output.\n    pub fn entry(&mut self, entry: &impl uDebug) -> Result<&mut Self, W::Error> {\n        if self.first {\n            self.first = false;\n\n            if self.formatter.pretty {\n                self.formatter.write_str(\"\\n\")?;\n            }\n        } else if !self.formatter.pretty {\n            self.formatter.write_str(\", \")?;\n        }\n\n        if self.formatter.pretty {\n            self.formatter.indent()?;\n        }\n\n        entry.fmt(self.formatter)?;\n\n        if self.formatter.pretty {\n            self.formatter.write_str(\",\\n\")?;\n        }\n\n        Ok(self)\n    }\n\n    /// Adds the contents of an iterator of entries to the list output.\n    pub fn entries(\n        &mut self,\n        entries: impl IntoIterator<Item = impl uDebug>,\n    ) -> Result<&mut Self, W::Error> {\n        for entry in entries {\n            self.entry(&entry)?;\n        }\n\n        Ok(self)\n    }\n\n    /// Finishes output\n    pub fn finish(&mut self) -> Result<(), W::Error> {\n        if self.formatter.pretty {\n            self.formatter.indentation -= 1;\n            self.formatter.indent()?;\n        }\n\n        self.formatter.write_str(\"]\")\n    }\n}\n\n/// A struct to help with [`uDebug`] implementations.\n///\n/// This is useful when you wish to output a formatted map as a part of your [`uDebug::fmt`]\n/// implementation.\n///\n/// This can be constructed by the [`Formatter::debug_map`] method.\npub struct DebugMap<'f, 'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    first: bool,\n    formatter: &'f mut Formatter<'w, W>,\n}\n\nimpl<W> DebugMap<'_, '_, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    /// Adds a new entry to the map output.\n    pub fn entry(&mut self, key: &impl uDebug, value: &impl uDebug) -> Result<&mut Self, W::Error> {\n        if self.first {\n            self.first = false;\n\n            if self.formatter.pretty {\n                self.formatter.write_str(\"\\n\")?;\n            }\n        } else if !self.formatter.pretty {\n            self.formatter.write_str(\", \")?;\n        }\n\n        if self.formatter.pretty {\n            self.formatter.indent()?;\n        }\n\n        key.fmt(self.formatter)?;\n        self.formatter.write_str(\": \")?;\n        value.fmt(self.formatter)?;\n\n        if self.formatter.pretty {\n            self.formatter.write_str(\",\\n\")?;\n        }\n\n        Ok(self)\n    }\n\n    /// Adds the contents of an iterator of entries to the map output.\n    pub fn entries(\n        &mut self,\n        entries: impl IntoIterator<Item = (impl uDebug, impl uDebug)>,\n    ) -> Result<&mut Self, W::Error> {\n        for (k, v) in entries.into_iter() {\n            self.entry(&k, &v)?;\n        }\n\n        Ok(self)\n    }\n\n    /// Finishes output\n    pub fn finish(&mut self) -> Result<(), W::Error> {\n        self.formatter.write_str(\"}\")\n    }\n}\n\n/// A struct to help with [`uDebug`] implementations.\n///\n/// This is useful when you wish to output a formatted set of items as a part of your\n/// [`uDebug::fmt`] implementation.\n///\n/// This can be constructed by the [`Formatter::debug_set`] method.\npub struct DebugSet<'f, 'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    first: bool,\n    formatter: &'f mut Formatter<'w, W>,\n}\n\nimpl<W> DebugSet<'_, '_, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    /// Adds a new entry to the set output.\n    pub fn entry(&mut self, entry: &impl uDebug) -> Result<&mut Self, W::Error> {\n        if self.first {\n            self.first = false;\n\n            if self.formatter.pretty {\n                self.formatter.write_str(\"\\n\")?;\n            }\n        } else if !self.formatter.pretty {\n            self.formatter.write_str(\", \")?;\n        }\n\n        if self.formatter.pretty {\n            self.formatter.indent()?;\n        }\n\n        entry.fmt(self.formatter)?;\n\n        if self.formatter.pretty {\n            self.formatter.write_str(\",\\n\")?;\n        }\n\n        Ok(self)\n    }\n\n    /// Adds the contents of an iterator of entries to the set output.\n    pub fn entries(\n        &mut self,\n        entries: impl IntoIterator<Item = impl uDebug>,\n    ) -> Result<&mut Self, W::Error> {\n        for entry in entries {\n            self.entry(&entry)?;\n        }\n\n        Ok(self)\n    }\n\n    /// Finishes output\n    pub fn finish(&mut self) -> Result<(), W::Error> {\n        self.formatter.write_str(\"}\")\n    }\n}\n\n/// A struct to help with [`uDebug`] implementations.\n///\n/// This is useful when you wish to output a formatted struct as a part of your [`uDebug::fmt`]\n/// implementation.\n///\n/// This can be constructed by the [`Formatter::debug_struct`] method.\npub struct DebugStruct<'f, 'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    first: bool,\n    formatter: &'f mut Formatter<'w, W>,\n}\n\nimpl<W> DebugStruct<'_, '_, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    /// Adds a new field to the generated struct output.\n    pub fn field(&mut self, name: &str, value: &impl uDebug) -> Result<&mut Self, W::Error> {\n        if self.first {\n            self.first = false;\n\n            self.formatter.write_str(\" {\")?;\n\n            if self.formatter.pretty {\n                self.formatter.write_str(\"\\n\")?;\n            } else {\n                self.formatter.write_str(\" \")?;\n            }\n        } else if !self.formatter.pretty {\n            self.formatter.write_str(\", \")?;\n        }\n\n        if self.formatter.pretty {\n            self.formatter.indent()?;\n        }\n\n        self.formatter.write_str(name)?;\n        self.formatter.write_str(\": \")?;\n        value.fmt(self.formatter)?;\n\n        if self.formatter.pretty {\n            self.formatter.write_str(\",\\n\")?;\n        }\n\n        Ok(self)\n    }\n\n    /// Finishes output\n    pub fn finish(&mut self) -> Result<(), W::Error> {\n        if self.formatter.pretty {\n            self.formatter.indentation -= 1;\n        }\n\n        if !self.first {\n            if self.formatter.pretty {\n                self.formatter.indent()?;\n            } else {\n                self.formatter.write_str(\" \")?;\n            }\n\n            self.formatter.write_str(\"}\")?;\n        }\n\n        Ok(())\n    }\n}\n\n/// A struct to help with [`uDebug`] implementations.\n///\n/// This is useful when you wish to output a formatted tuple as a part of your [`uDebug::fmt`]\n/// implementation.\n///\n/// This can be constructed by the [`Formatter::debug_tuple`] method.\npub struct DebugTuple<'f, 'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    fields: u8,\n    first: bool,\n    formatter: &'f mut Formatter<'w, W>,\n    unnamed: bool,\n}\n\nimpl<W> DebugTuple<'_, '_, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    /// Adds a new field to the generated tuple struct output.\n    pub fn field(&mut self, value: &impl uDebug) -> Result<&mut Self, W::Error> {\n        self.fields += 1;\n\n        if self.first {\n            self.first = false;\n\n            self.formatter.write_str(\"(\")?;\n\n            if self.formatter.pretty {\n                self.formatter.write_str(\"\\n\")?;\n            }\n        } else if !self.formatter.pretty {\n            self.formatter.write_str(\", \")?;\n        }\n\n        if self.formatter.pretty {\n            self.formatter.indent()?;\n        }\n\n        value.fmt(self.formatter)?;\n\n        if self.formatter.pretty {\n            self.formatter.write_str(\",\\n\")?;\n        }\n\n        Ok(self)\n    }\n\n    /// Finishes output\n    pub fn finish(&mut self) -> Result<(), W::Error> {\n        if self.formatter.pretty {\n            self.formatter.indentation -= 1;\n        }\n\n        if !self.first {\n            if self.formatter.pretty {\n                self.formatter.indent()?;\n            } else if self.unnamed && self.fields == 1 {\n                // this is a one-element tuple so we need a trailing comma\n                self.formatter.write_str(\",\")?;\n            }\n\n            self.formatter.write_str(\")\")?;\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "ufmt/src/impls/array.rs",
    "content": "use crate::{uDebug, uWrite, Formatter};\n\nmacro_rules! array {\n    ($($N:expr),+) => {\n        $(\n            impl<T> uDebug for [T; $N]\n            where\n                T: uDebug,\n            {\n                fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n                    where\n                    W: uWrite + ?Sized,\n                {\n                    <[T] as uDebug>::fmt(self, f)\n                }\n            }\n        )+\n    }\n}\n\narray!(\n    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n    26, 27, 28, 29, 30, 31, 32\n);\n"
  },
  {
    "path": "ufmt/src/impls/core.rs",
    "content": "use crate::{uDebug, uDisplay, uWrite, Formatter};\n\nimpl uDebug for bool {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        if *self {\n            f.write_str(\"true\")\n        } else {\n            f.write_str(\"false\")\n        }\n    }\n}\n\nimpl uDisplay for bool {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <bool as uDebug>::fmt(self, f)\n    }\n}\n\n// FIXME this (`escape_debug`) contains a panicking branch\n// impl uDebug for char {\n//     fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n//     where\n//         W: uWrite + ?Sized,\n//     {\n//         f.write_str(\"'\")?;\n//         for c in self.escape_debug() {\n//             f.write_char(c)?\n//         }\n//         f.write_str(\"'\")\n//     }\n// }\n\nimpl uDisplay for char {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.write_char(*self)\n    }\n}\n\nimpl<T> uDebug for [T]\nwhere\n    T: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.debug_list()?.entries(self)?.finish()\n    }\n}\n\n// Below borrowed from https://github.com/japaric/ufmt/pull/25\nimpl uDebug for str {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.write_str(\"\\\"\")?;\n        let mut from = 0;\n        for (i, c) in self.char_indices() {\n            let esc = c.escape_debug();\n\n            // If char needs escaping, flush backlog so far and write, else skip\n            if esc.len() != 1 {\n                // SAFETY: `char_indices()` guarantees that `i` is always the index of utf-8 boundary of `c`.\n                // In the first iteration `from` is zero and therefore also the index of the bounardy of `c`.\n                // In the following iterations `from` either keeps its value or is set to `i + c.len_utf8()`\n                // (with last rounds `i` and `c`), which means `from` is again `i` (this round), the index\n                // of this rounds `c`. Notice that this also implies `from <= i`.\n                f.write_str(unsafe { self.get_unchecked(from..i) })?;\n                for c in esc {\n                    f.write_char(c)?;\n                }\n                from = i + c.len_utf8();\n            }\n        }\n\n        // SAFETY: As seen above, `from` is the index of an utf-8 boundary in `self`.\n        // This also means that from is in bounds of `self`: `from <= self.len()`.\n        f.write_str(unsafe { self.get_unchecked(from..) })?;\n        f.write_str(\"\\\"\")\n    }\n}\n\nimpl uDisplay for str {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.write_str(self)\n    }\n}\n\nimpl<T> uDebug for &'_ T\nwhere\n    T: uDebug + ?Sized,\n{\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <T as uDebug>::fmt(self, f)\n    }\n}\n\nimpl<T> uDisplay for &'_ T\nwhere\n    T: uDisplay + ?Sized,\n{\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <T as uDisplay>::fmt(self, f)\n    }\n}\n\nimpl<T> uDebug for &'_ mut T\nwhere\n    T: uDebug + ?Sized,\n{\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <T as uDebug>::fmt(self, f)\n    }\n}\n\nimpl<T> uDisplay for &'_ mut T\nwhere\n    T: uDisplay + ?Sized,\n{\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <T as uDisplay>::fmt(self, f)\n    }\n}\n\nimpl<T> uDebug for Option<T>\nwhere\n    T: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        match self {\n            None => f.write_str(\"None\"),\n            Some(x) => f.debug_tuple(\"Some\")?.field(x)?.finish(),\n        }\n    }\n}\n\nimpl<T, E> uDebug for Result<T, E>\nwhere\n    T: uDebug,\n    E: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        match self {\n            Err(e) => f.debug_tuple(\"Err\")?.field(e)?.finish(),\n            Ok(x) => f.debug_tuple(\"Ok\")?.field(x)?.finish(),\n        }\n    }\n}\n"
  },
  {
    "path": "ufmt/src/impls/ixx.rs",
    "content": "use core::str;\n\nuse crate::{uDebug, uDisplay, uWrite, Formatter};\n\nmacro_rules! ixx_pad {\n    ($uxx:ty, $n:expr, $w:expr, $p:expr, $buf:expr) => {{\n        let n = $n;\n        let len = $buf.len();\n        let negative = n.is_negative();\n        let mut n = if negative {\n            match n.checked_abs() {\n                Some(n) => n as $uxx,\n                None => <$uxx>::max_value() / 2 + 1,\n            }\n        } else {\n            n as $uxx\n        };\n        let mut i = $buf.len() - 1;\n        loop {\n            *$buf\n                .get_mut(i)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() }) = (n % 10) as u8 + b'0';\n            n = n / 10;\n\n            if n == 0 {\n                break;\n            } else {\n                i -= 1;\n            }\n        }\n\n        // Now fill in padding up to the prescribed width.\n        // We do not support widths shorter than the value being\n        // printed, like core::fmt::format!()\n        // Also, we currently only support ' ' and '0' padding.\n        match ($w, $p) {\n            // For now, we default to left padding for all int-like values\n            (Some(mut w), pad) => {\n                // for space padding, pad before negative sign\n                // for 0 padding, pad after negative sign\n                if negative && pad == ' ' {\n                    i -= 1;\n                    *$buf\n                        .get_mut(i)\n                        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'-';\n                } else if negative {\n                    w -= 1;\n                }\n                while i > (len - (w as usize)) {\n                    i -= 1;\n                    let byte = match pad {\n                        '0' => b'0',\n                        _ => b' ',\n                    };\n\n                    *$buf\n                        .get_mut(i)\n                        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = byte;\n                }\n            }\n\n            _ => {}\n        }\n\n        if negative && ($w.is_none() || $p != ' ') {\n            i -= 1;\n            *$buf\n                .get_mut(i)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'-';\n        }\n\n        unsafe { str::from_utf8_unchecked($buf.get(i..).unwrap_or_else(|| assume_unreachable!())) }\n    }};\n}\n\nfn isize_pad(n: isize, width: Option<u8>, pad: char, buf: &mut [u8]) -> &str {\n    ixx_pad!(usize, n, width, pad, buf)\n}\n\nimpl uDebug for i8 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        if f.hex.is_some() {\n            <u8 as uDebug>::fmt(&(*self as u8), f)\n        } else {\n            let mut buf: [u8; 18] = [0; 18];\n\n            f.write_str(isize_pad(isize::from(*self), f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for i8 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i8 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for i16 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        if f.hex.is_some() {\n            <u16 as uDebug>::fmt(&(*self as u16), f)\n        } else {\n            let mut buf: [u8; 18] = [0; 18];\n\n            f.write_str(isize_pad(isize::from(*self), f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for i16 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i16 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for i32 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        if f.hex.is_some() {\n            <u32 as uDebug>::fmt(&(*self as u32), f)\n        } else {\n            let mut buf: [u8; 21] = [0; 21];\n\n            f.write_str(isize_pad(*self as isize, f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for i32 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i32 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for i64 {\n    #[cfg(any(target_pointer_width = \"32\", target_pointer_width = \"16\"))]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        if f.hex.is_some() {\n            <u64 as uDebug>::fmt(&(*self as u64), f)\n        } else {\n            let mut buf: [u8; 30] = [0; 30];\n\n            let s = ixx_pad!(u64, *self, f.width, f.pad, buf);\n            f.write_str(s)\n        }\n    }\n\n    #[cfg(target_pointer_width = \"64\")]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        if f.hex.is_some() {\n            <u64 as uDebug>::fmt(&(*self as u64), f)\n        } else {\n            let mut buf: [u8; 30] = [0; 30];\n\n            f.write_str(isize_pad(*self as isize, f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for i64 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i64 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for i128 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        if f.hex.is_some() {\n            <u128 as uDebug>::fmt(&(*self as u128), f)\n        } else {\n            let mut buf: [u8; 50] = [0; 50];\n\n            let s = ixx_pad!(u128, *self, f.width, f.pad, buf);\n            f.write_str(s)\n        }\n    }\n}\n\nimpl uDisplay for i128 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i128 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for isize {\n    #[cfg(target_pointer_width = \"16\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i16 as uDebug>::fmt(&(*self as i16), f)\n    }\n\n    #[cfg(target_pointer_width = \"32\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i32 as uDebug>::fmt(&(*self as i32), f)\n    }\n\n    #[cfg(target_pointer_width = \"64\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i64 as uDebug>::fmt(&(*self as i64), f)\n    }\n}\n\nimpl uDisplay for isize {\n    #[cfg(target_pointer_width = \"16\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i16 as uDisplay>::fmt(&(*self as i16), f)\n    }\n\n    #[cfg(target_pointer_width = \"32\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i32 as uDisplay>::fmt(&(*self as i32), f)\n    }\n\n    #[cfg(target_pointer_width = \"64\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <i64 as uDisplay>::fmt(&(*self as i64), f)\n    }\n}\n"
  },
  {
    "path": "ufmt/src/impls/nz.rs",
    "content": "use core::num::{\n    NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU16, NonZeroU32,\n    NonZeroU64, NonZeroU8, NonZeroUsize,\n};\n\nuse crate::{uDebug, uDisplay, uWrite, Formatter};\n\nmacro_rules! nz {\n    ($($NZ:ident : $inner:ident,)*) => {\n        $(\n            impl uDebug for $NZ {\n                #[inline(always)]\n                fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n                where\n                    W: uWrite + ?Sized,\n                {\n                    <$inner as uDebug>::fmt(&self.get(), f)\n                }\n            }\n\n            impl uDisplay for $NZ {\n                #[inline(always)]\n                fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n                where\n                    W: uWrite + ?Sized,\n                {\n                    <$inner as uDisplay>::fmt(&self.get(), f)\n                }\n            }\n        )*\n    }\n}\n\nnz!(\n    NonZeroI16: i16,\n    NonZeroI32: i32,\n    NonZeroI64: i64,\n    NonZeroI8: i8,\n    NonZeroIsize: isize,\n    NonZeroU16: u16,\n    NonZeroU32: u32,\n    NonZeroU64: u64,\n    NonZeroU8: u8,\n    NonZeroUsize: usize,\n);\n"
  },
  {
    "path": "ufmt/src/impls/ptr.rs",
    "content": "use core::str;\n\nuse crate::{uDebug, uWrite, Formatter};\n\nmacro_rules! hex {\n    ($self:expr, $f:expr, $N:expr) => {{\n        let mut buf: [u8; $N] = [0; $N];\n\n        let i = hex(*$self as usize, &mut buf);\n\n        unsafe {\n            $f.write_str(str::from_utf8_unchecked(\n                buf.get(i..).unwrap_or_else(|| assume_unreachable!()),\n            ))\n        }\n    }};\n}\n\nfn hex(mut n: usize, buf: &mut [u8]) -> usize {\n    let mut i = buf.len() - 1;\n\n    loop {\n        let d = (n % 16) as u8;\n        *buf.get_mut(i)\n            .unwrap_or_else(|| unsafe { assume_unreachable!() }) =\n            if d < 10 { d + b'0' } else { (d - 10) + b'a' };\n        n = n / 16;\n\n        i -= 1;\n        if n == 0 {\n            break;\n        }\n    }\n\n    *buf.get_mut(i)\n        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'x';\n    i -= 1;\n\n    *buf.get_mut(i)\n        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'0';\n\n    i\n}\n\nimpl<T> uDebug for *const T {\n    #[cfg(target_pointer_width = \"16\")]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        hex!(self, f, 6)\n    }\n\n    #[cfg(target_pointer_width = \"32\")]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        hex!(self, f, 10)\n    }\n\n    #[cfg(target_pointer_width = \"64\")]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        hex!(self, f, 18)\n    }\n}\n\nimpl<T> uDebug for *mut T {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        (*self as *const T).fmt(f)\n    }\n}\n"
  },
  {
    "path": "ufmt/src/impls/std.rs",
    "content": "use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\n\nuse crate::{uDebug, uDisplay, uWrite, Formatter};\n\nimpl<T> uDebug for Box<T>\nwhere\n    T: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <T as uDebug>::fmt(self, f)\n    }\n}\n\nimpl<T> uDisplay for Box<T>\nwhere\n    T: uDisplay,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <T as uDisplay>::fmt(self, f)\n    }\n}\n\nimpl<K, V> uDebug for BTreeMap<K, V>\nwhere\n    K: uDebug,\n    V: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.debug_map()?.entries(self)?.finish()\n    }\n}\n\nimpl<T> uDebug for BTreeSet<T>\nwhere\n    T: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.debug_set()?.entries(self)?.finish()\n    }\n}\n\nimpl<K, V> uDebug for HashMap<K, V>\nwhere\n    K: uDebug,\n    V: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.debug_map()?.entries(self)?.finish()\n    }\n}\n\nimpl<T> uDebug for HashSet<T>\nwhere\n    T: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.debug_set()?.entries(self)?.finish()\n    }\n}\n\nimpl uDebug for String {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <str as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDisplay for String {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <str as uDisplay>::fmt(self, f)\n    }\n}\n\nimpl<T> uDebug for Vec<T>\nwhere\n    T: uDebug,\n{\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <[T] as uDebug>::fmt(self, f)\n    }\n}\n"
  },
  {
    "path": "ufmt/src/impls/tuple.rs",
    "content": "use crate::{uDebug, uWrite, Formatter};\n\nmacro_rules! tuple {\n    ($($T:ident),*; $($i:tt),*) => {\n        impl<$($T,)*> uDebug for ($($T,)*)\n        where\n            $($T: uDebug,)*\n        {\n            fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n            where\n                W: uWrite + ?Sized,\n            {\n                f.debug_tuple(\"\")?$(.field(&self.$i)?)*.finish()\n            }\n        }\n\n    }\n}\n\nimpl uDebug for () {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        f.write_str(\"()\")\n    }\n}\n\ntuple!(A; 0);\ntuple!(A, B; 0, 1);\ntuple!(A, B, C; 0, 1, 2);\ntuple!(A, B, C, D; 0, 1, 2, 3);\ntuple!(A, B, C, D, E; 0, 1, 2, 3, 4);\ntuple!(A, B, C, D, E, F; 0, 1, 2, 3, 4, 5);\ntuple!(A, B, C, D, E, F, G; 0, 1, 2, 3, 4, 5, 6);\ntuple!(A, B, C, D, E, F, G, H; 0, 1, 2, 3, 4, 5, 6, 7);\ntuple!(A, B, C, D, E, F, G, H, I; 0, 1, 2, 3, 4, 5, 6, 7, 8);\ntuple!(A, B, C, D, E, F, G, H, I, J; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);\ntuple!(A, B, C, D, E, F, G, H, I, J, K; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);\ntuple!(A, B, C, D, E, F, G, H, I, J, K, L; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);\n"
  },
  {
    "path": "ufmt/src/impls/uxx.rs",
    "content": "use core::str;\n\nuse crate::{uDebug, uDisplay, uWrite, Formatter};\n\nmacro_rules! uxx_hex_pad {\n    ($n:expr, $w:expr, $p:expr, $buf:expr, $pretty:expr, $lower:expr) => {{\n        let mut n = $n;\n        let len = $buf.len();\n        let mut i = len - 1;\n        loop {\n            *$buf\n                .get_mut(i)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() }) = {\n                let d = (n as u8) & 0xf;\n                if d < 10 {\n                    d + b'0'\n                } else {\n                    if $lower {\n                        (d - 10) + b'a'\n                    } else {\n                        (d - 10) + b'A'\n                    }\n                }\n            };\n            n = n >> 4;\n\n            if n == 0 {\n                break;\n            } else {\n                i -= 1;\n            }\n        }\n\n        // Now fill in padding up to the prescribed width.\n        // We do not support widths shorter than the value being\n        // printed, like core::fmt::format!()\n        // Also, we currently only support ' ' and '0' padding.\n        match ($w, $p) {\n            // For now, we default to left padding for all int-like values\n            (Some(mut w), pad) => {\n                // for space padding, pad before 0x. For 0 padding,\n                // pad after 0x\n                if $pretty && pad == ' ' {\n                    i -= 2;\n                    *$buf\n                        .get_mut(i + 1)\n                        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'x';\n                    *$buf\n                        .get_mut(i)\n                        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'0';\n                } else if $pretty {\n                    w -= 2;\n                }\n                while i > (len - (w as usize)) {\n                    i -= 1;\n                    let byte = match pad {\n                        '0' => b'0',\n                        _ => b' ',\n                    };\n\n                    *$buf\n                        .get_mut(i)\n                        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = byte;\n                }\n            }\n            _ => {}\n        }\n\n        if $pretty && ($w.is_none() || $p != ' ') {\n            i -= 2;\n            *$buf\n                .get_mut(i + 1)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'x';\n            *$buf\n                .get_mut(i)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() }) = b'0';\n        }\n\n        unsafe { str::from_utf8_unchecked($buf.get(i..).unwrap_or_else(|| assume_unreachable!())) }\n    }};\n}\n\nmacro_rules! uxx_pad {\n    ($n:expr, $w: expr, $p:expr, $buf:expr) => {{\n        let mut n = $n;\n        let len = $buf.len();\n        let mut i = len - 1;\n        loop {\n            *$buf\n                .get_mut(i)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() }) = (n % 10) as u8 + b'0';\n            n = n / 10;\n\n            if n == 0 {\n                break;\n            } else {\n                i -= 1;\n            }\n        }\n        // Now fill in padding up to the prescribed width.\n        // We do not support widths shorter than the value being\n        // printed, like core::fmt::format!()\n        // Also, we currently only support ' ' and '0' padding.\n        match ($w, $p) {\n            // For now, we default to left padding for all int-like values\n            (Some(w), pad) => {\n                while i > (len - (w as usize)) {\n                    i -= 1;\n                    let byte = match pad {\n                        '0' => b'0',\n                        _ => b' ',\n                    };\n\n                    *$buf\n                        .get_mut(i)\n                        .unwrap_or_else(|| unsafe { assume_unreachable!() }) = byte;\n                }\n            }\n\n            _ => {}\n        }\n\n        unsafe { str::from_utf8_unchecked($buf.get(i..).unwrap_or_else(|| assume_unreachable!())) }\n    }};\n}\n\nfn usize_pad(n: usize, width: Option<u8>, pad: char, buf: &mut [u8]) -> &str {\n    uxx_pad!(n, width, pad, buf)\n}\n\nfn usize_hex_pad(\n    n: usize,\n    width: Option<u8>,\n    pad: char,\n    buf: &mut [u8],\n    pretty: bool,\n    lower: bool,\n) -> &str {\n    uxx_hex_pad!(n, width, pad, buf, pretty, lower)\n}\n\nimpl uDebug for u8 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        let mut buf: [u8; 18] = [0; 18];\n        if let Some(lower) = f.hex {\n            f.write_str(usize_hex_pad(\n                usize::from(*self),\n                f.width,\n                f.pad,\n                &mut buf,\n                f.pretty,\n                lower,\n            ))\n        } else {\n            f.write_str(usize_pad(usize::from(*self), f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for u8 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u8 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for u16 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        let mut buf: [u8; 18] = [0; 18];\n        if let Some(lower) = f.hex {\n            f.write_str(usize_hex_pad(\n                usize::from(*self),\n                f.width,\n                f.pad,\n                &mut buf,\n                f.pretty,\n                lower,\n            ))\n        } else {\n            f.write_str(usize_pad(usize::from(*self), f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for u16 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u16 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for u32 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        let mut buf: [u8; 20] = [0; 20];\n        if let Some(lower) = f.hex {\n            f.write_str(usize_hex_pad(\n                *self as usize,\n                f.width,\n                f.pad,\n                &mut buf,\n                f.pretty,\n                lower,\n            ))\n        } else {\n            f.write_str(usize_pad(*self as usize, f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for u32 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u32 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for u64 {\n    #[cfg(any(target_pointer_width = \"32\", target_pointer_width = \"16\"))]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        let mut buf: [u8; 28] = [0; 28];\n        let s = if let Some(lower) = f.hex {\n            uxx_hex_pad!(*self, f.width, f.pad, &mut buf, f.pretty, lower)\n        } else {\n            uxx_pad!(*self, f.width, f.pad, &mut buf)\n        };\n        f.write_str(s)\n    }\n\n    #[cfg(target_pointer_width = \"64\")]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        let mut buf: [u8; 30] = [0; 30];\n        if let Some(lower) = f.hex {\n            f.write_str(usize_hex_pad(\n                *self as usize,\n                f.width,\n                f.pad,\n                &mut buf,\n                f.pretty,\n                lower,\n            ))\n        } else {\n            f.write_str(usize_pad(*self as usize, f.width, f.pad, &mut buf))\n        }\n    }\n}\n\nimpl uDisplay for u64 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u64 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for u128 {\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        let mut buf: [u8; 49] = [0; 49];\n        let s = if let Some(lower) = f.hex {\n            uxx_hex_pad!(*self, f.width, f.pad, buf, f.pretty, lower)\n        } else {\n            uxx_pad!(*self, f.width, f.pad, buf)\n        };\n        f.write_str(s)\n    }\n}\n\nimpl uDisplay for u128 {\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u128 as uDebug>::fmt(self, f)\n    }\n}\n\nimpl uDebug for usize {\n    #[cfg(target_pointer_width = \"16\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u16 as uDebug>::fmt(&(*self as u16), f)\n    }\n\n    #[cfg(target_pointer_width = \"32\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u32 as uDebug>::fmt(&(*self as u32), f)\n    }\n\n    #[cfg(target_pointer_width = \"64\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u64 as uDebug>::fmt(&(*self as u64), f)\n    }\n}\n\nimpl uDisplay for usize {\n    #[cfg(target_pointer_width = \"16\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u16 as uDisplay>::fmt(&(*self as u16), f)\n    }\n\n    #[cfg(target_pointer_width = \"32\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u32 as uDisplay>::fmt(&(*self as u32), f)\n    }\n\n    #[cfg(target_pointer_width = \"64\")]\n    #[inline(always)]\n    fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized,\n    {\n        <u64 as uDisplay>::fmt(&(*self as u64), f)\n    }\n}\n"
  },
  {
    "path": "ufmt/src/impls.rs",
    "content": "mod array;\nmod core;\nmod ixx;\nmod nz;\nmod ptr;\n#[cfg(feature = \"std\")]\nmod std;\nmod tuple;\nmod uxx;\n"
  },
  {
    "path": "ufmt/src/lib.rs",
    "content": "//! `μfmt`, a (6-40x) smaller, (2-9x) faster and panic-free alternative to `core::fmt`\n//!\n//! # Design goals\n//!\n//! From highest priority to lowest priority\n//!\n//! - Optimized for binary size and speed (rather than for compilation time)\n//! - No dynamic dispatch in generated code\n//! - No panicking branches in generated code, when optimized\n//! - No recursion where possible\n//!\n//! # Features\n//!\n//! - [`Debug`] and [`Display`]-like traits\n//! - [`core::write!`][uwrite]-like macro\n//! - A generic [`Formatter<'_, impl uWrite>`][formatter] instead of a single `core::Formatter`; the\n//!   [`uWrite`] trait has an associated error type so each writer can choose its error type. For\n//!   example, the implementation for `std::String` uses [`Infallible`] as its error type.\n//! - [`core::fmt::Formatter::debug_struct`][debug_struct]-like API\n//! - [`#[derive(uDebug)]`][derive]\n//! - Pretty formatting (`{:#?}`) for `uDebug`\n//! - Hex formatting (`{:x}`) for numbers\n//! - Pretty hex formatting (`{:#x}`) for numbers\n//! - Fixed width 0-and-space-left-padded formatting (`{:08}`, `{:8}`) for numbers\n//! - Fixed width space-right-padded formatting (`{:8}`) for `uDisplay` types\n//! - Support for padding characters other than 0 and space is not currently implemented\n//!\n//! [`Debug`]: trait.uDebug.html\n//! [`Display`]: trait.uDisplay.html\n//! [uwrite]: index.html#reexports\n//! [formatter]: struct.Formatter.html\n//! [`uWrite`]: trait.uWrite.html\n//! [`Infallible`]: https://doc.rust-lang.org/core/convert/enum.Infallible.html\n//! [debug_struct]: file:///home/japaric/rust/ufmt/target/doc/ufmt/struct.Formatter.html#method.debug_list\n//! [derive]: derive/index.html\n//!\n//! # Non-features\n//!\n//! These are out of scope\n//!\n//! - Alignment and other advanced formatting options\n//! - Formatting floating point numbers\n//!\n//! # Examples\n//!\n//! - `uwrite!` / `uwriteln!`\n//!\n//! ```ignore\n//! use ufmt::{derive::uDebug, uwrite};\n//!\n//! #[derive(uDebug)]\n//! struct Pair { x: u32, y: u32 }\n//!\n//! let mut s = String::new();\n//! let pair = Pair { x: 1, y: 2 };\n//! uwrite!(s, \"{:?}\", pair).unwrap();\n//! assert_eq!(s, \"Pair { x: 1, y: 2 }\");\n//! ```\n//!\n//! - implementing `uWrite`\n//!\n//! When implementing the `uWrite` trait you should prefer the `ufmt_write::uWrite` crate over the\n//! `ufmt::uWrite` crate for better forward compatibility.\n//!\n//! ```\n//! use core::convert::Infallible;\n//!\n//! use ufmt_write::uWrite;\n//!\n//! struct MyWriter;\n//!\n//! impl uWrite for MyWriter {\n//!     type Error = Infallible;\n//!\n//!     fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {\n//!         // ..\n//!         Ok(())\n//!     }\n//! }\n//! ```\n//!\n//! - writing a `macro_rules!` macro that uses `uwrite!` (or `uwriteln!`).\n//!\n//! Both `ufmt` macros are implemented using [`proc-macro-hack`]; care is needed to avoid running\n//! into the compiler bug [#43081](https://github.com/rust-lang/rust/issues/43081). See also\n//! [dtolnay/proc-macro-hack#46][pmh-46].\n//!\n//! [`proc-macro-hack`]: https://github.com/dtolnay/proc-macro-hack\n//! [pmh-46]: https://github.com/dtolnay/proc-macro-hack/issues/46\n//!\n//! ```\n//! // like `std::format!` it returns a `std::String` but uses `uwrite!` instead of `write!`\n//! macro_rules! uformat {\n//!     // IMPORTANT use `tt` fragments instead of `expr` fragments (i.e. `$($exprs:expr),*`)\n//!     ($($tt:tt)*) => {{\n//!         let mut s = String::new();\n//!         match ufmt::uwrite!(&mut s, $($tt)*) {\n//!             Ok(_) => Ok(s),\n//!             Err(e) => Err(e),\n//!         }\n//!     }}\n//! }\n//! ```\n//!\n//! # Benchmarks\n//!\n//! The benchmarks ran on a ARM Cortex-M3 chip (`thumbv7m-none-eabi`).\n//!\n//! The benchmarks were compiled with `nightly-2019-05-01`, `-C opt-level=3`, `lto = true`,\n//! `codegen-units = 1`.\n//!\n//! In all benchmarks `x = i32::MIN` and `y = i32::MIN` plus some obfuscation was applied to\n//! prevent const-propagation of the `*write!` arguments.\n//!\n//! The unit of time is one core clock cycle: 125 ns (8 MHz)\n//!\n//! The `.text` and `.rodata` columns indicate the delta (in bytes) when commenting out the\n//! `*write!` statement.\n//!\n//! |Code                                      |Time|%        |`.text`|%        |`.rodata`|%       |\n//! |------------------------------------------|----|---------|-------|---------|---------|--------|\n//! |`write!(\"Hello, world!\")`                 |154 |~        |1906   |~        |248      |~       |\n//! |`uwrite!(\"Hello, world!\")`                |20  |**13.0%**|34     |**1.8%** |16       |**6.5%**|\n//! |`write!(w, \"{}\", 0i32)`                   |256 |~        |1958   |~        |232      |~       |\n//! |`uwrite!(w, \"{}\", 0i32)`                  |37  |**14.5%**|288    |**14.7%**|0        |**0%**  |\n//! |`write!(w, \"{}\", x)`                      |381 |~        |\n//! |`uwrite!(w, \"{}\", x)`                     |295 |77.4%    |\n//! |`write!(w, \"{:?}\", Pair { x: 0, y: 0 })`  |996 |~        |4704   |~        |312      |~       |\n//! |`uwrite!(w, \"{:?}\", Pair { x: 0, y: 0 })` |254 |**25.5%**|752    |**16.0%**|24       |**7.7%**|\n//! |`write!(w, \"{:?}\", Pair { x, y })`        |1264|~        |\n//! |`uwrite!(w, \"{:?}\", Pair { x, y })`       |776 |61.4%    |\n//! |`write!(w, \"{:#?}\", Pair { x: 0, y: 0 })` |2853|~        |4710   |~        |348      |~       |\n//! |`uwrite!(w, \"{:#?}\", Pair { x: 0, y: 0 })`|301 |**10.6%**|754    |**16.0%**|24       |**6.9%**|\n//! |`write!(w, \"{:#?}\", Pair { x, y })`       |3693|~        |\n//! |`uwrite!(w, \"{:#?}\", Pair { x, y })`      |823 |**22.3%**|\n//!\n//!\n//! Benchmark program:\n//!\n//! ``` ignore\n//! static X: AtomicI32 = AtomicI32::new(i32::MIN); // or `0`\n//! static Y: AtomicI32 = AtomicI32::new(i32::MIN); // or `0`\n//!\n//! #[exception]\n//! fn PendSV() {\n//!    // read DWT.CYCCNT here\n//!\n//!    let x = X.load(Ordering::Relaxed);\n//!    let y = Y.load(Ordering::Relaxed);\n//!\n//!    let p = Pair { x, y };\n//!\n//!    uwrite!(&mut W, \"{:#?}\", p).ok();\n//!\n//!    // write!(&mut W, \"{:#?}\", p).ok();\n//!\n//!    asm::bkpt(); // read DWT.CYCCNT here\n//! }\n//! ```\n//!\n//! Writer used in the benchmarks:\n//!\n//! ```\n//! use core::{convert::Infallible, fmt, ptr};\n//!\n//! use ufmt::uWrite;\n//!\n//! struct W;\n//!\n//! impl uWrite for W {\n//!     type Error = Infallible;\n//!\n//!     fn write_str(&mut self, s: &str) -> Result<(), Infallible> {\n//!         s.as_bytes()\n//!             .iter()\n//!             .for_each(|b| unsafe { drop(ptr::read_volatile(b)) });\n//!\n//!         Ok(())\n//!     }\n//! }\n//!\n//! impl fmt::Write for W {\n//!     fn write_str(&mut self, s: &str) -> fmt::Result {\n//!         s.as_bytes()\n//!             .iter()\n//!             .for_each(|b| unsafe { drop(ptr::read_volatile(b)) });\n//!\n//!         Ok(())\n//!     }\n//! }\n//! ```\n//!\n//! # Minimum Supported Rust Version (MSRV)\n//!\n//! This crate is guaranteed to compile on stable Rust 1.34 and up. It *might* compile on older\n//! versions but that may change in any new patch release.\n\n// Added when we vendored ufmt into libtock-rs to avoid needing to immediately\n// make many changes.\n#![allow(clippy::all)]\n#![cfg_attr(not(feature = \"std\"), no_std)]\n#![deny(missing_docs)]\n#![deny(rust_2018_compatibility)]\n#![deny(rust_2018_idioms)]\n#![deny(warnings)]\n\n// this lets us use `uwrite!` in the test suite\n#[allow(unused_extern_crates)]\n#[cfg(test)]\nextern crate self as ufmt;\n\nuse core::str;\n\nuse proc_macro_hack::proc_macro_hack;\npub use ufmt_write::uWrite;\n\n/// Write formatted data into a buffer\n///\n/// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be\n/// formatted according to the specified format string and the result will be passed to the writer.\n/// The writer must have type `[&mut] impl uWrite` or `[&mut] ufmt::Formatter<'_, impl uWrite>`. The\n/// macro returns the associated `Error` type of the `uWrite`-r.\n///\n/// The syntax is similar to [`core::write!`] but only a handful of argument types are accepted:\n///\n/// [`core::write!`]: https://doc.rust-lang.org/core/macro.write.html\n///\n/// - `{}` - `uDisplay`\n/// - `{:?}` - `uDebug`\n/// - `{:#?}` - \"pretty\" `uDebug`\n/// - `{:x}` - lowercase hexadecimal for numbers\n/// - `{:X}` - uppercase hexadecimal for numbers\n/// - `{:8}` - space padded width specifier. left pad spaces for numbers, right pad otherwise\n/// - `{:08}` - zero padded width specifier. left pads zeroes for numbers\n///\n/// Named parameters and \"specified\" positional parameters (`{0}`) are not supported.\n///\n/// `{{` and `}}` can be used to escape braces.\n#[proc_macro_hack]\npub use ufmt_macros::uwrite;\n\n/// Write formatted data into a buffer, with a newline appended\n///\n/// See [`uwrite!`](macro.uwrite.html) for more details\n#[proc_macro_hack]\npub use ufmt_macros::uwriteln;\n\npub use crate::helpers::{DebugList, DebugMap, DebugStruct, DebugTuple};\n\n#[macro_use]\nmod macros;\n\nmod helpers;\nmod impls;\n/// Derive macros\npub mod derive {\n    pub use ufmt_macros::uDebug;\n}\n\n/// Just like `core::fmt::Debug`\n#[allow(non_camel_case_types)]\npub trait uDebug {\n    /// Formats the value using the given formatter\n    fn fmt<W>(&self, _: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized;\n}\n\n/// Just like `core::fmt::Display`\n#[allow(non_camel_case_types)]\npub trait uDisplay {\n    /// Formats the value using the given formatter\n    fn fmt<W>(&self, _: &mut Formatter<'_, W>) -> Result<(), W::Error>\n    where\n        W: uWrite + ?Sized;\n}\n\n/// Configuration for formatting\n#[allow(non_camel_case_types)]\npub struct Formatter<'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    indentation: u8,\n    pretty: bool,\n    hex: Option<bool>, // Some(true) = lowercase\n    width: Option<u8>,\n    pad: char,\n    bytes_written: usize, // used internally for width padding\n    writer: &'w mut W,\n}\n\nimpl<'w, W> Formatter<'w, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    /// Creates a formatter from the given writer\n    pub fn new(writer: &'w mut W) -> Self {\n        Self {\n            indentation: 0,\n            pretty: false,\n            hex: None,\n            width: None,\n            pad: ' ',\n            bytes_written: 0,\n            writer,\n        }\n    }\n\n    /// Execute the closure with pretty-printing enabled\n    pub fn pretty(\n        &mut self,\n        f: impl FnOnce(&mut Self) -> Result<(), W::Error>,\n    ) -> Result<(), W::Error> {\n        let pretty = self.pretty;\n        self.pretty = true;\n        f(self)?;\n        self.pretty = pretty;\n        Ok(())\n    }\n\n    /// Execute the closure with hex-printing enabled\n    pub fn hex(\n        &mut self,\n        lower: bool,\n        pretty: bool,\n        f: impl FnOnce(&mut Self) -> Result<(), W::Error>,\n    ) -> Result<(), W::Error> {\n        let old_hex = self.hex;\n        let old_pretty = self.pretty;\n        self.pretty = pretty;\n        self.hex = Some(lower);\n        f(self)?;\n        self.hex = old_hex;\n        self.pretty = old_pretty;\n        Ok(())\n    }\n\n    /// Execute the closure with specified width / pad values\n    pub fn fixed_width(\n        &mut self,\n        pretty: bool,\n        hex: Option<bool>,\n        width: Option<u8>,\n        pad: char,\n        f: impl FnOnce(&mut Self) -> Result<(), W::Error>,\n    ) -> Result<(), W::Error> {\n        self.bytes_written = 0;\n        let old_hex = self.hex;\n        let old_pretty = self.pretty;\n        let old_width = self.width;\n        let old_pad = self.pad;\n        self.pretty = pretty;\n        self.hex = hex;\n        self.width = width;\n        self.pad = pad;\n        f(self)?;\n        // The trick here is that if the internal implementation\n        // already padded to the appropriate length, we don't have\n        // to do anything -- this is the case for all numeric types.\n        // Otherwise, we only support space padding to the right of\n        // the object, so just fill that in here.\n        if let Some(w) = self.width {\n            if (w as usize) > self.bytes_written {\n                // we don't support non-space padding here\n                if self.pad == ' ' {\n                    for _i in 0..(w as usize - self.bytes_written) {\n                        self.write_str(\" \")?;\n                    }\n                }\n            }\n        }\n        self.hex = old_hex;\n        self.pretty = old_pretty;\n        self.width = old_width;\n        self.pad = old_pad;\n        Ok(())\n    }\n\n    /// Writes a character to the underlying buffer contained within this formatter.\n    pub fn write_char(&mut self, c: char) -> Result<(), W::Error> {\n        let err = self.writer.write_char(c);\n        if err.is_ok() {\n            self.bytes_written += c.len_utf8();\n        }\n        err\n    }\n\n    /// Writes a string slice to the underlying buffer contained within this formatter.\n    pub fn write_str(&mut self, s: &str) -> Result<(), W::Error> {\n        let err = self.writer.write_str(s);\n        if err.is_ok() {\n            self.bytes_written += s.len();\n        }\n        err\n    }\n\n    /// Write whitespace according to the current `self.indentation`\n    fn indent(&mut self) -> Result<(), W::Error> {\n        for _ in 0..self.indentation {\n            self.write_str(\"    \")?;\n        }\n\n        Ok(())\n    }\n}\n\n// Implementation detail of the `uwrite*!` macros\n#[doc(hidden)]\npub trait UnstableDoAsFormatter {\n    type Writer: uWrite + ?Sized;\n\n    fn do_as_formatter(\n        &mut self,\n        f: impl FnOnce(&mut Formatter<'_, Self::Writer>) -> Result<(), <Self::Writer as uWrite>::Error>,\n    ) -> Result<(), <Self::Writer as uWrite>::Error>;\n}\n\nimpl<W> UnstableDoAsFormatter for W\nwhere\n    W: uWrite + ?Sized,\n{\n    type Writer = W;\n\n    fn do_as_formatter(\n        &mut self,\n        f: impl FnOnce(&mut Formatter<'_, W>) -> Result<(), W::Error>,\n    ) -> Result<(), W::Error> {\n        f(&mut Formatter::new(self))\n    }\n}\n\nimpl<W> UnstableDoAsFormatter for Formatter<'_, W>\nwhere\n    W: uWrite + ?Sized,\n{\n    type Writer = W;\n\n    fn do_as_formatter(\n        &mut self,\n        f: impl FnOnce(&mut Formatter<'_, W>) -> Result<(), W::Error>,\n    ) -> Result<(), W::Error> {\n        f(self)\n    }\n}\n"
  },
  {
    "path": "ufmt/src/macros.rs",
    "content": "macro_rules! assume_unreachable {\n    () => {\n        if cfg!(debug_assertions) {\n            unreachable!()\n        } else {\n            core::hint::unreachable_unchecked()\n        }\n    };\n}\n"
  },
  {
    "path": "ufmt/tests/vs-std-write.rs",
    "content": "use core::convert::Infallible;\nuse std::collections::{BTreeMap, BTreeSet};\n\nuse ufmt::{derive::uDebug, uDebug, uWrite, uwrite, uwriteln, Formatter};\n\nmacro_rules! uformat {\n    ($($tt:tt)*) => {{\n        let mut s = String::new();\n        #[allow(unreachable_code)]\n        match ufmt::uwrite!(&mut s, $($tt)*) {\n            Ok(_) => Ok(s),\n            Err(e) => Err(e),\n        }\n    }};\n}\n\nmacro_rules! cmp {\n    ($($tt:tt)*) => {\n        assert_eq!(\n            uformat!($($tt)*),\n            Ok(format!($($tt)*)),\n        )\n    }\n}\n\n#[test]\nfn core() {\n    cmp!(\"{:?}\", None::<i32>);\n    cmp!(\"{:#?}\", None::<i32>);\n\n    cmp!(\"{:?}\", Some(0));\n    cmp!(\"{:#?}\", Some(0));\n\n    cmp!(\"{:?}\", Ok::<_, ()>(1));\n    cmp!(\"{:#?}\", Ok::<_, ()>(1));\n\n    cmp!(\"{:?}\", Err::<(), _>(2));\n    cmp!(\"{:#?}\", Err::<(), _>(2));\n}\n\n#[test]\nfn recursion() {\n    #[derive(uDebug, Debug)]\n    struct Node {\n        value: i32,\n        next: Option<Box<Node>>,\n    }\n\n    fn x() -> Node {\n        let tail = Node {\n            value: 0,\n            next: None,\n        };\n        Node {\n            value: 1,\n            next: Some(Box::new(tail)),\n        }\n    }\n\n    cmp!(\"{:?}\", x());\n    cmp!(\"{:#?}\", x());\n}\n\n#[test]\nfn uxx() {\n    cmp!(\"{}\", 0u8);\n    cmp!(\"{}\", 10u8);\n    cmp!(\"{}\", 100u8);\n\n    // extreme values\n    cmp!(\"{}\", u8::max_value());\n    cmp!(\"{}\", u16::max_value());\n    cmp!(\"{}\", u32::max_value());\n    cmp!(\"{}\", u64::max_value());\n    cmp!(\"{}\", u128::max_value());\n    cmp!(\"{}\", usize::max_value());\n}\n\n#[test]\nfn ixx() {\n    // sanity check\n    cmp!(\"{}\", 0i8);\n    cmp!(\"{}\", 10i8);\n    cmp!(\"{}\", 100i8);\n\n    // extreme values\n    cmp!(\"{}\", i8::min_value());\n    cmp!(\"{}\", i8::max_value());\n    cmp!(\"{}\", i16::min_value());\n    cmp!(\"{}\", i16::max_value());\n    cmp!(\"{}\", i32::min_value());\n    cmp!(\"{}\", i32::max_value());\n    cmp!(\"{}\", i64::min_value());\n    cmp!(\"{}\", i64::max_value());\n    cmp!(\"{}\", i128::min_value());\n    cmp!(\"{}\", i128::max_value());\n    cmp!(\"{}\", isize::min_value());\n    cmp!(\"{}\", isize::max_value());\n}\n\n#[test]\nfn hex() {\n    cmp!(\"{:x}\", 0i8);\n    cmp!(\"{:x}\", 10i8);\n    cmp!(\"{:x}\", 100i8);\n    cmp!(\"{:x}\", i8::min_value());\n    cmp!(\"{:x}\", i8::max_value());\n    cmp!(\"{:x}\", i16::min_value());\n    cmp!(\"{:x}\", i16::max_value());\n    cmp!(\"{:x}\", i32::min_value());\n    cmp!(\"{:x}\", i32::max_value());\n    cmp!(\"{:x}\", i64::min_value());\n    cmp!(\"{:x}\", i64::max_value());\n    cmp!(\"{:x}\", i128::min_value());\n    cmp!(\"{:x}\", i128::max_value());\n    cmp!(\"{:x}\", isize::min_value());\n    cmp!(\"{:x}\", isize::max_value());\n    cmp!(\"{:x}\", 0u8);\n    cmp!(\"{:x}\", 10u8);\n    cmp!(\"{:x}\", 100u8);\n    cmp!(\"{:x}\", u8::max_value());\n    cmp!(\"{:x}\", u16::max_value());\n    cmp!(\"{:x}\", u32::max_value());\n    cmp!(\"{:x}\", u64::max_value());\n    cmp!(\"{:x}\", u128::max_value());\n    cmp!(\"{:x}\", usize::max_value());\n}\n\n#[test]\nfn special_hex() {\n    cmp!(\"{:X}\", 0i8);\n    cmp!(\"{:X}\", 10i8);\n    cmp!(\"{:X}\", 100i8);\n    cmp!(\"{:X}\", u32::max_value());\n    cmp!(\"{:X}\", u64::max_value());\n    cmp!(\"{:#X}\", 0i8);\n    cmp!(\"{:#X}\", 10i8);\n    cmp!(\"{:#X}\", u32::max_value());\n    cmp!(\"{:#X}\", u64::max_value());\n    cmp!(\"{:#x}\", 0i8);\n    cmp!(\"{:#x}\", 10i8);\n    cmp!(\"{:#x}\", u32::max_value());\n    cmp!(\"{:#x}\", u64::max_value());\n    cmp!(\"{:#x}\", 0i8);\n    cmp!(\"{:#x}\", 10i8);\n    cmp!(\"{:#9x}\", u32::max_value());\n    cmp!(\"{:#09x}\", u64::max_value());\n    cmp!(\"{:#9X}\", u32::max_value());\n    cmp!(\"{:#09X}\", u64::max_value());\n}\n\n// Verify padding, with spaces or zeroes, up to width 10, for any\n// numeric value.\nmacro_rules! width_test {\n    ($tt:expr) => {{\n        cmp!(\"{:1}\", $tt);\n        cmp!(\"{:3}\", $tt);\n        cmp!(\"{:5}\", $tt);\n        cmp!(\"{:7}\", $tt);\n        cmp!(\"{:9}\", $tt);\n        cmp!(\"{:10}\", $tt);\n        cmp!(\"{:02}\", $tt);\n        cmp!(\"{:04}\", $tt);\n        cmp!(\"{:06}\", $tt);\n        cmp!(\"{:08}\", $tt);\n        cmp!(\"{:010}\", $tt);\n        cmp!(\"{:018}\", $tt);\n\n        cmp!(\"lead{:018}follow\", $tt);\n        cmp!(\"lead{:10}follow\", $tt);\n    }};\n}\n\n// Verify space padding for non-numeric values\nmacro_rules! width_test_non_numeric {\n    ($tt:expr) => {{\n        cmp!(\"{:1}\", $tt);\n        cmp!(\"{:3}\", $tt);\n        cmp!(\"{:5}\", $tt);\n        cmp!(\"{:7}\", $tt);\n        cmp!(\"{:9}\", $tt);\n        cmp!(\"{:10}\", $tt);\n        cmp!(\"{:18}\", $tt);\n        cmp!(\"lead{:18}follow\", $tt);\n        cmp!(\"lead{:5}follow\", $tt);\n    }};\n}\n\n#[test]\nfn width_format_numbers() {\n    width_test!(0i8);\n    width_test!(10i8);\n    width_test!(100i8);\n    width_test!(i8::min_value());\n    width_test!(i8::max_value());\n    width_test!(i16::min_value());\n    width_test!(i16::max_value());\n    width_test!(i32::min_value());\n    width_test!(i32::max_value());\n    width_test!(i64::min_value());\n    width_test!(i64::max_value());\n    width_test!(i128::min_value());\n    width_test!(i128::max_value());\n    width_test!(isize::min_value());\n    width_test!(isize::max_value());\n    width_test!(0u8);\n    width_test!(10u8);\n    width_test!(100u8);\n    width_test!(u8::max_value());\n    width_test!(u16::max_value());\n    width_test!(u32::max_value());\n    width_test!(u64::max_value());\n    width_test!(u128::max_value());\n    width_test!(usize::max_value());\n\n    width_test!(0i8);\n    width_test!(10i8);\n    width_test!(100i8);\n    width_test!(i8::min_value());\n    width_test!(i8::max_value());\n    width_test!(i16::min_value());\n    width_test!(i16::max_value());\n    width_test!(i32::min_value());\n    width_test!(i32::max_value());\n    width_test!(i64::min_value());\n    width_test!(i64::max_value());\n    width_test!(i128::min_value());\n    width_test!(i128::max_value());\n    width_test!(isize::min_value());\n    width_test!(isize::max_value());\n    width_test!(0u8);\n    width_test!(10u8);\n    width_test!(100u8);\n    width_test!(u8::max_value());\n    width_test!(u16::max_value());\n    width_test!(u32::max_value());\n    width_test!(u64::max_value());\n    width_test!(u128::max_value());\n    width_test!(usize::max_value());\n}\n\n#[test]\nfn width_non_numbers() {\n    width_test_non_numeric!(false);\n    width_test_non_numeric!(\"hi\");\n    width_test_non_numeric!('P');\n}\n\n#[test]\nfn fmt() {\n    cmp!(\"Hello, world!\");\n    cmp!(\"The answer is {}\", 42);\n}\n\n#[test]\nfn map() {\n    fn x() -> BTreeMap<i32, i32> {\n        let mut m = BTreeMap::new();\n        m.insert(1, 2);\n        m.insert(3, 4);\n        m\n    }\n\n    cmp!(\"{:?}\", BTreeMap::<(), ()>::new());\n    cmp!(\"{:?}\", x());\n\n    cmp!(\"{:#?}\", BTreeMap::<(), ()>::new());\n    cmp!(\"{:#?}\", x());\n}\n\n#[test]\nfn set() {\n    fn x() -> BTreeSet<i32> {\n        let mut m = BTreeSet::new();\n        m.insert(1);\n        m.insert(3);\n        m\n    }\n\n    cmp!(\"{:?}\", BTreeSet::<()>::new());\n    cmp!(\"{:?}\", x());\n\n    cmp!(\"{:#?}\", BTreeSet::<()>::new());\n    cmp!(\"{:#?}\", x());\n}\n\n#[test]\nfn struct_() {\n    #[derive(Debug, uDebug)]\n    struct Braces {}\n\n    #[derive(Debug, uDebug)]\n    struct Parens();\n\n    #[derive(Debug, Default, uDebug)]\n    struct I32(i32);\n\n    #[derive(Debug, Default, uDebug)]\n    struct Tuple(i32, i32);\n\n    #[derive(Debug, Default, uDebug)]\n    struct Pair {\n        x: i32,\n        y: i32,\n    }\n\n    #[derive(Debug, Default, uDebug)]\n    struct Nested {\n        first: Pair,\n        second: Pair,\n    }\n\n    cmp!(\"{:?}\", Braces {});\n    cmp!(\"{:?}\", Parens());\n    cmp!(\"{:?}\", I32::default());\n    cmp!(\"{:?}\", Tuple::default());\n    cmp!(\"{:?}\", Pair::default());\n    cmp!(\"{:?}\", Nested::default());\n\n    cmp!(\"{:#?}\", Braces {});\n    cmp!(\"{:#?}\", Parens());\n    cmp!(\"{:#?}\", I32::default());\n    cmp!(\"{:#?}\", Tuple::default());\n    cmp!(\"{:#?}\", Pair::default());\n    cmp!(\"{:#?}\", Nested::default());\n}\n\n#[test]\nfn enum_() {\n    #[derive(Debug, uDebug)]\n    enum X {\n        A,\n        B(u8, u16),\n        C { x: u8, y: u16 },\n    }\n\n    cmp!(\"{:?}\", X::A);\n    cmp!(\"{:?}\", X::B(0, 1));\n    cmp!(\"{:?}\", X::C { x: 0, y: 1 });\n\n    cmp!(\"{:#?}\", X::A);\n    cmp!(\"{:#?}\", X::B(0, 1));\n    cmp!(\"{:#?}\", X::C { x: 0, y: 1 });\n}\n\n#[test]\nfn ptr() {\n    cmp!(\"{:?}\", 1 as *const u8);\n    cmp!(\"{:?}\", 0xf as *const u8);\n    cmp!(\"{:?}\", 0xff as *const u8);\n    cmp!(\"{:?}\", 0xfff as *const u8);\n    cmp!(\"{:?}\", 0xffff as *const u8);\n    cmp!(\"{:?}\", 0xfffff as *const u8);\n    cmp!(\"{:?}\", 0xffffff as *const u8);\n    cmp!(\"{:?}\", 0xfffffff as *const u8);\n    cmp!(\"{:?}\", 0xffffffff as *const u8);\n\n    #[cfg(target_pointer_width = \"64\")]\n    cmp!(\"{:?}\", 0xfffffffff as *const u8);\n}\n\n#[test]\nfn tuples() {\n    cmp!(\"{:?}\", ());\n    cmp!(\"{:?}\", (1,));\n    cmp!(\"{:?}\", (1, 2));\n    cmp!(\"{:?}\", (1, 2, 3));\n    cmp!(\"{:?}\", (1, 2, 3, 4));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5, 6));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5, 6, 7));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5, 6, 7, 8));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5, 6, 7, 8, 9));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));\n    cmp!(\"{:?}\", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));\n\n    cmp!(\"{:#?}\", ());\n    cmp!(\"{:#?}\", (1,));\n    cmp!(\"{:#?}\", (1, 2));\n}\n\n#[test]\nfn slice() {\n    cmp!(\"{:?}\", [0; 0]);\n    cmp!(\"{:?}\", [0]);\n    cmp!(\"{:?}\", [0, 1]);\n\n    cmp!(\"{:#?}\", [0; 0]);\n    cmp!(\"{:#?}\", [0]);\n    cmp!(\"{:#?}\", [0, 1]);\n}\n\n#[test]\nfn uwriteln() {\n    let mut s = String::new();\n    uwriteln!(&mut s, \"Hello\").unwrap();\n    uwriteln!(&mut s, \"World\",).unwrap();\n    assert_eq!(s, \"Hello\\nWorld\\n\");\n}\n\n#[test]\nfn formatter_uwrite() {\n    #[derive(uDebug)]\n    struct X;\n\n    struct Y;\n\n    impl uDebug for Y {\n        fn fmt<W>(&self, f: &mut Formatter<'_, W>) -> Result<(), W::Error>\n        where\n            W: uWrite + ?Sized,\n        {\n            uwrite!(f, \"{:?}\", X)\n        }\n    }\n\n    assert_eq!(uformat!(\"{:?}\", Y).unwrap(), \"X\")\n}\n\n#[test]\nfn generic() {\n    #[derive(uDebug, Debug)]\n    struct X<T>(T);\n\n    cmp!(\"{:?}\", X(0));\n\n    #[derive(uDebug, Debug)]\n    enum Y<T> {\n        Z(T),\n    }\n\n    cmp!(\"{:?}\", Y::Z(0));\n}\n\n// compile-pass test\n#[allow(dead_code)]\nfn static_lifetime(x: &'static mut u32) {\n    fn foo(x: &'static mut u32) -> *mut u32 {\n        x as *mut u32\n    }\n\n    uwrite!(&mut String::new(), \"{:?}\", foo(x)).ok();\n}\n\n// test dynamically sized writer\n#[test]\nfn dst() {\n    #[allow(rust_2018_idioms)] // false positive?\n    struct Cursor<B>\n    where\n        B: ?Sized,\n    {\n        pos: usize,\n        buffer: B,\n    }\n\n    impl<B> Cursor<B> {\n        fn new(buffer: B) -> Self {\n            Cursor { pos: 0, buffer }\n        }\n    }\n\n    impl uWrite for Cursor<[u8]> {\n        type Error = Infallible;\n\n        fn write_str(&mut self, s: &str) -> Result<(), Infallible> {\n            let bytes = s.as_bytes();\n            let len = bytes.len();\n            let start = self.pos;\n            if let Some(buffer) = self.buffer.get_mut(start..start + len) {\n                buffer.copy_from_slice(bytes);\n                self.pos += len;\n            }\n\n            Ok(())\n        }\n    }\n\n    let mut cursor = Cursor::new([0; 256]);\n    let cursor: &mut Cursor<[u8]> = &mut cursor;\n\n    uwrite!(cursor, \"The answer is {}\", 42).ok();\n\n    let msg = b\"The answer is 42\";\n    assert_eq!(&cursor.buffer[..msg.len()], msg);\n}\n"
  },
  {
    "path": "ufmt/utils/Cargo.toml",
    "content": "[package]\nauthors = [\"Jorge Aparicio <jorge@japaric.io>\"]\ncategories = [\"embedded\", \"no-std\"]\ndescription = \"`μfmt` utilities\"\ndocumentation = \"https://docs.rs/ufmt-utils\"\nedition = \"2021\"\nkeywords = [\"Debug\", \"Display\", \"Write\", \"format\"]\nlicense = \"MIT OR Apache-2.0\"\nname = \"ufmt-utils\"\nrepository = \"https://github.com/japaric/ufmt\"\nversion = \"0.1.1\"\n\n[dependencies]\nheapless = \"0.5.0\"\nufmt-write = { version = \"0.1.0\", path = \"../write\" }\n\n[dev-dependencies]\nufmt = { version = \"0.1.0\", path = \"..\" }\n"
  },
  {
    "path": "ufmt/utils/src/lib.rs",
    "content": "//! `μfmt` utilities\n//!\n//! # Minimum Supported Rust Version (MSRV)\n//!\n//! This crate is guaranteed to compile on stable Rust 1.36 and up. It *might* compile on older\n//! versions but that may change in any new patch release.\n\n#![deny(missing_docs)]\n#![deny(rust_2018_compatibility)]\n#![deny(rust_2018_idioms)]\n#![deny(warnings)]\n#![no_std]\n\nuse core::{convert::Infallible, str, fmt};\n\npub use heapless::consts;\nuse heapless::{ArrayLength, String};\nuse ufmt_write::uWrite;\n\n\nmacro_rules! assume_unreachable {\n    () => {\n        if cfg!(debug_assertions) {\n            panic!()\n        } else {\n            core::hint::unreachable_unchecked()\n        }\n    };\n}\n\n/// A write adapter that ignores all errors\npub struct Ignore<W>\nwhere\n    W: uWrite,\n{\n    writer: W,\n}\n\nimpl<W> Ignore<W>\nwhere\n    W: uWrite,\n{\n    /// Creates a new `Ignore` adapter\n    pub fn new(writer: W) -> Self {\n        Self { writer }\n    }\n\n    /// Destroys the adapter and returns the underlying writer\n    pub fn free(self) -> W {\n        self.writer\n    }\n}\n\nimpl<W> uWrite for Ignore<W>\nwhere\n    W: uWrite,\n{\n    type Error = Infallible;\n\n    fn write_str(&mut self, s: &str) -> Result<(), Infallible> {\n        let _ = self.writer.write_str(s);\n        Ok(())\n    }\n}\n\n/// A write adapter that buffers writes and automatically flushes on newlines\npub struct LineBuffered<W, N>\nwhere\n    N: ArrayLength<u8>,\n    W: uWrite,\n{\n    buffer: String<N>,\n    writer: W,\n}\n\nimpl<W, N> LineBuffered<W, N>\nwhere\n    N: ArrayLength<u8>,\n    W: uWrite,\n{\n    /// Creates a new `LineBuffered` adapter\n    pub fn new(writer: W) -> Self {\n        Self {\n            buffer: String::new(),\n            writer,\n        }\n    }\n\n    /// Flushes the contents of the buffer\n    pub fn flush(&mut self) -> Result<(), W::Error> {\n        let ret = self.writer.write_str(&self.buffer);\n        self.buffer.clear();\n        ret\n    }\n\n    /// Destroys the adapter and returns the underlying writer\n    pub fn free(self) -> W {\n        self.writer\n    }\n\n    fn push_str(&mut self, s: &str) -> Result<(), W::Error> {\n        let len = s.as_bytes().len();\n        if self.buffer.len() + len > self.buffer.capacity() {\n            self.flush()?;\n        }\n\n        if len > self.buffer.capacity() {\n            self.writer.write_str(s)?;\n        } else {\n            self.buffer\n                .push_str(s)\n                .unwrap_or_else(|_| unsafe { assume_unreachable!() })\n        }\n\n        Ok(())\n    }\n}\n\nimpl<W, N> uWrite for LineBuffered<W, N>\nwhere\n    N: ArrayLength<u8>,\n    W: uWrite,\n{\n    type Error = W::Error;\n\n    fn write_str(&mut self, mut s: &str) -> Result<(), W::Error> {\n        while let Some(pos) = s.as_bytes().iter().position(|b| *b == b'\\n') {\n            let line = s\n                .get(..pos + 1)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() });\n\n            self.push_str(line)?;\n            self.flush()?;\n\n            s = s\n                .get(pos + 1..)\n                .unwrap_or_else(|| unsafe { assume_unreachable!() });\n        }\n\n        self.push_str(s)\n    }\n}\n\n\n/// An adapter struct allowing to use `ufmt` on types which implement `core::fmt::Write`\n///\n/// For example:\n///\n/// ```\n/// use ufmt::uwrite;\n/// use ufmt_write::uWrite;\n/// use ufmt_utils::WriteAdapter;\n///\n/// let fancy_number: u8 = 42;\n///\n/// let mut s = String::new();\n/// uwrite!(WriteAdapter(&mut s), \"{:?}\", fancy_number);\n/// ```\npub struct WriteAdapter<W>(pub W) where W: fmt::Write;\n\nimpl<W> uWrite for WriteAdapter<W> where W: fmt::Write {\n    type Error = fmt::Error;\n\n    fn write_char(&mut self, c: char) -> Result<(), Self::Error> {\n        self.0.write_char(c)\n    }\n\n    fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {\n        self.0.write_str(s)\n    }\n}\n"
  },
  {
    "path": "ufmt/write/Cargo.toml",
    "content": "[package]\nauthors = [\"Jorge Aparicio <jorge@japaric.io>\"]\ncategories = [\"embedded\", \"no-std\"]\ndescription = \"`μfmt`'s `uWrite` trait\"\nedition = \"2021\"\nkeywords = [\"Debug\", \"Display\", \"Write\", \"format\"]\nlicense = \"MIT OR Apache-2.0\"\nname = \"ufmt-write\"\nrepository = \"https://github.com/japaric/ufmt\"\nversion = \"0.1.0\"\n\n# NOTE do NOT add an `alloc` feature before the alloc crate can be used in\n# no-std BINARIES\n[features]\n# NOTE do NOT turn `std` into a default feature; this is a no-std first crate\nstd = []\n"
  },
  {
    "path": "ufmt/write/src/lib.rs",
    "content": "//! `μfmt`'s `uWrite` trait\n\n#![cfg_attr(not(feature = \"std\"), no_std)]\n#![deny(missing_docs)]\n#![deny(rust_2018_compatibility)]\n#![deny(rust_2018_idioms)]\n#![deny(warnings)]\n\n#[cfg(feature = \"std\")]\nuse core::convert::Infallible;\n\n/// A collection of methods that are required / used to format a message into a stream.\n#[allow(non_camel_case_types)]\npub trait uWrite {\n    /// The error associated to this writer\n    type Error;\n\n    /// Writes a string slice into this writer, returning whether the write succeeded.\n    ///\n    /// This method can only succeed if the entire string slice was successfully written, and this\n    /// method will not return until all data has been written or an error occurs.\n    fn write_str(&mut self, s: &str) -> Result<(), Self::Error>;\n\n    /// Writes a [`char`] into this writer, returning whether the write succeeded.\n    ///\n    /// A single [`char`] may be encoded as more than one byte. This method can only succeed if the\n    /// entire byte sequence was successfully written, and this method will not return until all\n    /// data has been written or an error occurs.\n    fn write_char(&mut self, c: char) -> Result<(), Self::Error> {\n        let mut buf: [u8; 4] = [0; 4];\n        self.write_str(c.encode_utf8(&mut buf))\n    }\n}\n\n#[cfg(feature = \"std\")]\nimpl uWrite for String {\n    type Error = Infallible;\n\n    fn write_str(&mut self, s: &str) -> Result<(), Infallible> {\n        self.push_str(s);\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "unittest/Cargo.toml",
    "content": "[package]\nauthors = [\"Tock Project Developers <tock-dev@googlegroups.com>\"]\ndescription = \"\"\"libtock-rs unit test support. Provides a fake Tock kernel as \\\n                 well as the test_component! macro.\"\"\"\nedition = \"2021\"\nlicense = \"Apache-2.0 OR MIT\"\nname = \"libtock_unittest\"\nrepository = \"https://www.github.com/tock/libtock-rs\"\nrust-version.workspace = true\nversion = \"0.1.0\"\n\n[dependencies]\nlibtock_platform = { path = \"../platform\" }\nthiserror = \"1.0.44\"\n"
  },
  {
    "path": "unittest/src/allow_db.rs",
    "content": "use core::num::NonZeroUsize;\nuse libtock_platform::Register;\n\n/// `AllowDb` stores the currently-active Allow buffers, and is responsible for\n/// preventing overlapping Allow buffers.\n///\n/// Functionally, it receives raw register data from the Allow system calls\n/// implementations, verifies the new buffer does not overlap any active buffer,\n/// and converts the register values into usable reference types (such as\n/// `&'static mut [u8]`). When a buffer reference is returned, it removes it\n/// from its database and returns the raw register values.\n// TRD 104 (Tock's system call ABI) says that allow buffers only overlap if they\n// have a memory address in common, so zero-sized buffers cannot overlap.\n//\n// Read-Write Allow and Read-Only Allow are invoked through\n// RawSyscalls::syscall4, which is unsafe, and requires its caller to pass\n// arguments that are valid for the system call. Those requirements require that\n// either the length field is zero, or the address and length field represent a\n// valid slice. Several of the steps in this file require that property.\n//\n// Therefore AllowDb does not need to check for overlaps with zero-sized\n// buffers.\n#[derive(Default)]\npub struct AllowDb {\n    // List of all active buffers, excluding zero-sized buffers. Contains both\n    // read-only buffers and read-write buffers.\n    // Key: address of the buffer.\n    // Value: length of the buffer.\n    // Invariant: These buffers never overlap, and represent valid slices\n    // (although they can't be converted to slices because fake drivers may have\n    // a &mut [u8] pointing at the buffer).\n    buffers: std::collections::BTreeMap<*mut u8, NonZeroUsize>,\n}\n\nimpl AllowDb {\n    // Adds a new buffer, or returns an error if it overlaps with any existing\n    // buffers. Requires that address and len represent a valid slice.\n    unsafe fn insert_raw(\n        &mut self,\n        address: *mut u8,\n        len: NonZeroUsize,\n    ) -> Result<(), OverlapError> {\n        // The new buffer spans the address range [address, address + len - 1],\n        // so the highest-address buffer it overlaps with starts at\n        // address + len - 1. It can overlap with a buffer that starts with any\n        // address less than that (if that buffer's length is large enough), so\n        // we don't give a lower bound for the range.\n        //\n        // If the last buffer in this range does NOT overlap the new buffer,\n        // then that buffer's memory range is strictly less than the new buffer.\n        // Because buffers in self.buffers cannot overlap, all of the buffers in\n        // the range would need to be strictly less than the new buffer.\n        // Therefore we only need to check for overlap with the last buffer in\n        // this range.\n        //\n        // range_end is one past the end of the range to check.\n        let range_end = unsafe {\n            // Safety: The function's preconditions require that address and len\n            // represent a valid slice, which guarantees that this sum does not\n            // oveflow.\n            address.add(len.get())\n        };\n        if let Some(existing_buffer) = self.buffers.range(..range_end).next_back() {\n            let (&existing_address, &existing_len) = existing_buffer;\n            // Check if existing_buffer overlaps with the new buffer. Note that\n            // existing_address.add(existing_len) generates a pointer one past\n            // the end of the existing buffer, which is why the inequality is\n            // strict.\n            // Safety: self.buffers has an invariant that its values represent\n            // slices, so this sum cannot overflow.\n            if unsafe { existing_address.add(existing_len.get()) } > address {\n                return Err(OverlapError);\n            }\n        }\n        self.buffers.insert(address, len);\n        Ok(())\n    }\n\n    /// Adds a read-only buffer to the database, and returns it as a\n    /// `RoAllowBuffer`.\n    ///\n    /// # Safety\n    /// `address` and `len` must be valid as specified in TRD 104: either `len`\n    /// is 0 or `address` and `len` represent a valid slice.\n    pub unsafe fn insert_ro_buffer(\n        &mut self,\n        address: Register,\n        len: Register,\n    ) -> Result<RoAllowBuffer, OverlapError> {\n        let len: usize = len.into();\n        if let Some(nonzero_len) = NonZeroUsize::new(len) {\n            // The buffer is not zero-sized. Add it to the database (checking it\n            // does not overlap an existing buffer).\n            // Safety: `len` is nonzero, so by this function's precondition\n            // `address` and `len` represent a valid slice.\n            unsafe { self.insert_raw(address.into(), nonzero_len) }?;\n        }\n        Ok(RoAllowBuffer {\n            address: address.into(),\n            len,\n        })\n    }\n\n    /// Adds a read-write buffer to the database, and returns it as a\n    /// `RwAllowBuffer`.\n    ///\n    /// # Safety\n    /// `address` and `len` must be valid as specified in TRD 104: either `len`\n    /// is 0 or `address` and `len` represent a valid slice.\n    pub unsafe fn insert_rw_buffer(\n        &mut self,\n        address: Register,\n        len: Register,\n    ) -> Result<RwAllowBuffer, OverlapError> {\n        let address: *mut u8 = address.into();\n        let len: usize = len.into();\n        if let Some(nonzero_len) = NonZeroUsize::new(len) {\n            // The buffer is not zero-sized. Add it to the database (checking it\n            // does not overlap an existing buffer).\n            // Safety: `len` is nonzero, so by this function's precondition\n            // `address` and `len` represent a valid slice.\n            unsafe { self.insert_raw(address, nonzero_len) }?;\n        }\n        Ok(RwAllowBuffer { address, len })\n    }\n\n    /// Removes a read-only buffer from the database and returns its raw\n    /// register values.\n    ///\n    /// The returned value is the tuple (address, len) passed into the\n    /// insert_ro_buffer call that created the RoAllowBuffer.\n    pub fn remove_ro_buffer(&mut self, buffer: RoAllowBuffer) -> (Register, Register) {\n        self.buffers.remove(&(buffer.address as *mut u8));\n        (buffer.address.into(), buffer.len.into())\n    }\n\n    /// Removes a read-write buffer from the database and returns its raw\n    /// register values.\n    ///\n    /// The returned value is the tuple (address, len) passed into the\n    /// insert_rw_buffer call that created the RwAllowBuffer.\n    pub fn remove_rw_buffer(&mut self, buffer: RwAllowBuffer) -> (Register, Register) {\n        self.buffers.remove(&buffer.address);\n        (buffer.address.into(), buffer.len.into())\n    }\n}\n\n#[derive(Debug, Eq, PartialEq, thiserror::Error)]\n#[error(\"allow buffers overlap\")]\npub struct OverlapError;\n\n/// A read-only reference to a buffer that has been shared via the Allow system\n/// call. This reference is non-Copy, so `AllowDb` can determine when all\n/// references to the buffer have been destroyed.\n#[derive(Debug)]\npub struct RoAllowBuffer {\n    // Safety invariant: Either length is 0, or address and length can be\n    // soundly converted to a &'static [u8]. Note: that means that no &mut [u8]\n    // references may overlap the slice described by address and len.\n    address: *const u8,\n    len: usize,\n}\n\nimpl Default for RoAllowBuffer {\n    fn default() -> RoAllowBuffer {\n        RoAllowBuffer {\n            address: core::ptr::null(),\n            len: 0,\n        }\n    }\n}\n\n// Allows access to the pointed-to-buffer. The returned reference has the same\n// lifetime as the &self reference, so the caller can't keep the reference for\n// longer than it has access to the RoAllowBuffer.\nimpl std::ops::Deref for RoAllowBuffer {\n    type Target = [u8];\n    fn deref(&self) -> &[u8] {\n        match self.len {\n            0 => &[],\n            // Safety: Because length is nonzero, the safety invariant on\n            // address and len says this conversion is sound.\n            _ => unsafe { core::slice::from_raw_parts(self.address, self.len) },\n        }\n    }\n}\n\n/// A read-write reference to a buffer that has been shared via the Allow system\n/// call. This reference is non-Copy, so `AllowDb` can determine when all\n/// references to the buffer have been destroyed.\n#[derive(Debug)]\npub struct RwAllowBuffer {\n    // Safety invariant: Either length is 0, or address and length can be\n    // soundly converted to a &'static mut [u8]. Note: that means that no\n    // references may overlap the slice described by address and len.\n    address: *mut u8,\n    len: usize,\n}\n\nimpl Default for RwAllowBuffer {\n    fn default() -> RwAllowBuffer {\n        RwAllowBuffer {\n            address: core::ptr::null_mut(),\n            len: 0,\n        }\n    }\n}\n\n// Allows access to the pointed-to-buffer. The returned reference has the same\n// lifetime as the &self reference, so the caller can't keep the reference for\n// longer than it has access to the RwAllowBuffer.\nimpl std::ops::Deref for RwAllowBuffer {\n    type Target = [u8];\n    fn deref(&self) -> &[u8] {\n        match self.len {\n            0 => &[],\n            // Safety: Because length is nonzero, the safety invariant on\n            // address and len says this conversion is sound.\n            _ => unsafe { core::slice::from_raw_parts(self.address, self.len) },\n        }\n    }\n}\n\n// Same purpose as the Deref implementation, but for mut references.\nimpl std::ops::DerefMut for RwAllowBuffer {\n    fn deref_mut(&mut self) -> &mut [u8] {\n        match self.len {\n            0 => &mut [],\n            // Safety: Because length is nonzero, the safety invariant on\n            // address and len says this conversion is sound.\n            _ => unsafe { core::slice::from_raw_parts_mut(self.address, self.len) },\n        }\n    }\n}\n"
  },
  {
    "path": "unittest/src/allow_db_test.rs",
    "content": "//! Unit test cases for functionality in allow_db.\n\nuse crate::allow_db::*;\nuse core::cell::Cell;\n\n// Utility to call insert_ro_buffer with a slice.\n// Safety: insert_ro_slice does not prevent RoAllowBuffer from outliving slice.\n// Instead, the caller must make sure its use patterns don't cause invalid\n// accesses.\nunsafe fn insert_ro_slice(\n    db: &mut AllowDb,\n    slice: &[Cell<u8>],\n) -> Result<RoAllowBuffer, OverlapError> {\n    // Safety: The address and len arguments are derived directly from a slice,\n    // and therefore satisfy insert_ro_buffer's precondition.\n    unsafe { db.insert_ro_buffer(slice.as_ptr().into(), slice.len().into()) }\n}\n\n// Utility to call insert_rw_buffer with a slice.\n// Safety: insert_ro_slice does not prevent RoAllowBuffer from outliving slice.\n// Instead, the caller must make sure its use patterns don't cause invalid\n// accesses.\nunsafe fn insert_rw_slice(\n    db: &mut AllowDb,\n    slice: &[Cell<u8>],\n) -> Result<RwAllowBuffer, OverlapError> {\n    // Safety: The address and len arguments are derived directly frwm a slice,\n    // and therefore satisfy insert_rw_buffer's precondition.\n    unsafe { db.insert_rw_buffer(slice.as_ptr().into(), slice.len().into()) }\n}\n\n// Utility to return a RoAllowBuffer and verify the returned register values\n// match the provided slice.\nfn remove_ro_check(db: &mut AllowDb, buffer: RoAllowBuffer, slice: &[Cell<u8>]) {\n    let (address, len) = db.remove_ro_buffer(buffer);\n    let address: *const u8 = address.into();\n    assert_eq!(address, slice.as_ptr() as *const u8);\n    let len: usize = len.into();\n    assert_eq!(len, slice.len());\n}\n\n// Utility to return a RwAllowBuffer and verify the returned register values\n// match the prwvided slice.\nfn remove_rw_check(db: &mut AllowDb, buffer: RwAllowBuffer, slice: &[Cell<u8>]) {\n    let (address, len) = db.remove_rw_buffer(buffer);\n    let address: *mut u8 = address.into();\n    assert_eq!(address, slice.as_ptr() as *mut u8);\n    let len: usize = len.into();\n    assert_eq!(len, slice.len());\n}\n\n#[test]\nfn allow_db() {\n    let mut db: AllowDb = Default::default();\n    let fake_memory: &mut [u8] = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];\n    let fake_memory = Cell::from_mut(fake_memory).as_slice_of_cells();\n    // Safety: Big unsafe block because insert_ro_slice and insert_rw_slice do\n    // not protect lifetimes. We have to return all slices before they become\n    // invalid, which happens after this blocks ends (when we check\n    // fake_memory's value).\n    unsafe {\n        let ro_buffer_2_5 = insert_ro_slice(&mut db, &fake_memory[2..=5]).unwrap();\n        // A zero-sized buffer should not alias.\n        let ro_buffer_3_empty = insert_ro_slice(&mut db, &fake_memory[3..3]).unwrap();\n        let rw_buffer_3_empty = insert_rw_slice(&mut db, &fake_memory[3..3]).unwrap();\n        // Generate an overlapping allow, which should return an error.\n        insert_rw_slice(&mut db, &fake_memory[4..=7]).unwrap_err();\n        // Generate a variety of overlaps: overlapping just the first byte, the last\n        // byte, a larger range, a smaller range, and an identical range.\n        insert_rw_slice(&mut db, &fake_memory[0..=2]).unwrap_err();\n        insert_rw_slice(&mut db, &fake_memory[5..=10]).unwrap_err();\n        insert_ro_slice(&mut db, &fake_memory[1..=7]).unwrap_err();\n        insert_ro_slice(&mut db, &fake_memory[3..=4]).unwrap_err();\n        insert_ro_slice(&mut db, &fake_memory[2..=5]).unwrap_err();\n        // Add a second buffer, and make sure we can still add a buffer in the\n        // middle.\n        let mut rw_buffer_8_12 = insert_rw_slice(&mut db, &fake_memory[8..=12]).unwrap();\n        let ro_buffer_6_7 = insert_ro_slice(&mut db, &fake_memory[6..=7]).unwrap();\n\n        // Check the Deref implementations on the read-only buffers. For the\n        // nonempty read-write buffers, we mutate the buffers as well.\n        assert_eq!(*ro_buffer_2_5, [2, 3, 4, 5]);\n        assert_eq!(*ro_buffer_3_empty, []);\n        assert_eq!(*rw_buffer_3_empty, []);\n        assert_eq!(*rw_buffer_8_12, [8, 9, 10, 11, 12]);\n        rw_buffer_8_12.copy_from_slice(&[20, 21, 22, 23, 24]);\n        assert_eq!(*ro_buffer_6_7, [6, 7]);\n\n        // Remove a buffer, and check it can be re-added.\n        remove_ro_check(&mut db, ro_buffer_6_7, &fake_memory[6..=7]);\n        let rw_buffer_6_7 = insert_rw_slice(&mut db, &fake_memory[6..=7]).unwrap();\n\n        // Clean up all the buffers.\n        remove_ro_check(&mut db, ro_buffer_2_5, &fake_memory[2..=5]);\n        remove_ro_check(&mut db, ro_buffer_3_empty, &fake_memory[3..3]);\n        remove_rw_check(&mut db, rw_buffer_3_empty, &fake_memory[3..3]);\n        remove_rw_check(&mut db, rw_buffer_8_12, &fake_memory[8..=12]);\n        remove_rw_check(&mut db, rw_buffer_6_7, &fake_memory[6..=7]);\n    }\n\n    // Verify the values were correctly written into fake_memory.\n    let expected: &mut [u8] = &mut [0, 1, 2, 3, 4, 5, 6, 7, 20, 21, 22, 23, 24, 13, 14, 15];\n    assert_eq!(fake_memory, Cell::from_mut(expected).as_slice_of_cells());\n}\n"
  },
  {
    "path": "unittest/src/command_return.rs",
    "content": "//! Safe constructors for `libtock_platform::CommandReturn` variants.\n\nuse libtock_platform::{return_variant, CommandReturn, ErrorCode};\n\npub fn failure(error_code: ErrorCode) -> CommandReturn {\n    // Safety: return_variant is a failure, so r1 must be a valid ErrorCode,\n    // which is enforced by error_code's type.\n    unsafe { CommandReturn::new(return_variant::FAILURE, error_code as u32, 0, 0) }\n}\n\npub fn failure_u32(error_code: ErrorCode, value: u32) -> CommandReturn {\n    // Safety: return_variant is a failure, so r1 must be a valid ErrorCode,\n    // which is enforced by error_code's type.\n    unsafe { CommandReturn::new(return_variant::FAILURE_U32, error_code as u32, value, 0) }\n}\n\npub fn failure_2_u32(error_code: ErrorCode, value0: u32, value1: u32) -> CommandReturn {\n    unsafe {\n        // Safety: return_variant is a failure, so r1 must be a valid ErrorCode,\n        // which is enforced by error_code's type.\n        CommandReturn::new(\n            return_variant::FAILURE_2_U32,\n            error_code as u32,\n            value0,\n            value1,\n        )\n    }\n}\n\npub fn failure_u64(error_code: ErrorCode, value: u64) -> CommandReturn {\n    unsafe {\n        // Safety: return_variant is a failure, so r1 must be a valid ErrorCode,\n        // which is enforced by error_code's type.\n        CommandReturn::new(\n            return_variant::FAILURE_U64,\n            error_code as u32,\n            value as u32,\n            (value >> 32) as u32,\n        )\n    }\n}\n\npub fn success() -> CommandReturn {\n    // Safety: return_variant is a success so there are no other invariants to\n    // maintain.\n    unsafe { CommandReturn::new(return_variant::SUCCESS, 0, 0, 0) }\n}\n\npub fn success_u32(value: u32) -> CommandReturn {\n    // Safety: return_variant is a success so there are no other invariants to\n    // maintain.\n    unsafe { CommandReturn::new(return_variant::SUCCESS_U32, value, 0, 0) }\n}\n\npub fn success_2_u32(value0: u32, value1: u32) -> CommandReturn {\n    // Safety: return_variant is a success so there are no other invariants to\n    // maintain.\n    unsafe { CommandReturn::new(return_variant::SUCCESS_2_U32, value0, value1, 0) }\n}\n\npub fn success_u64(value: u64) -> CommandReturn {\n    unsafe {\n        // Safety: return_variant is a success so there are no other invariants\n        // to maintain.\n        CommandReturn::new(\n            return_variant::SUCCESS_U64,\n            value as u32,\n            (value >> 32) as u32,\n            0,\n        )\n    }\n}\n\npub fn success_3_u32(value0: u32, value1: u32, value2: u32) -> CommandReturn {\n    // Safety: return_variant is a success so there are no other invariants to\n    // maintain.\n    unsafe { CommandReturn::new(return_variant::SUCCESS_3_U32, value0, value1, value2) }\n}\n\npub fn success_u32_u64(value0: u32, value1: u64) -> CommandReturn {\n    unsafe {\n        // Safety: return_variant is a success so there are no other invariants\n        // to maintain.\n        CommandReturn::new(\n            return_variant::SUCCESS_U32_U64,\n            value0,\n            value1 as u32,\n            (value1 >> 32) as u32,\n        )\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn failure_test() {\n        assert_eq!(\n            failure(ErrorCode::Fail).get_failure(),\n            Some(ErrorCode::Fail)\n        );\n    }\n\n    #[test]\n    fn failure_u32_test() {\n        assert_eq!(\n            failure_u32(ErrorCode::Busy, 42).get_failure_u32(),\n            Some((ErrorCode::Busy, 42))\n        );\n    }\n\n    #[test]\n    fn failure_2_u32_test() {\n        assert_eq!(\n            failure_2_u32(ErrorCode::Off, 31, 27).get_failure_2_u32(),\n            Some((ErrorCode::Off, 31, 27))\n        );\n    }\n\n    #[test]\n    fn failure_u64_test() {\n        assert_eq!(\n            failure_u64(ErrorCode::Size, 0x1111_2222_3333_4444).get_failure_u64(),\n            Some((ErrorCode::Size, 0x1111_2222_3333_4444))\n        );\n    }\n\n    #[test]\n    fn success_test() {\n        assert!(success().is_success());\n    }\n\n    #[test]\n    fn success_u32_test() {\n        assert_eq!(success_u32(1618).get_success_u32(), Some(1618));\n    }\n\n    #[test]\n    fn success_2_u32_test() {\n        assert_eq!(success_2_u32(1, 2).get_success_2_u32(), Some((1, 2)));\n    }\n\n    #[test]\n    fn success_u64_test() {\n        assert_eq!(\n            success_u64(0x1111_2222_3333_4444).get_success_u64(),\n            Some(0x1111_2222_3333_4444)\n        );\n    }\n\n    #[test]\n    fn success_3_u32_test() {\n        assert_eq!(success_3_u32(3, 5, 8).get_success_3_u32(), Some((3, 5, 8)));\n    }\n\n    #[test]\n    fn success_u32_u64_test() {\n        assert_eq!(\n            success_u32_u64(13, 0x1111_2222_3333_4444).get_success_u32_u64(),\n            Some((13, 0x1111_2222_3333_4444))\n        );\n    }\n}\n"
  },
  {
    "path": "unittest/src/driver_info.rs",
    "content": "/// Information that a `fake::SyscallDriver` provides to the `fake::Kernel`\n/// during registration. This may be expanded over time as new features are\n/// added to Tock.\n#[non_exhaustive]\npub struct DriverInfo {\n    // All constructors of DriverInfo require the driver to specify\n    // `driver_num`.\n    pub(crate) driver_num: u32,\n\n    /// The maximum number of subscriptions to support. The maximum subscribe\n    /// number supported will be one less than `upcall_count`.\n    pub upcall_count: u32,\n}\n\nimpl DriverInfo {\n    /// Creates a new `DriverInfo` with the given driver number. `upcall_count`\n    /// will be initialized to zero.\n    pub fn new(driver_num: u32) -> Self {\n        Self {\n            driver_num,\n            upcall_count: 0,\n        }\n    }\n\n    /// Sets `upcall_count` and returns `self`. Used similar to a builder.\n    ///\n    /// # Example\n    /// ```\n    /// use libtock_platform::CommandReturn;\n    /// use libtock_unittest::{DriverInfo, fake};\n    /// struct FooDriver;\n    /// impl fake::SyscallDriver for FooDriver {\n    ///     fn info(&self) -> DriverInfo {\n    ///         DriverInfo::new(3).upcall_count(2)\n    ///     }\n    ///     fn command(&self, _: u32, _: u32, _: u32) -> CommandReturn {\n    ///         unimplemented!(\"Example code\");\n    ///     }\n    /// }\n    /// ```\n    pub fn upcall_count(mut self, upcall_count: u32) -> Self {\n        self.upcall_count = upcall_count;\n        self\n    }\n}\n"
  },
  {
    "path": "unittest/src/exit_test/mod.rs",
    "content": "//! Tools for testing code that calls the Exit system call.\n//!\n//! This module is not compatible with Miri because it requires the ability to\n//! spawn external processes, which Miri does not support by default. Therefore\n//! it is only available for non-Miri tests.\n\n#[cfg(test)]\nmod tests;\n\nuse std::panic::{catch_unwind, Location, UnwindSafe};\n\n/// Utility for testing code that is expected to call the Exit system call. It\n/// is used as follows (inside a unit test case):\n///\n/// ```\n/// // Note: exit_test is not available in Miri\n/// #[cfg(miri)]\n/// fn main() {}\n///\n/// #[cfg(not(miri))]\n/// fn main() {\n///     use libtock_platform::Syscalls;\n///     let _kernel = libtock_unittest::fake::Kernel::new();\n///     let exit = libtock_unittest::exit_test(\"tests::foo\", || {\n///         libtock_unittest::fake::Syscalls::exit_terminate(0);\n///     });\n///     assert_eq!(exit, libtock_unittest::ExitCall::Terminate(0));\n/// }\n/// ```\n///\n/// `exit_test` will panic (to fail the test case) if the code does not call\n/// Exit, or if the parameters to exit do not match `expected_exit`.\n///\n/// `test_name` must match the name of the test case, as is used in Rust's test\n/// framework's filter syntax.\n///\n/// `exit_test` is a hack, and the user should understand how it works to\n/// understand its limitations. When the above test case is executed, the\n/// following happens:\n///\n/// 1. The first test process (the one started by the user, e.g. through\n///    `cargo test`) executes the `foo()` test case, which calls `exit_test`.\n///    We'll call this process A, as it was the first test process to start.\n/// 2. `exit_test` spawns a second process, B, by invoking the same test binary\n///    as process A. When it does, it passes a filter to process B telling it\n///    to only invoke `foo()` (this is the purpose of the `test_name` argument).\n///    It also sets an environment variable telling process B that `exit_test`\n///    launched it.\n/// 3. Process B runs the `foo()` test case, which invokes `exit_test` a second\n///    time.\n/// 4. `exit_test` in process B uses the environment variable to detect that it\n///    is the subprocess version, and it runs closure `fcn`. If `fcn` does not\n///    call Exit, it panics. `exit_test` will not return from process B.\n/// 5. `exit_test` in process A waits until process B terminates.\n/// 6. `exit_test` in process A reads the output of process B to determine\n///    whether Exit was called, and if so what arguments were called.\n/// 7. `exit_test` in process A returns a value indicating what happened in\n///    process B, which `foo()` can make assertions on.\n#[track_caller]\npub fn exit_test<F: FnOnce() + UnwindSafe>(test_name: &str, fcn: F) -> ExitCall {\n    if let Some(signal_var) = std::env::var_os(SIGNAL_VAR) {\n        // We are process B, run the test function.\n        run_test(signal_var, fcn)\n    } else {\n        // We are process A, spawn process B.\n        spawn_test(test_name)\n    }\n}\n\n/// Indicates what type of Exit call was performed, and what completion code was\n/// provided.\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub enum ExitCall {\n    Terminate(u32),\n    Restart(u32),\n}\n\n// -----------------------------------------------------------------------------\n// Public API above, implementation details below.\n// -----------------------------------------------------------------------------\n\n// Prints a message telling exit_test the Exit system call was called.\npub(crate) fn signal_exit(exit_call: ExitCall) {\n    signal_message(ExitMessage::ExitCall(exit_call));\n}\n\n#[doc(hidden)]\nimpl std::fmt::Display for ExitCall {\n    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {\n        match self {\n            ExitCall::Terminate(code) => write!(f, \"exit-terminate({code})\"),\n            ExitCall::Restart(code) => write!(f, \"exit-restart({code})\"),\n        }\n    }\n}\n\n#[doc(hidden)]\nimpl std::str::FromStr for ExitCall {\n    type Err = ParseExitError;\n\n    fn from_str(s: &str) -> Result<ExitCall, ParseExitError> {\n        // Strip off the trailing ), leaving the name and (\n        let s = s.strip_suffix(')').ok_or(ParseExitError)?;\n\n        if let Some(s) = s.strip_prefix(\"exit-terminate(\") {\n            Ok(ExitCall::Terminate(s.parse().or(Err(ParseExitError))?))\n        } else if let Some(s) = s.strip_prefix(\"exit-restart(\") {\n            Ok(ExitCall::Restart(s.parse().or(Err(ParseExitError))?))\n        } else {\n            Err(ParseExitError)\n        }\n    }\n}\n\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[doc(hidden)]\npub struct ParseExitError;\n\n// The name of the environment variable used by process A to tell process B that\n// it is process B. The value of the environment variable is the location where\n// exit_test was called (this location is used to help verify that test_name is\n// correct).\nconst SIGNAL_VAR: &str = \"LIBTOCK_UNITTEST_EXIT_TEST\";\n\n// This string is printed by process B to tell process A how it exited. It is\n// followed by the Display string for a ExitMessage.\nconst EXIT_STRING: &str = \"LIBTOCK_UNITTEST_EXIT_TEST_RESULT: \";\n\n#[derive(Debug, Eq, PartialEq)]\nenum ExitMessage {\n    ExitCall(ExitCall),\n    WrongCase,\n    DidNotExit,\n}\n\nimpl std::fmt::Display for ExitMessage {\n    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {\n        match self {\n            ExitMessage::ExitCall(exit_call) => write!(f, \"ExitCall({exit_call})\"),\n            ExitMessage::WrongCase => write!(f, \"WrongCase\"),\n            ExitMessage::DidNotExit => write!(f, \"DidNotExit\"),\n        }\n    }\n}\n\nimpl std::str::FromStr for ExitMessage {\n    type Err = ParseExitError;\n\n    fn from_str(s: &str) -> Result<ExitMessage, ParseExitError> {\n        if let Some(s) = s.strip_prefix(\"ExitCall(\") {\n            let s = s.strip_suffix(')').ok_or(ParseExitError)?;\n            Ok(ExitMessage::ExitCall(s.parse()?))\n        } else if s == \"WrongCase\" {\n            Ok(ExitMessage::WrongCase)\n        } else if s == \"DidNotExit\" {\n            Ok(ExitMessage::DidNotExit)\n        } else {\n            Err(ParseExitError)\n        }\n    }\n}\n\n// Implements process A's behavior for exit_test: spawns this test again as a\n// subprocess, only executing the test specified by test_name.\n#[track_caller]\nfn spawn_test(test_name: &str) -> ExitCall {\n    let current_exe = std::env::current_exe().expect(\"Unable to find test executable\");\n    let output = std::process::Command::new(current_exe)\n        .args(std::env::args_os())\n        .arg(\"--nocapture\")\n        .arg(\"--exact\")\n        .arg(test_name)\n        .envs(std::env::vars_os())\n        .env(SIGNAL_VAR, format!(\"{}\", Location::caller()))\n        .output()\n        .expect(\"Subprocess exec failed\");\n    let stdout = String::from_utf8(output.stdout).expect(\"Subprocess produced invalid UTF-8\");\n    println!(\"{test_name} subprocess stdout:\\n{stdout}\");\n    let stderr = String::from_utf8(output.stderr).expect(\"Subprocess produced invalid UTF-8\");\n    println!(\"{test_name} subprocess stderr:\\n{stderr}\");\n\n    // Search for the exit message in stdout.\n    for line in stdout.lines() {\n        if let Some(message) = line.strip_prefix(EXIT_STRING) {\n            match message\n                .parse::<ExitMessage>()\n                .expect(\"Failed to parse exit message\")\n            {\n                ExitMessage::ExitCall(exit_call) => return exit_call,\n                ExitMessage::WrongCase => panic!(\n                    \"Subprocess executed the wrong test case. Perhaps test_name is incorrect?\"\n                ),\n                ExitMessage::DidNotExit => panic!(\"Subprocess did not call Exit.\"),\n            }\n        }\n    }\n    panic!(\"Subprocess did not indicate why it exited. Perhaps test_name is incorrect?\");\n}\n\n// Used by process B to send a message to process A.\nfn signal_message(message: ExitMessage) {\n    println!(\"{EXIT_STRING}{message}\");\n}\n\n// Implements process B's behavior for exit_test. Verifies the test case was\n// specified correctly, runs the test function, and prints an error if the test\n// function did not call Exit.\n#[track_caller]\nfn run_test<F: FnOnce() + UnwindSafe>(signal_var: std::ffi::OsString, fcn: F) -> ! {\n    let signal_var = signal_var.to_str().expect(\"Invalid signal variable value\");\n    if format!(\"{}\", Location::caller()) != signal_var {\n        signal_message(ExitMessage::WrongCase);\n        std::process::exit(1);\n    }\n    println!(\"exit_test: closure return value {:?}\", catch_unwind(fcn));\n    signal_message(ExitMessage::DidNotExit);\n    std::process::exit(1);\n}\n"
  },
  {
    "path": "unittest/src/exit_test/tests.rs",
    "content": "use super::*;\n\n#[test]\nfn exitcall_display() {\n    assert_eq!(format!(\"{}\", ExitCall::Terminate(3)), \"exit-terminate(3)\");\n    assert_eq!(format!(\"{}\", ExitCall::Restart(14)), \"exit-restart(14)\");\n}\n\n#[test]\nfn exitcall_parse() {\n    assert_eq!(\"exit-terminate(3)\".parse(), Ok(ExitCall::Terminate(3)));\n    assert_eq!(\"exit-restart(14)\".parse(), Ok(ExitCall::Restart(14)));\n    assert_eq!(\"exit-unknown(3)\".parse::<ExitCall>(), Err(ParseExitError));\n    assert_eq!(\n        \"exit-restart(not-an-int)\".parse::<ExitCall>(),\n        Err(ParseExitError)\n    );\n    assert_eq!(\"no-parens\".parse::<ExitCall>(), Err(ParseExitError));\n    assert_eq!(\"\".parse::<ExitCall>(), Err(ParseExitError));\n}\n\n#[test]\nfn exitmessage_display() {\n    assert_eq!(\n        format!(\"{}\", ExitMessage::ExitCall(ExitCall::Restart(1))),\n        \"ExitCall(exit-restart(1))\"\n    );\n    assert_eq!(format!(\"{}\", ExitMessage::WrongCase), \"WrongCase\");\n    assert_eq!(format!(\"{}\", ExitMessage::DidNotExit), \"DidNotExit\");\n}\n\n#[test]\nfn exitmessage_parse() {\n    assert_eq!(\"\".parse::<ExitMessage>(), Err(ParseExitError));\n    assert_eq!(\"ExitCall()\".parse::<ExitMessage>(), Err(ParseExitError));\n    assert_eq!(\n        \"ExitCall(error)\".parse::<ExitMessage>(),\n        Err(ParseExitError)\n    );\n    assert_eq!(\n        \"ExitCall(exit-restart(5))\".parse::<ExitMessage>(),\n        Ok(ExitMessage::ExitCall(ExitCall::Restart(5)))\n    );\n    assert_eq!(\n        \"WrongCase\".parse::<ExitMessage>(),\n        Ok(ExitMessage::WrongCase)\n    );\n    assert_eq!(\n        \"DidNotExit\".parse::<ExitMessage>(),\n        Ok(ExitMessage::DidNotExit)\n    );\n}\n\n#[should_panic(expected = \"did not call Exit\")]\n#[test]\nfn exit_test_did_not_exit() {\n    exit_test(\"exit_test::tests::exit_test_did_not_exit\", || {});\n}\n\n#[should_panic(expected = \"did not indicate why it exited\")]\n#[test]\nfn exit_test_did_not_signal() {\n    exit_test(\"exit_test::tests::exit_test_did_not_signal\", || {\n        std::process::exit(1)\n    });\n}\n\n#[test]\nfn exit_test_signal_terminate() {\n    let result = exit_test(\"exit_test::tests::exit_test_signal_terminate\", || {\n        signal_exit(ExitCall::Terminate(159));\n        std::process::exit(1);\n    });\n    assert_eq!(result, ExitCall::Terminate(159));\n}\n\n#[test]\nfn exit_test_signal_restart() {\n    let result = exit_test(\"exit_test::tests::exit_test_signal_restart\", || {\n        signal_exit(ExitCall::Restart(0));\n        std::process::exit(1);\n    });\n    assert_eq!(result, ExitCall::Restart(0));\n}\n\n#[should_panic(expected = \"executed the wrong test case\")]\n#[test]\nfn exit_test_wrong_case() {\n    // Intentionally-incorrect test case name.\n    exit_test(\"exit_test::tests::exit_test_signal_restart\", || {\n        signal_exit(ExitCall::Restart(0));\n        std::process::exit(1);\n    });\n}\n"
  },
  {
    "path": "unittest/src/expected_syscall.rs",
    "content": "use libtock_platform::Register;\n\n/// Unit tests can use `ExpectedSyscall` to alter `fake::Kernel`'s behavior for\n/// a particular system call. An example use case is error injection: unit tests\n/// can add a `ExpectedSyscall` to the fake kernel's queue to insert errors in\n/// order to test error handling code.\n#[derive(Clone, Copy, Debug)]\npub enum ExpectedSyscall {\n    // -------------------------------------------------------------------------\n    // Yield\n    // -------------------------------------------------------------------------\n    YieldNoWait {\n        /// If not `None`, `yield-no-wait` will set the return value to the\n        /// specified value. If `None`, `yield-no-wait` will set the return\n        /// value based on whether or not an upcall was run.\n        override_return: Option<libtock_platform::YieldNoWaitReturn>,\n    },\n\n    YieldWait {\n        /// If true, yield_wait will skip executing a upcall.\n        skip_upcall: bool,\n    },\n\n    // -------------------------------------------------------------------------\n    // Subscribe\n    // -------------------------------------------------------------------------\n    Subscribe {\n        driver_num: u32,\n        subscribe_num: u32,\n\n        /// If not None, the Subscribe call will be skipped and the provided\n        /// error code will be returned (along with the passed upcall).\n        skip_with_error: Option<libtock_platform::ErrorCode>,\n    },\n\n    // -------------------------------------------------------------------------\n    // Command\n    // -------------------------------------------------------------------------\n    Command {\n        // Matched values: the command must give the specified driver_id,\n        // command_id, argument0, and argument1 values.\n        driver_id: u32,\n        command_id: u32,\n        argument0: u32,\n        argument1: u32,\n\n        // If not None, the output of the driver will be replaced with the given\n        // return value.\n        override_return: Option<libtock_platform::CommandReturn>,\n    },\n\n    // -------------------------------------------------------------------------\n    // Read-Only Allow\n    // -------------------------------------------------------------------------\n    AllowRo {\n        driver_num: u32,\n        buffer_num: u32,\n\n        // If set to Some(_), the driver's allow_readonly method will not be\n        // invoked and the provided error will be returned instead.\n        return_error: Option<libtock_platform::ErrorCode>,\n    },\n\n    // -------------------------------------------------------------------------\n    // Read-Write Allow\n    // -------------------------------------------------------------------------\n    AllowRw {\n        driver_num: u32,\n        buffer_num: u32,\n\n        // If set to Some(_), the driver's allow_readwrite method will not be\n        // invoked and the provided error will be returned instead.\n        return_error: Option<libtock_platform::ErrorCode>,\n    },\n\n    // -------------------------------------------------------------------------\n    // Memop\n    // -------------------------------------------------------------------------\n    Memop {\n        memop_num: u32,\n        argument0: Register, // Necessary for Miri ptr provenance tests of brk\n\n        // If set to Some(_), the driver's memop method will not be\n        // invoked and the provided error will be returned instead.\n        return_error: Option<libtock_platform::ErrorCode>,\n    },\n    // TODO: Add Exit.\n}\n\nimpl ExpectedSyscall {\n    // Panics with a message describing that the named system call was called\n    // instead of the expected system call. Used by fake::Kernel to report\n    // incorrect system calls.\n    pub(crate) fn panic_wrong_call(&self, called: &str) -> ! {\n        // TODO: Implement Display for ExpectedSyscall and replace {:?} with {}\n        panic!(\"Expected system call {self:?}, but {called} was called instead.\");\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/adc/mod.rs",
    "content": "//! Fake implementation of the Adc API, documented here:\n//!\n//! Like the real API, `Adc` controls a fake Adc sensor. It provides\n//! a function `set_value` used to immediately call an upcall with a Adc value read by the sensor\n//! and a function 'set_value_sync' used to call the upcall when the read command is received.\n\nuse crate::{DriverInfo, DriverShareRef};\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::cell::Cell;\n\n// The `upcall_on_command` field is set to Some(value) if an upcall(with value as its argument) should be called when read command is received,\n// or None otherwise. It was needed for testing `read_sync` library function which simulates a synchronous Adc read,\n// because it was impossible to schedule an upcall during the `synchronous` read in other ways.\npub struct Adc {\n    busy: Cell<bool>,\n    upcall_on_command: Cell<Option<i32>>,\n    share_ref: DriverShareRef,\n}\n\nimpl Adc {\n    pub fn new() -> std::rc::Rc<Adc> {\n        std::rc::Rc::new(Adc {\n            busy: Cell::new(false),\n            upcall_on_command: Cell::new(None),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn is_busy(&self) -> bool {\n        self.busy.get()\n    }\n    pub fn set_value(&self, value: i32) {\n        if self.busy.get() {\n            self.share_ref\n                .schedule_upcall(0, (value as u32, 0, 0))\n                .expect(\"Unable to schedule upcall\");\n            self.busy.set(false);\n        }\n    }\n    pub fn set_value_sync(&self, value: i32) {\n        self.upcall_on_command.set(Some(value));\n    }\n}\n\nimpl crate::fake::SyscallDriver for Adc {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_id {\n            EXISTS => crate::command_return::success_u32(1),\n\n            SINGLE_SAMPLE => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_command.take() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x5;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst SINGLE_SAMPLE: u32 = 1;\n"
  },
  {
    "path": "unittest/src/fake/adc/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::adc::*;\nuse libtock_platform::{share, DefaultConfig, YieldNoWaitReturn};\n\n//Test the command implementation\n#[test]\nfn command() {\n    let adc = Adc::new();\n\n    assert!(adc.command(EXISTS, 1, 2).is_success_u32());\n\n    assert!(adc.command(SINGLE_SAMPLE, 0, 0).is_success());\n\n    assert_eq!(\n        adc.command(SINGLE_SAMPLE, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    adc.set_value(100);\n    assert!(adc.command(SINGLE_SAMPLE, 0, 1).is_success());\n    adc.set_value(100);\n\n    adc.set_value_sync(100);\n    assert!(adc.command(SINGLE_SAMPLE, 0, 1).is_success());\n    assert!(adc.command(SINGLE_SAMPLE, 0, 1).is_success());\n}\n\n// Integration test that verifies Adc works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let adc = Adc::new();\n    kernel.add_driver(&adc);\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2).is_success_u32());\n    assert!(fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    adc.set_value(100);\n    assert!(fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 1).is_success());\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        adc.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        adc.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 1).is_success());\n        adc.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        adc.set_value_sync(200);\n        assert!(fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 1).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    });\n}\n"
  },
  {
    "path": "unittest/src/fake/air_quality/mod.rs",
    "content": "use crate::{DriverInfo, DriverShareRef};\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::cell::Cell;\n\npub struct AirQuality {\n    busy: Cell<bool>,\n    co2_available: Cell<bool>,\n    tvoc_available: Cell<bool>,\n    upcall_on_read: Cell<Option<u32>>,\n    upcall_on_tuple_read: Cell<Option<(u32, u32)>>,\n    share_ref: DriverShareRef,\n}\n\nimpl AirQuality {\n    pub fn new() -> std::rc::Rc<AirQuality> {\n        std::rc::Rc::new(AirQuality {\n            busy: Cell::new(false),\n            co2_available: Cell::new(true),\n            tvoc_available: Cell::new(true),\n            upcall_on_read: Cell::new(None),\n            upcall_on_tuple_read: Cell::new(None),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn set_co2_available(&self, co2_available: bool) {\n        self.co2_available.set(co2_available);\n    }\n\n    pub fn set_tvoc_available(&self, tvoc_available: bool) {\n        self.tvoc_available.set(tvoc_available);\n    }\n\n    pub fn is_busy(&self) -> bool {\n        self.busy.get()\n    }\n\n    pub fn set_value(&self, value: u32) {\n        if self.busy.get() {\n            self.share_ref\n                .schedule_upcall(0, (value, 0, 0))\n                .expect(\"Unable to schedule upcall\");\n            self.busy.set(false);\n        }\n    }\n    pub fn set_value_sync(&self, value: u32) {\n        self.upcall_on_read.set(Some(value));\n    }\n    pub fn set_values_sync(&self, co2_value: u32, tvoc_value: u32) {\n        self.upcall_on_tuple_read.set(Some((co2_value, tvoc_value)));\n    }\n}\n\nimpl crate::fake::SyscallDriver for AirQuality {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_id {\n            EXISTS => crate::command_return::success(),\n            READ_CO2 => {\n                if !self.co2_available.get() {\n                    return crate::command_return::failure(ErrorCode::NoSupport);\n                }\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_read.take() {\n                    self.set_value(val);\n                }\n                if let Some((co2_val, _)) = self.upcall_on_tuple_read.get() {\n                    self.set_value(co2_val);\n                }\n\n                crate::command_return::success()\n            }\n            READ_TVOC => {\n                if !self.tvoc_available.get() {\n                    return crate::command_return::failure(ErrorCode::NoSupport);\n                }\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_read.take() {\n                    self.set_value(val);\n                }\n                if let Some((_, tvoc_val)) = self.upcall_on_tuple_read.take() {\n                    self.set_value(tvoc_val);\n                }\n\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60007;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ_CO2: u32 = 2;\nconst READ_TVOC: u32 = 3;\n"
  },
  {
    "path": "unittest/src/fake/air_quality/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::air_quality::*;\nuse libtock_platform::{share::scope, DefaultConfig, YieldNoWaitReturn};\n\n//Test the `command` implementation\n#[test]\nfn command() {\n    let driver = AirQuality::new();\n\n    assert!(driver.command(EXISTS, 0, 0).is_success());\n\n    driver.set_co2_available(false);\n    assert_eq!(\n        driver.command(READ_CO2, 0, 0).get_failure(),\n        Some(ErrorCode::NoSupport)\n    );\n    driver.set_tvoc_available(false);\n    assert_eq!(\n        driver.command(READ_TVOC, 0, 0).get_failure(),\n        Some(ErrorCode::NoSupport)\n    );\n\n    driver.set_co2_available(true);\n    driver.set_tvoc_available(true);\n\n    assert!(driver.command(READ_CO2, 0, 0).is_success());\n    assert_eq!(\n        driver.command(READ_CO2, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    driver.set_value(100);\n    assert!(driver.command(READ_CO2, 0, 0).is_success());\n    driver.set_value(100);\n\n    assert!(driver.command(READ_TVOC, 0, 0).is_success());\n    assert_eq!(\n        driver.command(READ_TVOC, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    driver.set_value(100);\n    assert!(driver.command(READ_TVOC, 0, 0).is_success());\n    driver.set_value(100);\n\n    driver.set_value_sync(100);\n    assert!(driver.command(READ_CO2, 0, 0).is_success());\n    assert!(driver.command(READ_TVOC, 0, 0).is_success());\n}\n\n// Integration test that verifies Temperature works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let driver = AirQuality::new();\n    kernel.add_driver(&driver);\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 0, 0).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_CO2, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, READ_CO2, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    driver.set_value(100);\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_CO2, 0, 0).is_success());\n    driver.set_value(100);\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_TVOC, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, READ_TVOC, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    driver.set_value(100);\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_TVOC, 0, 0).is_success());\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n    scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        driver.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_CO2, 0, 0).is_success());\n        driver.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((200,)));\n\n        driver.set_value_sync(200);\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_CO2, 0, 0).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_TVOC, 0, 0).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        driver.set_value_sync(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n        driver.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        driver.set_values_sync(100, 200);\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_CO2, 0, 0).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_TVOC, 0, 0).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_CO2, 0, 0).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n}\n"
  },
  {
    "path": "unittest/src/fake/alarm/mod.rs",
    "content": "//! Fake implementation of the Alarm API.\n//!\n//! Supports frequency and set_relative.\n//! Will schedule the upcall immediately.\n\nuse core::cell::Cell;\nuse core::num::Wrapping;\nuse libtock_platform::{CommandReturn, ErrorCode};\n\nuse crate::{DriverInfo, DriverShareRef};\n\npub struct Alarm {\n    frequency_hz: u32,\n    now: Cell<Wrapping<u32>>,\n    share_ref: DriverShareRef,\n}\n\nimpl Alarm {\n    pub fn new(frequency_hz: u32) -> std::rc::Rc<Alarm> {\n        std::rc::Rc::new(Alarm {\n            frequency_hz,\n            now: Cell::new(Wrapping(0)),\n            share_ref: Default::default(),\n        })\n    }\n}\n\nimpl crate::fake::SyscallDriver for Alarm {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_number: u32, argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_number {\n            command::FREQUENCY => crate::command_return::success_u32(self.frequency_hz),\n            command::SET_RELATIVE => {\n                // We're not actually sleeping, just ticking the timer.\n                // The semantics of sleeping aren't clear,\n                // so we're assuming that all future times are equal,\n                // and waking immediately.\n                let relative = argument0;\n                let wake = self.now.get() + Wrapping(relative);\n                self.share_ref\n                    .schedule_upcall(subscribe::CALLBACK, (wake.0, 0, 0))\n                    .expect(\"schedule_upcall failed\");\n                self.now.set(wake);\n                crate::command_return::success_u32(wake.0)\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x0;\n\n// Command IDs\n#[allow(unused)]\npub mod command {\n    pub const EXISTS: u32 = 0;\n    pub const FREQUENCY: u32 = 1;\n    pub const TIME: u32 = 2;\n    pub const STOP: u32 = 3;\n\n    pub const SET_RELATIVE: u32 = 5;\n    pub const SET_ABSOLUTE: u32 = 6;\n}\n\n#[allow(unused)]\npub mod subscribe {\n    pub const CALLBACK: u32 = 0;\n}\n"
  },
  {
    "path": "unittest/src/fake/alarm/tests.rs",
    "content": "use crate::fake;\nuse fake::alarm::*;\n\n// Tests the command implementation.\n#[test]\nfn command() {\n    use fake::SyscallDriver;\n    let alarm = Alarm::new(10);\n\n    assert_eq!(\n        alarm.command(command::FREQUENCY, 1, 2).get_success_u32(),\n        Some(10)\n    );\n}\n"
  },
  {
    "path": "unittest/src/fake/ambient_light/mod.rs",
    "content": "//! Fake implementation of the Ambient Light API, documented here:\n//! https://github.com/tock/tock/blob/master/doc/syscalls/60002_luminance.md\n//!\n//! Like the real API, `AmbientLight` controls a fake ambient light sensor. It provides\n//! a function `set_value` used to immediately call an upcall with a intensity value read by the sensor\n//! and a function 'set_value_sync' used to call the upcall when the read command is received.\n\nuse crate::{DriverInfo, DriverShareRef};\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::cell::Cell;\n\n// The `upcall_on_command` field is set to Some(value) if an upcall(with value as its argument) should be called when read command is received,\n// or None otherwise. It was needed for testing `read_sync` library function which simulates a synchronous temperature read,\n// because it was impossible to schedule an upcall during the `synchronous` read in other ways.\npub struct AmbientLight {\n    busy: Cell<bool>,\n    upcall_on_command: Cell<Option<u32>>,\n    share_ref: DriverShareRef,\n}\n\nimpl AmbientLight {\n    pub fn new() -> std::rc::Rc<AmbientLight> {\n        std::rc::Rc::new(AmbientLight {\n            busy: Cell::new(false),\n            upcall_on_command: Cell::new(None),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn is_busy(&self) -> bool {\n        self.busy.get()\n    }\n    pub fn set_value(&self, value: u32) {\n        if self.busy.get() {\n            self.share_ref\n                .schedule_upcall(0, (value, 0, 0))\n                .expect(\"Unable to schedule upcall\");\n            self.busy.set(false);\n        }\n    }\n    pub fn set_value_sync(&self, value: u32) {\n        self.upcall_on_command.set(Some(value));\n    }\n}\n\nimpl crate::fake::SyscallDriver for AmbientLight {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_id {\n            EXISTS => crate::command_return::success(),\n\n            READ_INTENSITY => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_command.take() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60002;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ_INTENSITY: u32 = 1;\n"
  },
  {
    "path": "unittest/src/fake/ambient_light/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::ambient_light::*;\nuse libtock_platform::{share, DefaultConfig, YieldNoWaitReturn};\n\n//Test the command implementation\n#[test]\nfn command() {\n    let amb = AmbientLight::new();\n\n    assert!(amb.command(EXISTS, 1, 2).is_success());\n\n    assert!(amb.command(READ_INTENSITY, 0, 0).is_success());\n\n    assert_eq!(\n        amb.command(READ_INTENSITY, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    amb.set_value(100);\n    assert!(amb.command(READ_INTENSITY, 0, 1).is_success());\n    amb.set_value(100);\n\n    amb.set_value_sync(100);\n    assert!(amb.command(READ_INTENSITY, 0, 1).is_success());\n    assert!(amb.command(READ_INTENSITY, 0, 1).is_success());\n}\n\n// Integration test that verifies AmbientLight works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let ambient_light = AmbientLight::new();\n    kernel.add_driver(&ambient_light);\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_INTENSITY, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, READ_INTENSITY, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    ambient_light.set_value(100);\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_INTENSITY, 0, 1).is_success());\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        ambient_light.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        ambient_light.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_INTENSITY, 0, 1).is_success());\n        ambient_light.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        ambient_light.set_value_sync(200);\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_INTENSITY, 0, 1).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    });\n}\n"
  },
  {
    "path": "unittest/src/fake/buttons/mod.rs",
    "content": "//! Fake implementation of the Buttons API, documented here:\n//! https://github.com/tock/tock/blob/master/doc/syscalls/00003_buttons.md\n//!\n//! Like the real API, `Buttons` controls a set of fake buttons. It provides\n//! a function `get_button_state` used to retrieve the state and interrupt\n//! status of a button.\n//!\n//! It also provides the function `set_pressed` that set the button's state.\n\nuse core::cell::Cell;\nuse libtock_platform::{CommandReturn, ErrorCode};\n\nuse crate::{DriverInfo, DriverShareRef};\n\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub struct ButtonState {\n    pub pressed: bool,\n    pub interrupt_enabled: bool,\n}\n\npub struct Buttons<const NUM_BUTTONS: usize> {\n    buttons: [Cell<ButtonState>; NUM_BUTTONS],\n    share_ref: DriverShareRef,\n}\n\nimpl<const NUM_BUTTONS: usize> Buttons<NUM_BUTTONS> {\n    pub fn new() -> std::rc::Rc<Buttons<NUM_BUTTONS>> {\n        #[allow(clippy::declare_interior_mutable_const)]\n        const OFF: Cell<ButtonState> = Cell::new(ButtonState {\n            pressed: false,\n            interrupt_enabled: false,\n        });\n        std::rc::Rc::new(Buttons {\n            buttons: [OFF; NUM_BUTTONS],\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn set_pressed(&self, button: u32, pressed: bool) -> Result<(), ErrorCode> {\n        self.buttons\n            .get(button as usize)\n            .map(|button_state| {\n                let original_button_state = button_state.get();\n                button_state.set(ButtonState {\n                    pressed,\n                    ..original_button_state\n                });\n                if original_button_state.interrupt_enabled\n                    && original_button_state.pressed != pressed\n                {\n                    self.share_ref\n                        .schedule_upcall(0, (button, pressed as u32, 0))\n                        .expect(\"Unable to schedule upcall {}\");\n                }\n            })\n            .ok_or(ErrorCode::Invalid)\n    }\n\n    pub fn get_button_state(&self, button: u32) -> Option<ButtonState> {\n        self.buttons.get(button as usize).map(|button| button.get())\n    }\n}\n\nimpl<const NUM_BUTTONS: usize> crate::fake::SyscallDriver for Buttons<NUM_BUTTONS> {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_number: u32, argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_number {\n            BUTTONS_COUNT => crate::command_return::success_u32(NUM_BUTTONS as u32),\n            BUTTONS_ENABLE_INTERRUPTS => {\n                if argument0 < NUM_BUTTONS as u32 {\n                    let button = self.buttons[argument0 as usize].get();\n                    self.buttons[argument0 as usize].set(ButtonState {\n                        interrupt_enabled: true,\n                        ..button\n                    });\n                    crate::command_return::success()\n                } else {\n                    crate::command_return::failure(ErrorCode::Invalid)\n                }\n            }\n            BUTTONS_DISABLE_INTERRUPTS => {\n                if argument0 < NUM_BUTTONS as u32 {\n                    let button = self.buttons[argument0 as usize].get();\n                    self.buttons[argument0 as usize].set(ButtonState {\n                        interrupt_enabled: false,\n                        ..button\n                    });\n                    crate::command_return::success()\n                } else {\n                    crate::command_return::failure(ErrorCode::Invalid)\n                }\n            }\n            BUTTONS_READ => {\n                if argument0 < NUM_BUTTONS as u32 {\n                    crate::command_return::success_u32(\n                        self.buttons[argument0 as usize].get().pressed as u32,\n                    )\n                } else {\n                    crate::command_return::failure(ErrorCode::Invalid)\n                }\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x3;\n\n// Command IDs\nconst BUTTONS_COUNT: u32 = 0;\n\nconst BUTTONS_ENABLE_INTERRUPTS: u32 = 1;\nconst BUTTONS_DISABLE_INTERRUPTS: u32 = 2;\n\nconst BUTTONS_READ: u32 = 3;\n"
  },
  {
    "path": "unittest/src/fake/buttons/tests.rs",
    "content": "use crate::fake;\nuse fake::buttons::*;\nuse libtock_platform::ErrorCode;\n\n// Tests the command implementation.\n#[test]\nfn command() {\n    use fake::SyscallDriver;\n    let buttons = Buttons::<10>::new();\n\n    assert_eq!(\n        buttons.command(BUTTONS_COUNT, 1, 2).get_success_u32(),\n        Some(10)\n    );\n\n    assert_eq!(\n        buttons.command(BUTTONS_READ, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        buttons\n            .command(BUTTONS_ENABLE_INTERRUPTS, 11, 0)\n            .get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        buttons\n            .command(BUTTONS_DISABLE_INTERRUPTS, 11, 0)\n            .get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n\n    for button_index in 0..10 {\n        assert_eq!(\n            buttons.get_button_state(button_index),\n            Some(ButtonState {\n                pressed: false,\n                interrupt_enabled: false\n            })\n        );\n\n        assert!(buttons\n            .command(BUTTONS_ENABLE_INTERRUPTS, button_index, 0)\n            .is_success());\n        assert_eq!(\n            buttons.get_button_state(button_index),\n            Some(ButtonState {\n                pressed: false,\n                interrupt_enabled: true\n            })\n        );\n\n        assert!(buttons\n            .command(BUTTONS_DISABLE_INTERRUPTS, button_index, 0)\n            .is_success());\n        assert_eq!(\n            buttons.get_button_state(button_index),\n            Some(ButtonState {\n                pressed: false,\n                interrupt_enabled: false\n            })\n        );\n\n        assert_eq!(buttons.set_pressed(button_index, true), Ok(()));\n        assert_eq!(\n            buttons.get_button_state(button_index),\n            Some(ButtonState {\n                pressed: true,\n                interrupt_enabled: false\n            })\n        );\n\n        assert_eq!(buttons.set_pressed(button_index, false), Ok(()));\n        assert_eq!(\n            buttons.get_button_state(button_index),\n            Some(ButtonState {\n                pressed: false,\n                interrupt_enabled: false\n            })\n        );\n    }\n}\n\n// Integration test that verifies Buttons works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let buttons = Buttons::<10>::new();\n    kernel.add_driver(&buttons);\n    let value = fake::Syscalls::command(DRIVER_NUM, BUTTONS_COUNT, 1, 2);\n    assert_eq!(value.get_success_u32(), Some(10));\n\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, BUTTONS_READ, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert!(fake::Syscalls::command(DRIVER_NUM, BUTTONS_READ, 0, 0).is_success_u32());\n\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, BUTTONS_ENABLE_INTERRUPTS, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert!(fake::Syscalls::command(DRIVER_NUM, BUTTONS_ENABLE_INTERRUPTS, 0, 0).is_success());\n\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, BUTTONS_DISABLE_INTERRUPTS, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert!(fake::Syscalls::command(DRIVER_NUM, BUTTONS_DISABLE_INTERRUPTS, 0, 0).is_success());\n}\n"
  },
  {
    "path": "unittest/src/fake/buzzer/mod.rs",
    "content": "//! Fake implementation of the Buzzer API, documented here:\n//!\n//! Like the real API, `Buzzer` controls a fake buzzer. It provides\n//! a function `set_tone` used to immediately call an upcall with a tone set by the buzzer\n//! and a function 'set_tone_sync' used to call the upcall when the tone command is received.\n\nuse crate::{DriverInfo, DriverShareRef};\nuse core::time::Duration;\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::cell::Cell;\n\n// The `upcall_on_command` field is set to Some(value) if an upcall(with value as its argument) should be called when tone command is received,\n// or None otherwise. It was needed for testing `tone_sync` library function which simulates a synchronous tone set,\n// because it was impossible to schedule an upcall during the `synchronous` tone set in other ways.\npub struct Buzzer {\n    busy: Cell<bool>,\n    upcall_on_command: [Cell<Option<i32>>; 2],\n    share_ref: DriverShareRef,\n}\n\nimpl Buzzer {\n    pub fn new() -> std::rc::Rc<Buzzer> {\n        std::rc::Rc::new(Buzzer {\n            busy: Cell::new(false),\n            upcall_on_command: [Cell::new(None), Cell::new(None)],\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn is_busy(&self) -> bool {\n        self.busy.get()\n    }\n\n    pub fn set_tone(&self, freq: i32, duration: Duration) {\n        if self.busy.get() {\n            self.share_ref\n                .schedule_upcall(0, (freq as u32, duration.as_millis() as u32, 0))\n                .expect(\"Unable to schedule upcall\");\n            self.busy.set(false);\n        }\n    }\n\n    pub fn set_tone_sync(&self, freq: i32, duration: i32) {\n        self.upcall_on_command[0].set(Some(freq));\n        self.upcall_on_command[1].set(Some(duration));\n    }\n}\n\nimpl crate::fake::SyscallDriver for Buzzer {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_num: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_num {\n            EXISTS => crate::command_return::success(),\n            TONE => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(freq) = self.upcall_on_command[0].take() {\n                    if let Some(duration) = self.upcall_on_command[1].take() {\n                        self.set_tone(freq, Duration::from_millis(duration as u64));\n                    }\n                }\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x90000;\n\n// Command IDs\nconst EXISTS: u32 = 0;\nconst TONE: u32 = 1;\n"
  },
  {
    "path": "unittest/src/fake/buzzer/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::buzzer::*;\nuse libtock_platform::{share, DefaultConfig, YieldNoWaitReturn};\n\n#[test]\nfn command() {\n    let buzzer = Buzzer::new();\n    assert!(buzzer.command(EXISTS, 1, 2).is_success());\n    assert!(buzzer.command(TONE, 0, 0).is_success());\n\n    assert_eq!(\n        buzzer.command(TONE, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    buzzer.set_tone(100, Duration::from_millis(100));\n    assert!(buzzer.command(TONE, 0, 1).is_success());\n    buzzer.set_tone(100, Duration::from_millis(100));\n\n    buzzer.set_tone_sync(100, 100);\n    assert!(buzzer.command(TONE, 0, 1).is_success());\n    assert!(buzzer.command(TONE, 0, 1).is_success());\n}\n\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let buzzer = Buzzer::new();\n    kernel.add_driver(&buzzer);\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, TONE, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, TONE, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    buzzer.set_tone(100, Duration::from_millis(100));\n    assert!(fake::Syscalls::command(DRIVER_NUM, TONE, 0, 1).is_success());\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        buzzer.set_tone(100, Duration::from_millis(100));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        buzzer.set_tone(200, Duration::from_millis(100));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, TONE, 0, 1).is_success());\n        buzzer.set_tone(200, Duration::from_millis(100));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((200,)));\n    });\n}\n"
  },
  {
    "path": "unittest/src/fake/console/mod.rs",
    "content": "//! Fake implementation of the Console API, documented here:\n//! https://github.com/tock/tock/blob/master/doc/syscalls/00001_console.md\n//!\n//! Like the real API, `Console` stores each message written to it.\n//! The resulting byte stream can be retrieved via `take_bytes`\n//! for use in unit tests.\n\nuse core::cell::{Cell, RefCell};\nuse core::cmp;\nuse libtock_platform::{CommandReturn, ErrorCode};\n\nuse crate::{DriverInfo, DriverShareRef, RoAllowBuffer, RwAllowBuffer};\n\npub struct Console {\n    messages: Cell<Vec<u8>>,\n    buffer: Cell<RoAllowBuffer>,\n\n    read_buffer: RefCell<RwAllowBuffer>,\n    /// To be returned on read\n    input: Cell<Vec<u8>>,\n\n    share_ref: DriverShareRef,\n}\n\nimpl Console {\n    pub fn new() -> std::rc::Rc<Console> {\n        Self::new_with_input(b\"\")\n    }\n\n    pub fn new_with_input(inputs: &[u8]) -> std::rc::Rc<Console> {\n        std::rc::Rc::new(Console {\n            messages: Default::default(),\n            buffer: Default::default(),\n            read_buffer: Default::default(),\n            input: Cell::new(Vec::from(inputs)),\n            share_ref: Default::default(),\n        })\n    }\n\n    /// Returns the bytes that have been submitted so far,\n    /// and clears them.\n    pub fn take_bytes(&self) -> Vec<u8> {\n        self.messages.take()\n    }\n}\n\nimpl crate::fake::SyscallDriver for Console {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(3)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn allow_readonly(\n        &self,\n        buffer_num: u32,\n        buffer: RoAllowBuffer,\n    ) -> Result<RoAllowBuffer, (RoAllowBuffer, ErrorCode)> {\n        if buffer_num == ALLOW_WRITE {\n            Ok(self.buffer.replace(buffer))\n        } else {\n            Err((buffer, ErrorCode::Invalid))\n        }\n    }\n\n    fn allow_readwrite(\n        &self,\n        buffer_num: u32,\n        buffer: RwAllowBuffer,\n    ) -> Result<RwAllowBuffer, (RwAllowBuffer, ErrorCode)> {\n        if buffer_num == ALLOW_READ {\n            Ok(self.read_buffer.replace(buffer))\n        } else {\n            Err((buffer, ErrorCode::Invalid))\n        }\n    }\n\n    fn command(&self, command_num: u32, argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_num {\n            EXISTS => {}\n            WRITE => {\n                let mut bytes = self.messages.take();\n                let buffer = self.buffer.take();\n                let size = cmp::min(buffer.len(), argument0 as usize);\n                bytes.extend_from_slice(&(*buffer)[..size]);\n                self.buffer.set(buffer);\n                self.messages.set(bytes);\n                self.share_ref\n                    .schedule_upcall(SUBSCRIBE_WRITE, (size as u32, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n            }\n            READ => {\n                let count_wanted = argument0 as usize;\n                let bytes = self.input.take();\n                let count_wanted = cmp::min(count_wanted, bytes.len());\n                let to_send = &bytes[..count_wanted];\n                let to_keep = &bytes[count_wanted..];\n                self.input.set(Vec::from(to_keep));\n\n                let count_available = to_send.len();\n                self.read_buffer.borrow_mut()[..count_wanted].copy_from_slice(to_send);\n                self.share_ref\n                    .schedule_upcall(SUBSCRIBE_READ, (0, count_available as u32, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n            }\n            _ => return crate::command_return::failure(ErrorCode::NoSupport),\n        }\n        crate::command_return::success()\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Implementation details below\n// -----------------------------------------------------------------------------\n\n#[cfg(test)]\nmod tests;\n\nconst DRIVER_NUM: u32 = 0x1;\n\n// Command numbers\nconst EXISTS: u32 = 0;\nconst WRITE: u32 = 1;\nconst READ: u32 = 2;\n//const ABORT: u32 = 3;\nconst SUBSCRIBE_WRITE: u32 = 1;\nconst SUBSCRIBE_READ: u32 = 2;\nconst ALLOW_WRITE: u32 = 1;\nconst ALLOW_READ: u32 = 1;\n"
  },
  {
    "path": "unittest/src/fake/console/tests.rs",
    "content": "use crate::fake;\nuse crate::{RoAllowBuffer, RwAllowBuffer};\nuse libtock_platform::share;\nuse libtock_platform::DefaultConfig;\n\n// Tests the command implementation.\n#[test]\nfn command() {\n    use fake::SyscallDriver;\n    let console = fake::Console::new();\n    assert!(console.command(fake::console::EXISTS, 1, 2).is_success());\n    assert!(console.allow_readonly(1, RoAllowBuffer::default()).is_ok());\n    assert!(console.allow_readonly(2, RoAllowBuffer::default()).is_err());\n\n    assert!(console.allow_readwrite(1, RwAllowBuffer::default()).is_ok());\n    assert!(console\n        .allow_readwrite(2, RwAllowBuffer::default())\n        .is_err());\n}\n\n// Integration test that verifies Console works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let console = fake::Console::new();\n    kernel.add_driver(&console);\n    assert!(\n        fake::Syscalls::command(fake::console::DRIVER_NUM, fake::console::EXISTS, 1, 2)\n            .is_success()\n    );\n    share::scope(|allow_ro| {\n        fake::Syscalls::allow_ro::<\n            DefaultConfig,\n            { fake::console::DRIVER_NUM },\n            { fake::console::ALLOW_WRITE },\n        >(allow_ro, b\"abcd\")\n        .unwrap();\n        assert!(\n            fake::Syscalls::command(fake::console::DRIVER_NUM, fake::console::WRITE, 3, 0)\n                .is_success()\n        );\n    });\n    assert_eq!(console.take_bytes(), b\"abc\");\n    assert_eq!(console.take_bytes(), b\"\");\n\n    let mut buf = [0; 4];\n\n    share::scope(|allow_rw| {\n        fake::Syscalls::allow_rw::<\n            DefaultConfig,\n            { fake::console::DRIVER_NUM },\n            { fake::console::ALLOW_READ },\n        >(allow_rw, &mut buf)\n        .unwrap();\n        assert!(\n            fake::Syscalls::command(fake::console::DRIVER_NUM, fake::console::READ, 3, 0)\n                .is_success()\n        );\n    });\n}\n"
  },
  {
    "path": "unittest/src/fake/gpio/mod.rs",
    "content": "//! Fake implementation of the GPIO API, documented here:\n//! https://github.com/tock/tock/blob/master/doc/syscalls/00004_gpio.md\n//!\n//! Like the real API, `Gpio` controls a set of fake gpios. It provides\n//! a function `get_button_state` used to retrieve the state and interrupt\n//! status of a button.\n//!\n//! It also provides the function `set_pressed` that set the button's state.\n\nuse core::cell::Cell;\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::convert::TryFrom;\n\nuse crate::{DriverInfo, DriverShareRef};\n\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum GpioMode {\n    Output,\n    Input(PullMode),\n    Disable,\n}\n\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum PullMode {\n    PullNone = 0,\n    PullUp = 1,\n    PullDown = 2,\n}\n\nimpl TryFrom<u32> for PullMode {\n    type Error = ErrorCode;\n\n    fn try_from(value: u32) -> Result<Self, Self::Error> {\n        match value {\n            0 => Ok(PullMode::PullNone),\n            1 => Ok(PullMode::PullUp),\n            2 => Ok(PullMode::PullDown),\n            _ => Err(ErrorCode::Invalid),\n        }\n    }\n}\n\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum InterruptEdge {\n    Either,\n    Rising,\n    Falling,\n}\n\nimpl TryFrom<u32> for InterruptEdge {\n    type Error = ErrorCode;\n\n    fn try_from(value: u32) -> Result<Self, Self::Error> {\n        match value {\n            0 => Ok(InterruptEdge::Either),\n            1 => Ok(InterruptEdge::Rising),\n            2 => Ok(InterruptEdge::Falling),\n            _ => Err(ErrorCode::Invalid),\n        }\n    }\n}\n\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub struct GpioState {\n    pub value: bool,\n    pub mode: GpioMode,\n    pub interrupt_enabled: Option<InterruptEdge>,\n}\n\npub struct Gpio<const NUM_GPIOS: usize> {\n    gpios: [Cell<Option<GpioState>>; NUM_GPIOS],\n    share_ref: DriverShareRef,\n}\n\nimpl<const NUM_GPIOS: usize> Gpio<NUM_GPIOS> {\n    pub fn new() -> std::rc::Rc<Gpio<NUM_GPIOS>> {\n        #[allow(clippy::declare_interior_mutable_const)]\n        const OFF: Cell<Option<GpioState>> = Cell::new(Some(GpioState {\n            value: false,\n            mode: GpioMode::Input(PullMode::PullNone),\n            interrupt_enabled: None,\n        }));\n        std::rc::Rc::new(Gpio {\n            gpios: [OFF; NUM_GPIOS],\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn set_missing_gpio(&self, gpio: usize) {\n        if let Some(state) = self.gpios.get(gpio) {\n            state.set(None);\n        }\n    }\n\n    pub fn set_value(&self, pin: u32, value: bool) -> Result<(), ErrorCode> {\n        self.gpios\n            .get(pin as usize)\n            .map(|gpio| {\n                if let Some(gpio_state) = gpio.get() {\n                    let original_value = gpio_state.value;\n                    gpio.set(Some(GpioState {\n                        value,\n                        ..gpio_state\n                    }));\n                    if original_value != value {\n                        if value {\n                            if gpio_state.interrupt_enabled == Some(InterruptEdge::Either)\n                                || gpio_state.interrupt_enabled == Some(InterruptEdge::Rising)\n                            {\n                                self.share_ref\n                                    .schedule_upcall(0, (pin, value as u32, 0))\n                                    .expect(\"Unable to schedule upcall\");\n                            }\n                        } else if gpio_state.interrupt_enabled == Some(InterruptEdge::Falling)\n                            || gpio_state.interrupt_enabled == Some(InterruptEdge::Either)\n                        {\n                            self.share_ref\n                                .schedule_upcall(0, (pin, value as u32, 0))\n                                .expect(\"Unable to schedule upcall\");\n                        }\n                    }\n                    Ok(())\n                } else {\n                    Err(ErrorCode::NoDevice)\n                }\n            })\n            .ok_or(ErrorCode::Invalid)\n            .and_then(|value| value)\n    }\n\n    pub fn get_gpio_state(&self, button: u32) -> Option<GpioState> {\n        self.gpios\n            .get(button as usize)\n            .map(|button| button.get())\n            .and_then(|value| value)\n    }\n}\n\nimpl<const NUM_GPIOS: usize> crate::fake::SyscallDriver for Gpio<NUM_GPIOS> {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_number: u32, argument0: u32, argument1: u32) -> CommandReturn {\n        if command_number == EXISTS {\n            crate::command_return::success()\n        } else if command_number == GPIO_COUNT {\n            crate::command_return::success_u32(NUM_GPIOS as u32)\n        } else if argument0 < NUM_GPIOS as u32 {\n            if self.gpios[argument0 as usize].get().is_some() {\n                let gpio = self.gpios[argument0 as usize].get().unwrap();\n                match command_number {\n                    GPIO_ENABLE_OUTPUT => {\n                        self.gpios[argument0 as usize].set(Some(GpioState {\n                            mode: GpioMode::Output,\n                            ..gpio\n                        }));\n                        crate::command_return::success()\n                    }\n                    GPIO_SET => {\n                        if let GpioMode::Output = gpio.mode {\n                            self.gpios[argument0 as usize].set(Some(GpioState {\n                                value: true,\n                                ..gpio\n                            }));\n                        }\n                        crate::command_return::success()\n                    }\n                    GPIO_CLEAR => {\n                        if let GpioMode::Output = gpio.mode {\n                            self.gpios[argument0 as usize].set(Some(GpioState {\n                                value: false,\n                                ..gpio\n                            }));\n                        }\n                        crate::command_return::success()\n                    }\n                    GPIO_TOGGLE => {\n                        if let GpioMode::Output = gpio.mode {\n                            self.gpios[argument0 as usize].set(Some(GpioState {\n                                value: !gpio.value,\n                                ..gpio\n                            }));\n                        }\n                        crate::command_return::success()\n                    }\n                    GPIO_ENABLE_INPUT => {\n                        let pull_mode = PullMode::try_from(argument1);\n                        match pull_mode {\n                            Ok(mode) => {\n                                self.gpios[argument0 as usize].set(Some(GpioState {\n                                    mode: GpioMode::Input(mode),\n                                    ..gpio\n                                }));\n                                crate::command_return::success()\n                            }\n                            Err(error) => crate::command_return::failure(error),\n                        }\n                    }\n                    GPIO_READ_INPUT => {\n                        if let GpioMode::Input(_) = gpio.mode {\n                            crate::command_return::success_u32(gpio.value as u32)\n                        } else {\n                            crate::command_return::success_u32(0)\n                        }\n                    }\n                    GPIO_ENABLE_INTERRUPTS => {\n                        let edge = InterruptEdge::try_from(argument1);\n                        match edge {\n                            Ok(interrupt_edge) => {\n                                self.gpios[argument0 as usize].set(Some(GpioState {\n                                    interrupt_enabled: Some(interrupt_edge),\n                                    ..gpio\n                                }));\n                                crate::command_return::success()\n                            }\n                            Err(error) => crate::command_return::failure(error),\n                        }\n                    }\n                    GPIO_DISABLE_INTERRUPTS => {\n                        self.gpios[argument0 as usize].set(Some(GpioState {\n                            interrupt_enabled: None,\n                            ..gpio\n                        }));\n                        crate::command_return::success()\n                    }\n                    GPIO_DISABLE => {\n                        self.gpios[argument0 as usize].set(Some(GpioState {\n                            mode: GpioMode::Disable,\n                            ..gpio\n                        }));\n                        crate::command_return::success()\n                    }\n                    _ => crate::command_return::failure(ErrorCode::NoSupport),\n                }\n            } else {\n                crate::command_return::failure(ErrorCode::NoDevice)\n            }\n        } else {\n            crate::command_return::failure(ErrorCode::Invalid)\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x4;\n\n// Command IDs\nconst EXISTS: u32 = 0;\n\nconst GPIO_ENABLE_OUTPUT: u32 = 1;\nconst GPIO_SET: u32 = 2;\nconst GPIO_CLEAR: u32 = 3;\nconst GPIO_TOGGLE: u32 = 4;\n\nconst GPIO_ENABLE_INPUT: u32 = 5;\nconst GPIO_READ_INPUT: u32 = 6;\n\nconst GPIO_ENABLE_INTERRUPTS: u32 = 7;\nconst GPIO_DISABLE_INTERRUPTS: u32 = 8;\n\nconst GPIO_DISABLE: u32 = 9;\n\nconst GPIO_COUNT: u32 = 10;\n"
  },
  {
    "path": "unittest/src/fake/gpio/tests.rs",
    "content": "use crate::fake;\nuse fake::gpio::*;\nuse libtock_platform::{share, DefaultConfig, ErrorCode, YieldNoWaitReturn};\n\n// Tests the command implementation.\n#[test]\nfn command() {\n    use fake::SyscallDriver;\n    let gpio = Gpio::<10>::new();\n\n    gpio.set_missing_gpio(1);\n\n    assert_eq!(gpio.command(GPIO_COUNT, 1, 2).get_success_u32(), Some(10));\n\n    // Enable Output\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_OUTPUT, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_OUTPUT, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(gpio.command(GPIO_ENABLE_OUTPUT, 0, 0).is_success());\n\n    // Gpio Set\n    assert_eq!(\n        gpio.command(GPIO_SET, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_SET, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(gpio.command(GPIO_SET, 0, 0).is_success(),);\n    assert!(gpio.get_gpio_state(0).unwrap().value);\n\n    // Gpio Clear\n    assert_eq!(\n        gpio.command(GPIO_CLEAR, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_CLEAR, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(gpio.command(GPIO_CLEAR, 0, 0).is_success(),);\n    assert!(!gpio.get_gpio_state(0).unwrap().value);\n\n    // Gpio Toggle\n    assert_eq!(\n        gpio.command(GPIO_TOGGLE, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_TOGGLE, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(gpio.command(GPIO_TOGGLE, 0, 0).is_success(),);\n    assert!(gpio.get_gpio_state(0).unwrap().value);\n    assert!(gpio.command(GPIO_TOGGLE, 0, 0).is_success(),);\n    assert!(!gpio.get_gpio_state(0).unwrap().value);\n\n    // Enable Input\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_INPUT, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_INPUT, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_INPUT, 0, 3).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n\n    assert!(gpio.command(GPIO_ENABLE_INPUT, 0, 0).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().mode,\n        GpioMode::Input(PullMode::PullNone)\n    );\n\n    assert!(gpio.command(GPIO_ENABLE_INPUT, 0, 1).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().mode,\n        GpioMode::Input(PullMode::PullUp)\n    );\n\n    assert!(gpio.command(GPIO_ENABLE_INPUT, 0, 2).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().mode,\n        GpioMode::Input(PullMode::PullDown)\n    );\n\n    // Gpio Read\n    assert_eq!(\n        gpio.command(GPIO_READ_INPUT, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_READ_INPUT, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert_eq!(gpio.set_value(0, true), Ok(()));\n    assert_eq!(\n        gpio.command(GPIO_READ_INPUT, 0, 0).get_success_u32(),\n        Some(1)\n    );\n    assert_eq!(gpio.set_value(0, false), Ok(()));\n    assert_eq!(\n        gpio.command(GPIO_READ_INPUT, 0, 0).get_success_u32(),\n        Some(0)\n    );\n\n    // Enable Interrupts\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_INTERRUPTS, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_INTERRUPTS, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert_eq!(\n        gpio.command(GPIO_ENABLE_INTERRUPTS, 0, 3).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n\n    assert!(gpio.command(GPIO_ENABLE_INTERRUPTS, 0, 0).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().interrupt_enabled,\n        Some(InterruptEdge::Either)\n    );\n\n    assert!(gpio.command(GPIO_ENABLE_INTERRUPTS, 0, 1).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().interrupt_enabled,\n        Some(InterruptEdge::Rising)\n    );\n\n    assert!(gpio.command(GPIO_ENABLE_INTERRUPTS, 0, 2).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().interrupt_enabled,\n        Some(InterruptEdge::Falling)\n    );\n\n    // Disable Interrupts\n    assert_eq!(\n        gpio.command(GPIO_DISABLE_INTERRUPTS, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_DISABLE_INTERRUPTS, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert!(gpio.command(GPIO_DISABLE_INTERRUPTS, 0, 0).is_success());\n    assert_eq!(gpio.get_gpio_state(0).unwrap().interrupt_enabled, None);\n\n    // Disable Pin\n    assert_eq!(\n        gpio.command(GPIO_DISABLE, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        gpio.command(GPIO_DISABLE, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert!(gpio.command(GPIO_DISABLE, 0, 0).is_success());\n    assert_eq!(gpio.get_gpio_state(0).unwrap().mode, GpioMode::Disable);\n}\n\n// Integration test that verifies Gpio works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let gpio = Gpio::<10>::new();\n    gpio.set_missing_gpio(1);\n    kernel.add_driver(&gpio);\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_COUNT, 1, 2).get_success_u32(),\n        Some(10)\n    );\n\n    // Enable Output\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_OUTPUT, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_OUTPUT, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_OUTPUT, 0, 0).is_success());\n\n    // Gpio Set\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_SET, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_SET, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_SET, 0, 0).is_success(),);\n    assert!(gpio.get_gpio_state(0).unwrap().value);\n\n    // Gpio Clear\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_CLEAR, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_CLEAR, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_CLEAR, 0, 0).is_success(),);\n    assert!(!gpio.get_gpio_state(0).unwrap().value);\n\n    // Gpio Toggle\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_TOGGLE, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_TOGGLE, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_TOGGLE, 0, 0).is_success(),);\n    assert!(gpio.get_gpio_state(0).unwrap().value);\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_TOGGLE, 0, 0).is_success(),);\n    assert!(!gpio.get_gpio_state(0).unwrap().value);\n\n    // Enable Input\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INPUT, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INPUT, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INPUT, 0, 3).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INPUT, 0, 0).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().mode,\n        GpioMode::Input(PullMode::PullNone)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INPUT, 0, 1).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().mode,\n        GpioMode::Input(PullMode::PullUp)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INPUT, 0, 2).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().mode,\n        GpioMode::Input(PullMode::PullDown)\n    );\n\n    // Gpio Read\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_READ_INPUT, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_READ_INPUT, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert_eq!(gpio.set_value(0, true), Ok(()));\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_READ_INPUT, 0, 0).get_success_u32(),\n        Some(1)\n    );\n    assert_eq!(gpio.set_value(0, false), Ok(()));\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_READ_INPUT, 0, 0).get_success_u32(),\n        Some(0)\n    );\n\n    // Enable Interrupts\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, 0, 3).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, 0, 0).is_success());\n    assert_eq!(\n        gpio.get_gpio_state(0).unwrap().interrupt_enabled,\n        Some(InterruptEdge::Either)\n    );\n\n    let listener = Cell::<Option<(u32, u32)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        assert_eq!(gpio.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        assert_eq!(gpio.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(gpio.set_value(0, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        assert_eq!(gpio.set_value(0, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, 0, 1).is_success());\n        assert_eq!(\n            gpio.get_gpio_state(0).unwrap().interrupt_enabled,\n            Some(InterruptEdge::Rising)\n        );\n\n        assert_eq!(gpio.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        assert_eq!(gpio.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(gpio.set_value(0, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_ENABLE_INTERRUPTS, 0, 2).is_success());\n        assert_eq!(\n            gpio.get_gpio_state(0).unwrap().interrupt_enabled,\n            Some(InterruptEdge::Falling)\n        );\n\n        assert_eq!(gpio.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(gpio.set_value(0, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        assert_eq!(gpio.set_value(0, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n\n    // Disable Interrupts\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_DISABLE_INTERRUPTS, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_DISABLE_INTERRUPTS, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_DISABLE_INTERRUPTS, 0, 0).is_success());\n    assert_eq!(gpio.get_gpio_state(0).unwrap().interrupt_enabled, None);\n\n    let listener = Cell::<Option<(u32, u32)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        assert_eq!(gpio.set_value(0, true), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert_eq!(gpio.set_value(0, false), Ok(()));\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n    });\n\n    // Disable Pin\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_DISABLE, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GPIO_DISABLE, 1, 0).get_failure(),\n        Some(ErrorCode::NoDevice)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, GPIO_DISABLE, 0, 0).is_success());\n    assert_eq!(gpio.get_gpio_state(0).unwrap().mode, GpioMode::Disable);\n}\n"
  },
  {
    "path": "unittest/src/fake/ieee802154/mod.rs",
    "content": "//! Fake implementation of the raw IEEE 802.15.4 API.\n\nuse core::cell::Cell;\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::{\n    cell::RefCell,\n    collections::VecDeque,\n    convert::TryFrom,\n    rc::{self, Rc},\n};\n\nuse crate::{command_return, DriverInfo, DriverShareRef, RoAllowBuffer, RwAllowBuffer};\n\n/// Maximum length of a MAC frame.\nconst MAX_MTU: usize = 127;\n\nconst PSDU_OFFSET: usize = 2;\n\n#[derive(Debug)]\n#[repr(C)]\npub struct Frame {\n    pub header_len: u8,\n    pub payload_len: u8,\n    pub mic_len: u8,\n    pub body: [u8; MAX_MTU],\n}\n\nimpl Frame {\n    pub fn with_body(body: &[u8]) -> Self {\n        let mut frame = Self {\n            header_len: 0,\n            payload_len: u8::try_from(body.len()).unwrap(),\n            mic_len: 0,\n            body: [0_u8; 127],\n        };\n\n        frame.body[PSDU_OFFSET..PSDU_OFFSET + body.len()].copy_from_slice(body);\n\n        frame\n    }\n}\n\n/// Fake IEEE 802.15.4 PHY driver implementation.\npub struct Ieee802154Phy {\n    pan: Cell<u16>,\n    addr_short: Cell<u16>,\n    addr_long: Cell<u64>,\n    chan: Cell<u8>,\n    tx_power: Cell<i8>,\n    radio_on: Cell<bool>,\n\n    tx_buf: Cell<RoAllowBuffer>,\n    rx_buf: RefCell<RwAllowBuffer>,\n\n    transmitted_frames: Cell<Vec<Vec<u8>>>,\n\n    frames_to_be_received: RefCell<VecDeque<Frame>>,\n\n    share_ref: DriverShareRef,\n}\n\n// Needed for scheduling an receive upcall immediately after subscribing to it.\n// Without that,\n\nthread_local!(pub(crate) static DRIVER: RefCell<rc::Weak<Ieee802154Phy>> = const { RefCell::new(rc::Weak::new()) });\n\nimpl Ieee802154Phy {\n    pub fn instance() -> Option<Rc<Self>> {\n        DRIVER.with_borrow(|driver| driver.upgrade())\n    }\n\n    pub fn new() -> Rc<Self> {\n        let new = Self::new_with_frames_to_be_received(std::iter::empty());\n        DRIVER.with_borrow_mut(|inner| *inner = Rc::downgrade(&new));\n        new\n    }\n\n    pub fn new_with_frames_to_be_received(\n        frames_to_be_received: impl IntoIterator<Item = Frame>,\n    ) -> Rc<Self> {\n        Rc::new(Self {\n            pan: Default::default(),\n            addr_short: Default::default(),\n            addr_long: Default::default(),\n            chan: Default::default(),\n            tx_power: Default::default(),\n            radio_on: Default::default(),\n            tx_buf: Default::default(),\n            rx_buf: Default::default(),\n            transmitted_frames: Default::default(),\n            frames_to_be_received: RefCell::new(frames_to_be_received.into_iter().collect()),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn take_transmitted_frames(&self) -> Vec<Vec<u8>> {\n        self.transmitted_frames.take()\n    }\n\n    pub fn has_pending_rx_frames(&self) -> bool {\n        let rx_buf = self.rx_buf.borrow();\n\n        #[allow(clippy::get_first)]\n        let read_index = rx_buf.get(0);\n        let write_index = rx_buf.get(1);\n\n        matches!((read_index, write_index), (Some(r), Some(w)) if r != w)\n    }\n\n    pub fn radio_receive_frame(&self, frame: Frame) {\n        self.frames_to_be_received.borrow_mut().push_back(frame);\n    }\n\n    pub fn driver_receive_pending_frames(&self) {\n        for frame in self.frames_to_be_received.borrow_mut().drain(..) {\n            self.driver_receive_frame(&frame.body[..frame.payload_len as usize + PSDU_OFFSET]);\n        }\n    }\n\n    fn driver_receive_frame(&self, frame: &[u8]) {\n        let mut rx_buf = self.rx_buf.borrow_mut();\n        Self::phy_driver_receive_frame(&mut rx_buf, frame);\n    }\n\n    // Code taken and adapted from capsules/extra/src/ieee802154/phy_driver.rs.\n    fn phy_driver_receive_frame(rbuf: &mut [u8], frame: &[u8]) {\n        let frame_len = frame.len() - PSDU_OFFSET;\n\n        ////////////////////////////////////////////////////////\n        // NOTE: context for the ring buffer and assumptions\n        // regarding the ring buffer format and usage can be\n        // found in the detailed comment at the top of this\n        // file.\n        //\n        // Ring buffer format:\n        //  | read  | write | user_frame | user_frame |...| user_frame |\n        //  | index | index | 0          | 1          |   | n          |\n        //\n        // user_frame format:\n        //  | header_len | payload_len | mic_len | 15.4 frame |\n        //\n        ////////////////////////////////////////////////////////\n\n        const PSDU_OFFSET: usize = 2;\n\n        // 2 bytes for the readwrite buffer metadata (read and\n        // write index).\n        const RING_BUF_METADATA_SIZE: usize = 2;\n\n        /// 3 byte metadata (offset, len, mic_len)\n        const USER_FRAME_METADATA_SIZE: usize = 3;\n\n        /// 3 byte metadata + 127 byte max payload\n        const USER_FRAME_MAX_SIZE: usize = USER_FRAME_METADATA_SIZE + MAX_MTU;\n\n        // Confirm the availability of the buffer. A buffer of\n        // len 0 is indicative of the userprocess not allocating\n        // a readwrite buffer. We must also confirm that the\n        // userprocess correctly formatted the buffer to be of\n        // length 2 + n * USER_FRAME_MAX_SIZE, where n is the\n        // number of user frames that the buffer can store. We\n        // combine checking the buffer's non-zero length and the\n        // case of the buffer being shorter than the\n        // `RING_BUF_METADATA_SIZE` as an invalid buffer (e.g.\n        // of length 1) may otherwise errantly pass the second\n        // conditional check (due to unsigned integer\n        // arithmetic).\n        assert!(rbuf.len() > RING_BUF_METADATA_SIZE);\n        assert!((rbuf.len() - RING_BUF_METADATA_SIZE) % USER_FRAME_MAX_SIZE == 0);\n\n        let mut read_index = rbuf[0] as usize;\n        let mut write_index = rbuf[1] as usize;\n\n        let max_pending_rx = (rbuf.len() - RING_BUF_METADATA_SIZE) / USER_FRAME_MAX_SIZE;\n\n        // Confirm user modifiable metadata is valid (i.e.\n        // within bounds of the provided buffer).\n        assert!(read_index < max_pending_rx && write_index < max_pending_rx);\n\n        // We don't parse the received packet, so we don't know\n        // how long all of the pieces are.\n        let mic_len = 0;\n        let header_len = 0;\n\n        // Start in the buffer where we are going to write this\n        // incoming packet.\n        let offset = RING_BUF_METADATA_SIZE + (write_index * USER_FRAME_MAX_SIZE);\n\n        // Copy the entire frame over to userland, preceded by\n        // three metadata bytes: the header length, the data\n        // length, and the MIC length.\n        let dst_start = offset + USER_FRAME_METADATA_SIZE;\n        let dst_end = dst_start + frame_len;\n        let src_start = PSDU_OFFSET;\n        let src_end = src_start + frame_len;\n        rbuf[dst_start..dst_end].copy_from_slice(&frame[src_start..src_end]);\n\n        rbuf[offset] = header_len as u8;\n        rbuf[offset + 1] = frame_len as u8;\n        rbuf[offset + 2] = mic_len as u8;\n\n        // Prepare the ring buffer for the next write. The\n        // current design favors newness; newly received packets\n        // will begin to overwrite the oldest data in the event\n        // of the buffer becoming full. The read index must\n        // always point to the \"oldest\" data. If we have\n        // overwritten the oldest data, the next oldest data is\n        // now at the read index + 1. We must update the read\n        // index to reflect this.\n        write_index = (write_index + 1) % max_pending_rx;\n        if write_index == read_index {\n            read_index = (read_index + 1) % max_pending_rx;\n            rbuf[0] = read_index as u8;\n        }\n\n        // Update write index metadata since we have added a\n        // frame.\n        rbuf[1] = write_index as u8;\n    }\n\n    pub fn trigger_rx_upcall(&self) {\n        self.share_ref\n            .schedule_upcall(subscribe::FRAME_RECEIVED, (0, 0, 0))\n            .expect(\"Unable to schedule upcall {}\");\n    }\n}\n\nimpl crate::fake::SyscallDriver for Ieee802154Phy {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(2)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_number: u32, argument0: u32, argument1: u32) -> CommandReturn {\n        match command_number {\n            command::EXISTS => command_return::success(),\n            command::STATUS => {\n                if self.radio_on.get() {\n                    command_return::success()\n                } else {\n                    command_return::failure(ErrorCode::Off)\n                }\n            }\n            command::SET_SHORT_ADDR => {\n                self.addr_short.set(u16::try_from(argument0).unwrap());\n                command_return::success()\n            }\n            command::SET_PAN => {\n                self.pan.set(u16::try_from(argument0).unwrap());\n                command_return::success()\n            }\n            command::SET_CHAN => {\n                self.chan.set(u8::try_from(argument0).unwrap());\n                command_return::success()\n            }\n            command::SET_TX_PWR => {\n                self.tx_power.set(i8::try_from(argument0 as i32).unwrap());\n                command_return::success()\n            }\n            command::COMMIT_CFG => command_return::success(),\n            command::GET_SHORT_ADDR => command_return::success_u32(self.addr_short.get() as u32),\n            command::GET_PAN => command_return::success_u32(self.pan.get() as u32),\n            command::GET_CHAN => command_return::success_u32(self.chan.get() as u32),\n            command::GET_TX_PWR => command_return::success_u32(self.tx_power.get() as i32 as u32),\n            command::SET_LONG_ADDR => {\n                self.addr_long\n                    .set(argument0 as u64 | (argument1 as u64) << 32);\n                command_return::success()\n            }\n            command::GET_LONG_ADDR => command_return::success_u64(self.addr_long.get()),\n            command::TURN_ON => {\n                self.radio_on.set(true);\n                command_return::success()\n            }\n            command::TURN_OFF => {\n                self.radio_on.set(false);\n                command_return::success()\n            }\n            command::TRANSMIT => {\n                let mut transmitted_frames = self.transmitted_frames.take();\n                let tx_buf = self.tx_buf.take();\n                transmitted_frames.push(Vec::from(tx_buf.as_ref()));\n\n                self.tx_buf.set(tx_buf);\n                self.transmitted_frames.set(transmitted_frames);\n                self.share_ref\n                    .schedule_upcall(subscribe::FRAME_TRANSMITTED, (2137, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n\n                command_return::success()\n            }\n            _ => command_return::failure(ErrorCode::Invalid),\n        }\n    }\n\n    fn allow_readonly(\n        &self,\n        buffer_num: u32,\n        buffer: crate::RoAllowBuffer,\n    ) -> Result<crate::RoAllowBuffer, (crate::RoAllowBuffer, ErrorCode)> {\n        if buffer_num == allow_ro::WRITE {\n            Ok(self.tx_buf.replace(buffer))\n        } else {\n            Err((buffer, ErrorCode::Invalid))\n        }\n    }\n\n    fn allow_readwrite(\n        &self,\n        buffer_num: u32,\n        buffer: crate::RwAllowBuffer,\n    ) -> Result<crate::RwAllowBuffer, (crate::RwAllowBuffer, ErrorCode)> {\n        if buffer_num == allow_rw::READ {\n            Ok(self.rx_buf.replace(buffer))\n        } else {\n            Err((buffer, ErrorCode::Invalid))\n        }\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x30001;\n\n// Command IDs\n/// - `0`: Driver existence check.\n/// - `1`: Return radio status. Ok(())/OFF = on/off.\n/// - `2`: Set short address.\n/// - `4`: Set PAN ID.\n/// - `5`: Set channel.\n/// - `6`: Set transmission power.\n/// - `7`: Commit any configuration changes.\n/// - `8`: Get the short MAC address.\n/// - `10`: Get the PAN ID.\n/// - `11`: Get the channel.\n/// - `12`: Get the transmission power.\n/// - `27`: Transmit a frame. The frame must be stored in the write RO allow\n///   buffer 0. The allowed buffer must be the length of the frame. The\n///   frame includes the PDSU (i.e., the MAC payload) _without_ the MFR\n///   (i.e., CRC) bytes.\n/// - `28`: Set long address.\n/// - `29`: Get the long MAC address.\n/// - `30`: Turn the radio on.\n/// - `31`: Turn the radio off.\nmod command {\n    pub const EXISTS: u32 = 0;\n    pub const STATUS: u32 = 1;\n    pub const SET_SHORT_ADDR: u32 = 2;\n    pub const SET_PAN: u32 = 4;\n    pub const SET_CHAN: u32 = 5;\n    pub const SET_TX_PWR: u32 = 6;\n    pub const COMMIT_CFG: u32 = 7;\n    pub const GET_SHORT_ADDR: u32 = 8;\n    pub const GET_PAN: u32 = 10;\n    pub const GET_CHAN: u32 = 11;\n    pub const GET_TX_PWR: u32 = 12;\n    pub const TRANSMIT: u32 = 27;\n    pub const SET_LONG_ADDR: u32 = 28;\n    pub const GET_LONG_ADDR: u32 = 29;\n    pub const TURN_ON: u32 = 30;\n    pub const TURN_OFF: u32 = 31;\n}\n\nmod subscribe {\n    /// Frame is received\n    pub const FRAME_RECEIVED: u32 = 0;\n    /// Frame is transmitted\n    pub const FRAME_TRANSMITTED: u32 = 1;\n}\n\n/// Ids for read-only allow buffers\nmod allow_ro {\n    /// Write buffer. Contains the frame payload to be transmitted.\n    pub const WRITE: u32 = 0;\n}\n\n/// Ids for read-write allow buffers\nmod allow_rw {\n    /// Read buffer. Will contain the received frame.\n    pub const READ: u32 = 0;\n}\n"
  },
  {
    "path": "unittest/src/fake/kernel.rs",
    "content": "use crate::kernel_data::{with_kernel_data, DriverData, KernelData, KERNEL_DATA};\nuse crate::{DriverShareRef, ExpectedSyscall, SyscallLogEntry};\nuse std::cell::Cell;\n\n/// A fake implementation of the Tock kernel. Used with `fake::Syscalls`, which\n/// provides system calls that are routed to this kernel. `fake::SyscallDriver`s\n/// may be attached to a `fake::Kernel`, and the `fake::Kernel` will route\n/// system calls to the correct fake driver.\n///\n/// Note that there can only be one `fake::Kernel` instance per thread, as\n/// `fake::Syscalls` uses a thread-local variable to locate the `fake::Kernel`.\n// Note: The kernel's data is actually stored in\n// crate::kernel_data::KERNEL_DATA. See the kernel_data module comment for an\n// explanation.\npub struct Kernel {\n    // Prevents user code from constructing a Kernel directly, in order to force\n    // construction via new().\n    _private: (),\n}\n\nimpl Kernel {\n    /// Creates a `Kernel` for this thread and returns it. The returned `Kernel`\n    /// should be dropped at the end of the test, before this thread creates\n    /// another `Kernel`.\n    // Clippy suggests we implement Default instead of having new. However,\n    // using Default implies the newly-created instance isn't special, but it is\n    // (as only one can exist per thread). Also, Default::default is not\n    // #[track_caller].\n    #[allow(clippy::new_without_default)]\n    #[track_caller]\n    pub fn new() -> Kernel {\n        let old_option = KERNEL_DATA.with(|kernel_data| {\n            kernel_data.replace(Some(KernelData {\n                allow_db: Default::default(),\n                create_location: std::panic::Location::caller(),\n                drivers: Default::default(),\n                expected_syscalls: Default::default(),\n                syscall_log: Vec::new(),\n                upcall_queue: Default::default(),\n                memory_break: core::ptr::null(),\n            }))\n        });\n        if let Some(old_kernel_data) = old_option {\n            panic!(\n                \"New fake::Kernel created before the previous fake::Kernel \\\n                 was dropped. The previous fake::Kernel was created at {}.\",\n                old_kernel_data.create_location\n            );\n        }\n        Kernel { _private: () }\n    }\n\n    /// Adds a `fake::SyscallDriver` to this `fake::Kernel`. After the call,\n    /// system calls with this driver's ID will be routed to the driver.\n    // TODO: It's kind of weird to implicitly clone the RC by default. Instead,\n    // we should probably take the Rc by value. Also, after making that change,\n    // maybe we can take a Rc<dyn fake::SyscallDriver> instead of using\n    // generics?\n    // TODO: Add a test for add_driver.\n    pub fn add_driver<D: crate::fake::SyscallDriver>(&self, driver: &std::rc::Rc<D>) {\n        let info = driver.info();\n        let driver_data = DriverData {\n            driver: driver.clone(),\n            num_upcalls: info.upcall_count,\n            upcalls: std::collections::HashMap::with_capacity(info.upcall_count as usize),\n        };\n        let insert_return = with_kernel_data(|kernel_data| {\n            kernel_data\n                .unwrap()\n                .drivers\n                .insert(info.driver_num, driver_data)\n        });\n        assert!(\n            insert_return.is_none(),\n            \"Duplicate driver with number {}\",\n            info.driver_num\n        );\n        driver.register(DriverShareRef {\n            driver_num: Cell::new(info.driver_num),\n        });\n    }\n\n    /// Adds an ExpectedSyscall to the expected syscall queue.\n    ///\n    /// # What is the expected syscall queue?\n    ///\n    /// In addition to routing system calls to drivers, `Kernel` supports\n    /// injecting artificial system call responses. The primary use case for\n    /// this feature is to simulate errors without having to implement error\n    /// simulation in each `fake::SyscallDriver`.\n    ///\n    /// The expected syscall queue is a FIFO queue containing anticipated\n    /// upcoming system calls. It starts empty, and as long as it is empty, the\n    /// expected syscall functionality does nothing. When the queue is nonempty\n    /// and a system call is made, the system call is compared with the next\n    /// queue entry. If the system call matches, then the action defined by the\n    /// expected syscall is taken. If the call does not match, the call panics\n    /// (to make the unit test fail).\n    pub fn add_expected_syscall(&self, expected_syscall: ExpectedSyscall) {\n        with_kernel_data(|kernel_data| {\n            kernel_data\n                .unwrap()\n                .expected_syscalls\n                .push_back(expected_syscall)\n        });\n    }\n\n    /// Returns the system call log and empties it.\n    pub fn take_syscall_log(&self) -> Vec<SyscallLogEntry> {\n        with_kernel_data(|kernel_data| std::mem::take(&mut kernel_data.unwrap().syscall_log))\n    }\n\n    /// Returns true if the specified driver installed.\n    pub fn is_driver_present(driver_num: u32) -> bool {\n        with_kernel_data(|kernel_data| {\n            kernel_data.is_some_and(|kernel| kernel.drivers.contains_key(&driver_num))\n        })\n    }\n\n    /// Returns true if there are any pending upcalls.\n    pub fn is_upcall_pending() -> bool {\n        with_kernel_data(|kernel_data| {\n            kernel_data.is_some_and(|kernel| !kernel.upcall_queue.is_empty())\n        })\n    }\n}\n\nimpl Drop for Kernel {\n    fn drop(&mut self) {\n        KERNEL_DATA.with(|kernel_data| kernel_data.replace(None));\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/kernel_tests.rs",
    "content": "use crate::kernel_data::with_kernel_data;\nuse crate::{fake, ExpectedSyscall, SyscallLogEntry};\n\n#[test]\nfn expected_syscall_queue() {\n    use libtock_platform::YieldNoWaitReturn::Upcall;\n    use std::matches;\n    use ExpectedSyscall::YieldNoWait;\n    let kernel = fake::Kernel::new();\n    with_kernel_data(|kernel_data| assert!(kernel_data.unwrap().expected_syscalls.is_empty()));\n    kernel.add_expected_syscall(YieldNoWait {\n        override_return: None,\n    });\n    kernel.add_expected_syscall(YieldNoWait {\n        override_return: Some(Upcall),\n    });\n    with_kernel_data(|kernel_data| {\n        let expected_syscalls = &mut kernel_data.unwrap().expected_syscalls;\n        assert!(matches!(\n            expected_syscalls.pop_front(),\n            Some(YieldNoWait {\n                override_return: None\n            })\n        ));\n        assert!(matches!(\n            expected_syscalls.pop_front(),\n            Some(YieldNoWait {\n                override_return: Some(Upcall)\n            })\n        ));\n        assert!(expected_syscalls.is_empty());\n    });\n}\n\n#[test]\nfn syscall_log() {\n    use SyscallLogEntry::{YieldNoWait, YieldWait};\n    let kernel = fake::Kernel::new();\n    assert_eq!(kernel.take_syscall_log(), []);\n    with_kernel_data(|kernel_data| {\n        let syscall_log = &mut kernel_data.unwrap().syscall_log;\n        syscall_log.push(YieldNoWait);\n        syscall_log.push(YieldWait);\n    });\n    assert_eq!(kernel.take_syscall_log(), [YieldNoWait, YieldWait]);\n    assert_eq!(kernel.take_syscall_log(), []);\n}\n"
  },
  {
    "path": "unittest/src/fake/key_value/mod.rs",
    "content": "use libtock_platform::{CommandReturn, ErrorCode};\n\nuse core::cell::{Cell, RefCell};\nuse std::collections::HashMap;\nuse std::str;\n\nuse crate::{DriverInfo, DriverShareRef, RoAllowBuffer, RwAllowBuffer};\n\npub struct KeyValue {\n    buffer_in_key: Cell<RoAllowBuffer>,\n    buffer_in_val: Cell<RoAllowBuffer>,\n\n    buffer_out_val: RefCell<RwAllowBuffer>,\n\n    share_ref: DriverShareRef,\n\n    database: RefCell<HashMap<String, String>>,\n}\n\nimpl KeyValue {\n    pub fn new() -> std::rc::Rc<KeyValue> {\n        std::rc::Rc::new(KeyValue {\n            buffer_in_key: Default::default(),\n            buffer_in_val: Default::default(),\n            buffer_out_val: Default::default(),\n\n            share_ref: Default::default(),\n\n            database: Default::default(),\n        })\n    }\n}\n\nimpl crate::fake::SyscallDriver for KeyValue {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn allow_readonly(\n        &self,\n        buffer_num: u32,\n        buffer: RoAllowBuffer,\n    ) -> Result<RoAllowBuffer, (RoAllowBuffer, ErrorCode)> {\n        match buffer_num {\n            RO_ALLOW_KEY => Ok(self.buffer_in_key.replace(buffer)),\n            RO_ALLOW_VAL => Ok(self.buffer_in_val.replace(buffer)),\n            _ => Err((buffer, ErrorCode::Invalid)),\n        }\n    }\n\n    fn allow_readwrite(\n        &self,\n        buffer_num: u32,\n        buffer: RwAllowBuffer,\n    ) -> Result<RwAllowBuffer, (RwAllowBuffer, ErrorCode)> {\n        match buffer_num {\n            RW_ALLOW_VAL => Ok(self.buffer_out_val.replace(buffer)),\n            _ => Err((buffer, ErrorCode::Invalid)),\n        }\n    }\n\n    fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_id {\n            CMD_DRIVER_CHECK => crate::command_return::success(),\n            CMD_GET => {\n                let k = self.buffer_in_key.take();\n                let k_str = str::from_utf8(&k).unwrap();\n\n                let db = self.database.take();\n                match db.get(k_str) {\n                    Some(val) => {\n                        let cp_len = core::cmp::min(self.buffer_out_val.borrow().len(), val.len());\n                        self.buffer_out_val.borrow_mut()[..cp_len]\n                            .copy_from_slice(&val.as_bytes()[..cp_len]);\n\n                        self.share_ref\n                            .schedule_upcall(SUB_CALLBACK, (0, val.len() as u32, 0))\n                            .expect(\"Unable to schedule upcall {}\");\n                    }\n                    _ => {\n                        self.share_ref\n                            .schedule_upcall(SUB_CALLBACK, (ErrorCode::NoSupport as u32, 0, 0))\n                            .expect(\"Unable to schedule upcall {}\");\n                    }\n                }\n                self.buffer_in_key.set(k);\n                self.database.replace(db);\n\n                crate::command_return::success()\n            }\n            CMD_SET => {\n                let k = self.buffer_in_key.take();\n                let k_str = str::from_utf8(&k).unwrap();\n                let v = self.buffer_in_val.take();\n                let v_str = str::from_utf8(&v).unwrap();\n\n                let mut db = self.database.take();\n                db.insert(k_str.to_string(), v_str.to_string());\n\n                self.buffer_in_key.set(k);\n                self.buffer_in_val.set(v);\n                self.database.replace(db);\n\n                self.share_ref\n                    .schedule_upcall(SUB_CALLBACK, (0, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n\n                crate::command_return::success()\n            }\n            CMD_ADD => {\n                let k = self.buffer_in_key.take();\n                let k_str = str::from_utf8(&k).unwrap();\n                let v = self.buffer_in_val.take();\n                let v_str = str::from_utf8(&v).unwrap();\n\n                let mut db = self.database.take();\n\n                let mut found = false;\n                if let Some(_val) = db.get(k_str) {\n                    self.share_ref\n                        .schedule_upcall(SUB_CALLBACK, (ErrorCode::NoSupport as u32, 0, 0))\n                        .expect(\"Unable to schedule upcall {}\");\n                    found = true;\n                }\n\n                if !found {\n                    db.insert(k_str.to_string(), v_str.to_string());\n\n                    self.share_ref\n                        .schedule_upcall(SUB_CALLBACK, (0, 0, 0))\n                        .expect(\"Unable to schedule upcall {}\");\n                }\n\n                self.buffer_in_key.set(k);\n                self.buffer_in_val.set(v);\n                self.database.replace(db);\n\n                crate::command_return::success()\n            }\n            CMD_UPDATE => {\n                let k = self.buffer_in_key.take();\n                let k_str = str::from_utf8(&k).unwrap();\n                let v = self.buffer_in_val.take();\n                let v_str = str::from_utf8(&v).unwrap();\n\n                let mut db = self.database.take();\n\n                let mut found = false;\n                match db.get(k_str) {\n                    Some(_val) => {\n                        found = true;\n                    }\n                    _ => {\n                        self.share_ref\n                            .schedule_upcall(SUB_CALLBACK, (ErrorCode::NoSupport as u32, 0, 0))\n                            .expect(\"Unable to schedule upcall {}\");\n                    }\n                }\n\n                if found {\n                    db.insert(k_str.to_string(), v_str.to_string());\n\n                    self.share_ref\n                        .schedule_upcall(SUB_CALLBACK, (0, 0, 0))\n                        .expect(\"Unable to schedule upcall {}\");\n                }\n\n                self.buffer_in_key.set(k);\n                self.buffer_in_val.set(v);\n                self.database.replace(db);\n\n                crate::command_return::success()\n            }\n            CMD_DELETE => {\n                let k = self.buffer_in_key.take();\n                let k_str = str::from_utf8(&k).unwrap();\n\n                let mut db = self.database.take();\n\n                match db.remove(k_str) {\n                    Some(_val) => {\n                        self.share_ref\n                            .schedule_upcall(SUB_CALLBACK, (0, 0, 0))\n                            .expect(\"Unable to schedule upcall {}\");\n                    }\n                    _ => {\n                        self.share_ref\n                            .schedule_upcall(SUB_CALLBACK, (ErrorCode::NoSupport as u32, 0, 0))\n                            .expect(\"Unable to schedule upcall {}\");\n                    }\n                }\n\n                self.buffer_in_key.set(k);\n                self.database.replace(db);\n\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x50003;\n\n// Command IDs\n\nconst CMD_DRIVER_CHECK: u32 = 0;\nconst CMD_GET: u32 = 1;\nconst CMD_SET: u32 = 2;\nconst CMD_DELETE: u32 = 3;\nconst CMD_ADD: u32 = 4;\nconst CMD_UPDATE: u32 = 5;\n\nconst RO_ALLOW_KEY: u32 = 0;\nconst RO_ALLOW_VAL: u32 = 1;\nconst RW_ALLOW_VAL: u32 = 0;\n\nconst SUB_CALLBACK: u32 = 0;\n"
  },
  {
    "path": "unittest/src/fake/leds/mod.rs",
    "content": "//! Fake implementation of the LEDs API, documented here:\n//! https://github.com/tock/tock/blob/master/doc/syscalls/00002_leds.md\n//!\n//! Like the real API, `Leds` controls a set of fake LEDs. It provides\n//! a function `get_led` used to retrieve the state of an LED.\n\nuse crate::DriverInfo;\nuse core::cell::Cell;\nuse libtock_platform::{CommandReturn, ErrorCode};\n\npub struct Leds<const LEDS_COUNT: usize> {\n    leds: [Cell<bool>; LEDS_COUNT],\n}\n\nimpl<const LEDS_COUNT: usize> Leds<LEDS_COUNT> {\n    pub fn new() -> std::rc::Rc<Leds<LEDS_COUNT>> {\n        #[allow(clippy::declare_interior_mutable_const)]\n        const OFF: Cell<bool> = Cell::new(false);\n        std::rc::Rc::new(Leds {\n            leds: [OFF; LEDS_COUNT],\n        })\n    }\n\n    pub fn get_led(&self, led: u32) -> Option<bool> {\n        self.leds.get(led as usize).map(|led| led.get())\n    }\n}\n\nimpl<const LEDS_COUNT: usize> crate::fake::SyscallDriver for Leds<LEDS_COUNT> {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM)\n    }\n\n    fn command(&self, command_num: u32, argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_num {\n            EXISTS => crate::command_return::success_u32(LEDS_COUNT as u32),\n            LED_ON => {\n                if argument0 < LEDS_COUNT as u32 {\n                    self.leds[argument0 as usize].set(true);\n                    crate::command_return::success()\n                } else {\n                    crate::command_return::failure(ErrorCode::Invalid)\n                }\n            }\n            LED_OFF => {\n                if argument0 < LEDS_COUNT as u32 {\n                    self.leds[argument0 as usize].set(false);\n                    crate::command_return::success()\n                } else {\n                    crate::command_return::failure(ErrorCode::Invalid)\n                }\n            }\n            LED_TOGGLE => {\n                if argument0 < LEDS_COUNT as u32 {\n                    self.leds[argument0 as usize].set(!self.leds[argument0 as usize].get());\n                    crate::command_return::success()\n                } else {\n                    crate::command_return::failure(ErrorCode::Invalid)\n                }\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Implementation details below\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x2;\n\n// Command numbers\nconst EXISTS: u32 = 0;\nconst LED_ON: u32 = 1;\nconst LED_OFF: u32 = 2;\nconst LED_TOGGLE: u32 = 3;\n"
  },
  {
    "path": "unittest/src/fake/leds/tests.rs",
    "content": "use crate::fake;\nuse fake::leds::*;\nuse libtock_platform::ErrorCode;\n\n// Tests the command implementation.\n#[test]\nfn command() {\n    use fake::SyscallDriver;\n    let leds = Leds::<10>::new();\n    let value = leds.command(EXISTS, 1, 2);\n    assert_eq!(value.get_success_u32(), Some(10));\n    assert_eq!(\n        leds.command(LED_ON, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(leds.get_led(0), Some(false));\n    assert!(leds.command(LED_ON, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(true));\n    assert!(leds.command(LED_OFF, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(false));\n    assert!(leds.command(LED_TOGGLE, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(true));\n    assert!(leds.command(LED_TOGGLE, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(false));\n}\n\n// Integration test that verifies Leds works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let leds = Leds::<10>::new();\n    kernel.add_driver(&leds);\n    let value = fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2);\n    assert!(value.is_success_u32());\n    assert_eq!(value.get_success_u32(), Some(10));\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, LED_ON, 11, 0).get_failure(),\n        Some(ErrorCode::Invalid)\n    );\n    assert_eq!(leds.get_led(0), Some(false));\n    assert!(fake::Syscalls::command(DRIVER_NUM, LED_ON, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(true));\n    assert!(fake::Syscalls::command(DRIVER_NUM, LED_OFF, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(false));\n    assert!(fake::Syscalls::command(DRIVER_NUM, LED_TOGGLE, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(true));\n    assert!(fake::Syscalls::command(DRIVER_NUM, LED_TOGGLE, 0, 0).is_success());\n    assert_eq!(leds.get_led(0), Some(false));\n}\n"
  },
  {
    "path": "unittest/src/fake/low_level_debug/mod.rs",
    "content": "//! Fake implementation of the LowLevelDebug API, documented here:\n//! https://github.com/tock/tock/blob/master/doc/syscalls/00008_low_level_debug.md\n//!\n//! Like the real API, `LowLevelDebug` prints each message it is commanded to\n//! print. It also keeps a log of the messages as `Message` instances, which can\n//! be retrieved via `take_messages` for use in unit tests.\n\nuse crate::DriverInfo;\nuse libtock_platform::{CommandReturn, ErrorCode};\n\npub struct LowLevelDebug {\n    messages: core::cell::Cell<Vec<Message>>,\n}\n\nimpl LowLevelDebug {\n    pub fn new() -> std::rc::Rc<LowLevelDebug> {\n        std::rc::Rc::new(LowLevelDebug {\n            messages: Default::default(),\n        })\n    }\n\n    /// Returns the messages that have been printed, and clears the message\n    /// queue.\n    pub fn take_messages(&self) -> Vec<Message> {\n        self.messages.take()\n    }\n}\n\nimpl crate::fake::SyscallDriver for LowLevelDebug {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM)\n    }\n\n    fn command(&self, command_num: u32, argument0: u32, argument1: u32) -> CommandReturn {\n        match command_num {\n            EXISTS => {}\n            PRINT_ALERT_CODE => self.handle_message(Message::AlertCode(argument0)),\n            PRINT_1 => self.handle_message(Message::Print1(argument0)),\n            PRINT_2 => self.handle_message(Message::Print2(argument0, argument1)),\n            _ => return crate::command_return::failure(ErrorCode::NoSupport),\n        }\n        crate::command_return::success()\n    }\n}\n\n#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub enum Message {\n    AlertCode(u32),\n    Print1(u32),\n    Print2(u32, u32),\n}\n\nimpl core::fmt::Display for Message {\n    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {\n        match *self {\n            Message::AlertCode(code) => {\n                write!(f, \"alert code 0x{:x} ({})\", code, alert_description(code))\n            }\n            Message::Print1(arg0) => write!(f, \"prints 0x{arg0:x}\"),\n            Message::Print2(arg0, arg1) => write!(f, \"prints 0x{arg0:x} 0x{arg1:x}\"),\n        }\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Implementation details below\n// -----------------------------------------------------------------------------\n\n#[cfg(test)]\nmod tests;\n\nconst DRIVER_NUM: u32 = 0x8;\n\n// Command numbers\nconst EXISTS: u32 = 0;\nconst PRINT_ALERT_CODE: u32 = 1;\nconst PRINT_1: u32 = 2;\nconst PRINT_2: u32 = 3;\n\n// Predefined alert codes\nconst PANIC: u32 = 0x01;\nconst WRONG_LOCATION: u32 = 0x02;\n\nimpl LowLevelDebug {\n    fn handle_message(&self, message: Message) {\n        // Format the message the same way as the real LowLevelDebug.\n        // `libtock_unittest` doesn't support multiple processes, so we pretend\n        // this is the first process (number 0).\n        println!(\"LowLevelDebug: App 0x0 {message}\");\n        let mut messages = self.messages.take();\n        messages.push(message);\n        self.messages.set(messages);\n    }\n}\n\n// Returns a description of a predefined alert code.\nfn alert_description(code: u32) -> &'static str {\n    match code {\n        PANIC => \"panic\",\n        WRONG_LOCATION => \"wrong location\",\n        _ => \"unknown\",\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/low_level_debug/tests.rs",
    "content": "use crate::fake;\nuse fake::low_level_debug::*;\n\n// Tests the command implementation.\n#[test]\nfn command() {\n    use fake::SyscallDriver;\n    let low_level_debug = LowLevelDebug::new();\n    assert!(low_level_debug.command(EXISTS, 1, 2).is_success());\n    assert!(low_level_debug.command(PRINT_ALERT_CODE, 3, 4).is_success());\n    assert_eq!(low_level_debug.take_messages(), [Message::AlertCode(3)]);\n    assert!(low_level_debug.command(PRINT_1, 5, 6).is_success());\n    assert!(low_level_debug.command(PRINT_2, 7, 8).is_success());\n    assert_eq!(\n        low_level_debug.take_messages(),\n        [Message::Print1(5), Message::Print2(7, 8)]\n    );\n}\n\n// Integration test that verifies LowLevelDebug works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let low_level_debug = LowLevelDebug::new();\n    kernel.add_driver(&low_level_debug);\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, PRINT_ALERT_CODE, 3, 4).is_success());\n    assert_eq!(low_level_debug.take_messages(), [Message::AlertCode(3)]);\n    assert!(fake::Syscalls::command(DRIVER_NUM, PRINT_1, 5, 6).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, PRINT_2, 7, 8).is_success());\n    assert_eq!(\n        low_level_debug.take_messages(),\n        [Message::Print1(5), Message::Print2(7, 8)]\n    );\n}\n\n// Tests the Display implementation on Message.\n#[test]\nfn message_display() {\n    use Message::*;\n    assert_eq!(format!(\"{}\", AlertCode(0x0)), \"alert code 0x0 (unknown)\");\n    assert_eq!(format!(\"{}\", AlertCode(0x1)), \"alert code 0x1 (panic)\");\n    assert_eq!(\n        format!(\"{}\", AlertCode(0x2)),\n        \"alert code 0x2 (wrong location)\"\n    );\n    assert_eq!(format!(\"{}\", AlertCode(0x3)), \"alert code 0x3 (unknown)\");\n    assert_eq!(format!(\"{}\", Print1(0x31)), \"prints 0x31\");\n    assert_eq!(format!(\"{}\", Print2(0x41, 0x59)), \"prints 0x41 0x59\");\n}\n"
  },
  {
    "path": "unittest/src/fake/mod.rs",
    "content": "//! `fake` contains fake implementations of Tock kernel components. Fake\n//! components emulate the behavior of the real Tock kernel components, but in\n//! the unit test environment. They generally have additional testing features,\n//! such as error injection functionality.\n//!\n//! These components are exposed under the `fake` module because otherwise their\n//! names would collide with the corresponding drivers (e.g. the fake Console\n//! would collide with the Console driver in unit tests). Tests should generally\n//! `use libtock_unittest::fake` and refer to the type with the `fake::` prefix\n//! (e.g. `fake::Console`).\n\nmod adc;\nmod air_quality;\nmod alarm;\nmod ambient_light;\nmod buttons;\nmod buzzer;\nmod console;\nmod gpio;\npub mod ieee802154;\nmod kernel;\nmod key_value;\nmod leds;\nmod low_level_debug;\nmod ninedof;\nmod proximity;\nmod screen;\nmod sound_pressure;\nmod syscall_driver;\nmod syscalls;\nmod temperature;\n\npub use adc::Adc;\npub use air_quality::AirQuality;\npub use alarm::Alarm;\npub use ambient_light::AmbientLight;\npub use buttons::Buttons;\npub use buzzer::Buzzer;\npub use console::Console;\npub use gpio::{Gpio, GpioMode, InterruptEdge, PullMode};\npub use ieee802154::Ieee802154Phy;\npub use kernel::Kernel;\npub use key_value::KeyValue;\npub use leds::Leds;\npub use low_level_debug::{LowLevelDebug, Message};\npub use ninedof::{NineDof, NineDofData};\npub use proximity::Proximity;\npub use screen::Screen;\npub use sound_pressure::SoundPressure;\npub use syscall_driver::SyscallDriver;\npub use syscalls::Syscalls;\npub use temperature::Temperature;\n\n#[cfg(test)]\nmod kernel_tests;\n"
  },
  {
    "path": "unittest/src/fake/ninedof/mod.rs",
    "content": "//! Fake implementation of the NineDof API, documented here:\n//!\n//! Like the real API, `NineDof` controls a fake 9dof sensor. It provides\n//! a function `set_value` used to immediately call an upcall with a 9dof value read by the sensor\n//! and a function 'set_value_sync' used to call the upcall when the read command is received.\n\nuse crate::{DriverInfo, DriverShareRef};\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::cell::Cell;\n\npub struct NineDof {\n    busy: Cell<bool>,\n    upcall_on_command: Cell<Option<NineDofData>>,\n    share_ref: DriverShareRef,\n}\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\npub struct NineDofData {\n    pub x: i32,\n    pub y: i32,\n    pub z: i32,\n}\n\nimpl NineDof {\n    pub fn new() -> std::rc::Rc<NineDof> {\n        std::rc::Rc::new(NineDof {\n            busy: Cell::new(false),\n            upcall_on_command: Cell::new(None),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn is_busy(&self) -> bool {\n        self.busy.get()\n    }\n    pub fn set_value(&self, value: NineDofData) {\n        if self.busy.get() {\n            self.share_ref\n                .schedule_upcall(0, (value.x as u32, value.y as u32, value.z as u32))\n                .expect(\"Unable to schedule upcall\");\n            self.busy.set(false);\n        }\n    }\n    pub fn set_value_sync(&self, value: NineDofData) {\n        self.upcall_on_command.set(Some(value));\n    }\n}\n\nimpl crate::fake::SyscallDriver for NineDof {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_id {\n            EXISTS => crate::command_return::success(),\n\n            READ_ACCELEROMETER => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_command.take() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            READ_MAGNETOMETER => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_command.take() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            READ_GYRO => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_command.take() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60004;\n\n// Command IDs\nconst EXISTS: u32 = 0;\nconst READ_ACCELEROMETER: u32 = 1;\nconst READ_MAGNETOMETER: u32 = 100;\nconst READ_GYRO: u32 = 200;\n"
  },
  {
    "path": "unittest/src/fake/ninedof/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::ninedof::*;\nuse libtock_platform::{share, DefaultConfig, YieldNoWaitReturn};\n\n//Test the command implementation\n#[test]\nfn command() {\n    let ninedof = NineDof::new();\n\n    assert!(ninedof.command(EXISTS, 1, 2).is_success());\n\n    assert!(ninedof.command(READ_ACCELEROMETER, 0, 0).is_success());\n\n    assert_eq!(\n        ninedof.command(READ_ACCELEROMETER, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    let payload: NineDofData = NineDofData { x: 1, y: 2, z: 3 };\n\n    ninedof.set_value(payload);\n    assert!(ninedof.command(READ_ACCELEROMETER, 0, 1).is_success());\n    ninedof.set_value(payload);\n\n    ninedof.set_value_sync(payload);\n    assert!(ninedof.command(READ_ACCELEROMETER, 0, 1).is_success());\n    assert!(ninedof.command(READ_ACCELEROMETER, 0, 1).is_success());\n}\n\n// Integration test that verifies NineDof works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let ninedof = NineDof::new();\n    kernel.add_driver(&ninedof);\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_ACCELEROMETER, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, READ_ACCELEROMETER, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    let payload: NineDofData = NineDofData { x: 1, y: 2, z: 3 };\n\n    ninedof.set_value(payload);\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_ACCELEROMETER, 0, 1).is_success());\n\n    let listener = Cell::<Option<(u32, u32, u32)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        ninedof.set_value(payload);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((1, 2, 3)));\n\n        ninedof.set_value(payload);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_ACCELEROMETER, 0, 1).is_success());\n        ninedof.set_value(payload);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((1, 2, 3)));\n    });\n}\n"
  },
  {
    "path": "unittest/src/fake/proximity/mod.rs",
    "content": "//! Fake implementation of the Proximity API.\n//!\n//! Like the real API, `Proximity` controls a fake proximity sensor.\n//! It provides a function `set_value` used to immediately simulate a sensor reading,\n//! and a function `set_value_sync` used to simulate a sensor reading when one\n//! of the read commands is received.\n\nuse std::cell::Cell;\n\nuse crate::{DriverInfo, DriverShareRef};\nuse libtock_platform::{CommandReturn, ErrorCode};\n\n#[derive(Clone, Copy, PartialEq, Eq)]\npub enum ProximityCommand {\n    ReadProximity = 1,\n    ReadProximityOnInterrupt = 2,\n    NoCommand = 3,\n}\n#[derive(Default, Clone, Copy)]\npub struct Thresholds {\n    lower: u8,\n    upper: u8,\n}\n\n// The `upcall_on_command` field is set to Some(value) if an upcall(with value as its argument) should be called when a read command is received,\n// or None otherwise. It was needed for testing `read_sync` library functions which simulates a synchronous sensor read,\n// because it was impossible to schedule an upcall during the `synchronous` read in other ways.\npub struct Proximity {\n    current_command: Cell<ProximityCommand>,\n    thresholds: Cell<Thresholds>,\n    upcall_on_command: Cell<Option<u8>>,\n    share_ref: DriverShareRef,\n}\n\nimpl Proximity {\n    pub fn new() -> std::rc::Rc<Proximity> {\n        std::rc::Rc::new(Proximity {\n            current_command: Cell::new(ProximityCommand::NoCommand),\n            thresholds: Cell::new(Thresholds { lower: 0, upper: 0 }),\n            upcall_on_command: Cell::new(None),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn set_value(&self, value: u8) {\n        //should not schedule an upcall if no reading was initiated or interrupt conditions are not true\n        match self.current_command.get() {\n            ProximityCommand::NoCommand => return,\n            ProximityCommand::ReadProximityOnInterrupt => {\n                if value >= self.thresholds.get().lower && value <= self.thresholds.get().upper {\n                    return;\n                }\n            }\n            ProximityCommand::ReadProximity => {}\n        }\n\n        self.share_ref\n            .schedule_upcall(0, (value as u32, 0, 0))\n            .expect(\"Unable to schedule upcall\");\n        self.current_command.set(ProximityCommand::NoCommand);\n        self.upcall_on_command.set(None);\n    }\n\n    pub fn set_value_sync(&self, value: u8) {\n        self.upcall_on_command.set(Some(value));\n    }\n}\n\nimpl crate::fake::SyscallDriver for Proximity {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn {\n        match command_id {\n            EXISTS => crate::command_return::success(),\n\n            READ => {\n                if self.current_command.get() != ProximityCommand::NoCommand {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.current_command.set(ProximityCommand::ReadProximity);\n                if let Some(val) = self.upcall_on_command.get() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            READ_ON_INT => {\n                if self.current_command.get() != ProximityCommand::NoCommand {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.current_command\n                    .set(ProximityCommand::ReadProximityOnInterrupt);\n                self.thresholds.set(Thresholds {\n                    lower: argument0 as u8,\n                    upper: argument1 as u8,\n                });\n                if let Some(val) = self.upcall_on_command.get() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60005;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ: u32 = 1;\nconst READ_ON_INT: u32 = 2;\n"
  },
  {
    "path": "unittest/src/fake/proximity/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::proximity::*;\nuse libtock_platform::{share, DefaultConfig, YieldNoWaitReturn};\n\n//Test the command implementation\n#[test]\nfn command() {\n    let proximity = Proximity::new();\n\n    assert!(proximity.command(EXISTS, 0, 0).is_success());\n\n    assert!(proximity.command(READ, 0, 0).is_success());\n\n    assert_eq!(\n        proximity.command(READ, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    proximity.set_value(0);\n    assert!(proximity.command(READ_ON_INT, 10, 20).is_success());\n\n    //should still be busy, value does not meet conditions\n    proximity.set_value(15);\n    assert_eq!(\n        proximity.command(READ, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    proximity.set_value(50);\n    assert!(proximity.command(READ, 0, 0).is_success());\n    proximity.set_value(50);\n\n    proximity.set_value_sync(10);\n    assert!(proximity.command(READ, 0, 0).is_success());\n\n    //upcall was called after command, should not be busy\n\n    assert!(proximity.command(READ, 0, 0).is_success());\n}\n\n// Integration test that verifies Proximity works with fake::Kernel and\n// libtock_platform::Syscalls.\n\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let proximity = Proximity::new();\n    kernel.add_driver(&proximity);\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 0, 0).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, READ, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    proximity.set_value(100);\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        //should not call an upcall as no command was given\n        proximity.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ, 0, 0).is_success());\n        //now it should call an upcall\n        proximity.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_ON_INT, 50, 150).is_success());\n        proximity.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        proximity.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        proximity.set_value_sync(100);\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ, 0, 0).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    })\n}\n"
  },
  {
    "path": "unittest/src/fake/screen/mod.rs",
    "content": "use crate::{command_return, DriverInfo, DriverShareRef, RoAllowBuffer};\nuse core::cell::Cell;\nuse libtock_platform::{CommandReturn, ErrorCode};\n\npub struct Screen {\n    screen_setup: Option<u16>,     // Optional screen setup state\n    resolution_modes: Option<u16>, // Number of supported resolution modes\n    invert: Cell<bool>,            // Current invert state (true = inverted)\n    screen_resolution_width_height: [Option<(u16, u16)>; 3], // Predefined resolutions\n    resolution_width_height: [Cell<u16>; 2], // Current resolution (width, height)\n    pixel_modes: Option<u16>,      // Number of pixel formats supported\n    screen_pixel_format: [u16; 2], // Predefined pixel formats\n    pixel_format: Cell<u32>,       // Currently selected pixel format\n    brightness: Cell<u16>,         // Current brightness level\n    rotation: Cell<u16>,           // Current screen rotation\n    write_frame: [Cell<u16>; 2],   // Coordinates for the write frame\n    power: Cell<u16>,              // Power state\n    share_ref: DriverShareRef,     // Handle for kernel-user communication\n    write_buffer: Cell<Option<RoAllowBuffer>>, // Optional buffer for write operations\n    messages: Cell<Vec<u8>>,\n}\n\nimpl Screen {\n    pub fn new() -> std::rc::Rc<Screen> {\n        #[allow(clippy::declare_interior_mutable_const)]\n        const VALUE_U16: Cell<u16> = Cell::new(0);\n        #[allow(clippy::declare_interior_mutable_const)]\n        const VALUE_U32: Cell<u32> = Cell::new(0);\n        std::rc::Rc::new(Screen {\n            screen_setup: Some(3),\n            screen_pixel_format: [332, 565], // Example pixel formats\n            screen_resolution_width_height: [\n                Some((1920, 1080)),\n                Some((2560, 1440)),\n                Some((1280, 720)),\n            ],\n            pixel_format: VALUE_U32,\n            resolution_modes: Some(2),\n            resolution_width_height: [VALUE_U16, VALUE_U16],\n            invert: Cell::new(false),\n            brightness: VALUE_U16,\n            pixel_modes: Some(5),\n            rotation: VALUE_U16,\n            write_frame: [VALUE_U16, VALUE_U16],\n            power: VALUE_U16,\n            share_ref: Default::default(),\n            write_buffer: Cell::new(None),\n            messages: Default::default(),\n        })\n    }\n\n    pub fn take_bytes(&self) -> Vec<u8> {\n        self.messages.take()\n    }\n\n    // Checks if the buffer size is compatible with the pixel format\n    fn is_buffer_length_valid(&self, buffer_len: usize) -> bool {\n        let bytes_per_pixel = match self.pixel_format.get() {\n            1 => 1,            // Monochrome\n            2 => 2,            // RGB_565\n            3 => 3,            // RGB_888\n            4 => 4,            // ARGB_8888\n            _ => return false, // Unknown/unsupported format\n        };\n\n        buffer_len % bytes_per_pixel == 0\n    }\n\n    // Simulates writing to the screen\n    fn write(&self, buffer: &[u8]) -> Result<(), ErrorCode> {\n        if !self.is_buffer_length_valid(buffer.len()) {\n            return Err(ErrorCode::Invalid);\n        }\n\n        self.share_ref\n            .schedule_upcall(0, (0, 0, 0))\n            .expect(\"Unable to schedule upcall\");\n        Ok(())\n    }\n\n    // Simulates filling the screen with a color\n    fn fill(&self, _color: u16) -> Result<(), ErrorCode> {\n        self.share_ref\n            .schedule_upcall(0, (0, 0, 0))\n            .expect(\"Unable to schedule upcall\");\n        Ok(())\n    }\n}\n\nimpl crate::fake::SyscallDriver for Screen {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(3)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn allow_readonly(\n        &self,\n        buffer_num: u32,\n        buffer: RoAllowBuffer,\n    ) -> Result<RoAllowBuffer, (RoAllowBuffer, ErrorCode)> {\n        if buffer_num == WRITE_BUFFER_ID {\n            let old_buffer = self.write_buffer.replace(Some(buffer));\n            Ok(old_buffer.unwrap_or_default())\n        } else {\n            Err((buffer, ErrorCode::Invalid))\n        }\n    }\n\n    fn command(&self, command_num: u32, argument0: u32, argument1: u32) -> CommandReturn {\n        match command_num {\n            EXISTS => command_return::success(),\n\n            SCREEN_SETUP => command_return::success_u32(self.screen_setup.unwrap() as u32),\n\n            SET_POWER => {\n                self.power.set(1);\n                command_return::success()\n            }\n\n            GET_POWER => command_return::success_u32(self.power.get() as u32),\n\n            SET_BRIGHTNESS => {\n                self.brightness.set(argument0 as u16);\n                self.share_ref\n                    .schedule_upcall(0, (0, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n                crate::command_return::success()\n            }\n            GET_BRIGHTNESS => crate::command_return::success_u32(self.brightness.get() as u32),\n\n            SET_INVERT_ON => {\n                self.share_ref\n                    .schedule_upcall(0, (0, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n                self.invert.set(argument0 != 0);\n                crate::command_return::success()\n            }\n\n            SET_INVERT_OFF => {\n                self.share_ref\n                    .schedule_upcall(0, (0, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n                self.invert.set(argument0 != 0);\n                command_return::success()\n            }\n\n            SET_INVERT => {\n                self.invert.set(argument0 != 0);\n                command_return::success()\n            }\n\n            GET_INVERT => command_return::success_u32(self.invert.get() as u32),\n\n            GET_RESOLUTION_MODES_COUNT => {\n                if Option::is_some(&self.screen_setup) {\n                    crate::command_return::success_u32(self.resolution_modes.unwrap() as u32)\n                } else {\n                    command_return::failure(ErrorCode::NoSupport)\n                }\n            }\n\n            GET_RESOLUTION_WIDTH_HEIGHT => {\n                if argument0 < self.screen_resolution_width_height.len() as u32 {\n                    if Option::is_some(&self.screen_setup) {\n                        self.share_ref\n                            .schedule_upcall(0, (0, 0, 0))\n                            .expect(\"Unable to schedule upcall {}\");\n                        crate::command_return::success_2_u32(\n                            self.screen_resolution_width_height[argument0 as usize]\n                                .unwrap()\n                                .0 as u32,\n                            self.screen_resolution_width_height[argument0 as usize]\n                                .unwrap()\n                                .1 as u32,\n                        )\n                    } else {\n                        command_return::failure(ErrorCode::NoSupport)\n                    }\n                } else {\n                    command_return::failure(ErrorCode::Invalid)\n                }\n            }\n\n            PIXEL_MODES_COUNT => {\n                if self.screen_setup.is_some() {\n                    command_return::success_u32(self.pixel_modes.unwrap() as u32)\n                } else {\n                    command_return::failure(ErrorCode::NoSupport)\n                }\n            }\n\n            PIXEL_FORMAT => {\n                if argument0 < self.screen_pixel_format.len() as u32 {\n                    if Option::is_some(&self.screen_setup) {\n                        self.share_ref\n                            .schedule_upcall(0, (0, 0, 0))\n                            .expect(\"Unable to schedule upcall {}\");\n                        crate::command_return::success_u32(\n                            self.screen_pixel_format[argument0 as usize] as u32,\n                        )\n                    } else {\n                        crate::command_return::failure(ErrorCode::NoSupport)\n                    }\n                } else {\n                    command_return::failure(ErrorCode::Invalid)\n                }\n            }\n\n            GET_ROTATION => {\n                self.share_ref\n                    .schedule_upcall(0, (0, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n                crate::command_return::success_u32(self.rotation.get() as u32)\n            }\n\n            SET_ROTATION => {\n                if argument0 > 359 {\n                    command_return::failure(ErrorCode::Invalid)\n                } else {\n                    self.rotation.set(argument0 as u16);\n                    self.share_ref\n                        .schedule_upcall(0, (0, 0, 0))\n                        .expect(\"Unable to schedule upcall {}\");\n                    command_return::success()\n                }\n            }\n\n            GET_RESOLUTION => command_return::success_2_u32(\n                self.resolution_width_height[0].get() as u32,\n                self.resolution_width_height[1].get() as u32,\n            ),\n\n            SET_RESOLUTION => {\n                self.share_ref\n                    .schedule_upcall(0, (0, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n                self.resolution_width_height[0].set(argument0 as u16);\n                self.resolution_width_height[1].set(argument1 as u16);\n                command_return::success()\n            }\n\n            GET_PIXEL_FORMAT => command_return::success_u32(self.pixel_format.get()),\n\n            SET_PIXEL_FORMAT => {\n                if argument0 < self.pixel_modes.unwrap() as u32 {\n                    self.pixel_format.set(argument0);\n                    self.share_ref\n                        .schedule_upcall(0, (0, 0, 0))\n                        .expect(\"Unable to schedule upcall {}\");\n                    command_return::success()\n                } else {\n                    command_return::failure(ErrorCode::Invalid)\n                }\n            }\n\n            SET_WRITE_FRAME => {\n                self.share_ref\n                    .schedule_upcall(0, (0, 0, 0))\n                    .expect(\"Unable to schedule upcall {}\");\n                self.write_frame[0].set(argument0 as u16);\n                self.write_frame[1].set(argument1 as u16);\n                command_return::success()\n            }\n\n            GET_WRITE_FRAME => command_return::success_2_u32(\n                self.write_frame[0].get() as u32,\n                self.write_frame[1].get() as u32,\n            ),\n\n            WRITE => {\n                let buffer_len = argument0 as usize;\n                let buffer = self\n                    .write_buffer\n                    .take()\n                    .expect(\"No buffer provided for WRITE command\");\n\n                if buffer.len() != buffer_len || !self.is_buffer_length_valid(buffer_len) {\n                    return command_return::failure(ErrorCode::Invalid);\n                }\n\n                match self.write(buffer.as_ref()) {\n                    Ok(()) => command_return::success(),\n                    Err(e) => command_return::failure(e),\n                }\n            }\n\n            FILL => {\n                let color = argument0 as u16;\n                match self.fill(color) {\n                    Ok(()) => command_return::success(),\n                    Err(e) => command_return::failure(e),\n                }\n            }\n\n            _ => command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n// -----------------------------------------------------------------------------\n// Implementation details below\n// -----------------------------------------------------------------------------\n\n#[cfg(test)]\nmod tests;\n\nconst DRIVER_NUM: u32 = 0x90001;\nconst WRITE_BUFFER_ID: u32 = 0; // Buffer ID for write operations\n\n// Command IDs\n#[allow(unused)]\npub const EXISTS: u32 = 0;\npub const SCREEN_SETUP: u32 = 1;\npub const SET_POWER: u32 = 2;\npub const SET_BRIGHTNESS: u32 = 3;\npub const SET_INVERT_ON: u32 = 4;\npub const SET_INVERT_OFF: u32 = 5;\npub const SET_INVERT: u32 = 6;\npub const GET_RESOLUTION_MODES_COUNT: u32 = 11;\npub const GET_RESOLUTION_WIDTH_HEIGHT: u32 = 12;\npub const PIXEL_MODES_COUNT: u32 = 13;\npub const PIXEL_FORMAT: u32 = 14;\npub const GET_ROTATION: u32 = 21;\npub const SET_ROTATION: u32 = 22;\npub const GET_RESOLUTION: u32 = 23;\npub const SET_RESOLUTION: u32 = 24;\npub const GET_PIXEL_FORMAT: u32 = 25;\npub const SET_PIXEL_FORMAT: u32 = 26;\npub const SET_WRITE_FRAME: u32 = 100;\npub const WRITE: u32 = 200;\npub const FILL: u32 = 300;\npub const GET_POWER: u32 = 400;\npub const GET_BRIGHTNESS: u32 = 401;\npub const GET_INVERT: u32 = 402;\npub const GET_WRITE_FRAME: u32 = 403;\n"
  },
  {
    "path": "unittest/src/fake/screen/tests.rs",
    "content": "use crate::fake;\nuse fake::screen::*;\nuse fake::SyscallDriver;\nuse libtock_platform::share;\nuse libtock_platform::CommandReturn;\nuse libtock_platform::DefaultConfig;\nuse libtock_platform::Syscalls;\n// Tests the command implementation.\n#[test]\nfn command() {\n    let screen = fake::screen::Screen::new();\n\n    // Check if the driver exists\n    let value = screen.command(EXISTS, 0, 0);\n    assert!(CommandReturn::is_success(&value));\n\n    // Verify screen setup command\n    assert_eq!(\n        screen.command(SCREEN_SETUP, 0, 0).get_success_u32(),\n        Some(3)\n    );\n\n    // Test power on/off functionality\n    assert!(screen.command(SET_POWER, 0, 0).is_success());\n    assert_eq!(screen.command(GET_POWER, 0, 0).get_success_u32(), Some(1));\n\n    // Test brightness control\n    assert!(screen.command(SET_BRIGHTNESS, 50, 0).is_success());\n    assert_eq!(\n        screen.command(GET_BRIGHTNESS, 0, 0).get_success_u32(),\n        Some(50)\n    );\n\n    // Pixel mode and format test\n    assert_eq!(\n        screen.command(PIXEL_MODES_COUNT, 0, 0).get_success_u32(),\n        Some(5)\n    );\n    assert_eq!(\n        screen.command(PIXEL_FORMAT, 0, 0).get_success_u32(),\n        Some(332)\n    );\n\n    // Set and get rotation\n    assert!(screen.command(SET_ROTATION, 90, 0).is_success());\n    assert_eq!(\n        screen.command(GET_ROTATION, 0, 0).get_success_u32(),\n        Some(90)\n    );\n\n    // Set and get resolution\n    assert!(screen.command(SET_RESOLUTION, 1280, 720).is_success());\n    assert_eq!(\n        screen.command(GET_RESOLUTION, 0, 0).get_success_2_u32(),\n        Some((1280, 720))\n    );\n\n    // Test invert mode toggle\n    assert!(screen.command(SET_INVERT, 1, 0).is_success());\n    assert_eq!(screen.command(GET_INVERT, 0, 0).get_success_u32(), Some(1));\n\n    // Set and get write frame area\n    assert!(screen.command(SET_WRITE_FRAME, 360, 720).is_success());\n    assert_eq!(\n        screen.command(GET_WRITE_FRAME, 0, 0).get_success_2_u32(),\n        Some((360, 720))\n    );\n\n    // Set and validate pixel format\n    assert!(screen.command(SET_PIXEL_FORMAT, 1, 0).is_success());\n\n    // Ensure that an invalid pixel format returns an error.\n    assert!(screen.command(SET_PIXEL_FORMAT, 99999, 0).is_failure());\n\n    // Kernel setup for screen and buffer simulation\n    let kernel = fake::Kernel::new();\n    kernel.add_driver(&screen);\n    let buf = [0; 4];\n\n    // Share buffer with the driver and test WRITE command\n    share::scope(|allow_ro| {\n        fake::Syscalls::allow_ro::<\n            DefaultConfig,\n            { fake::screen::DRIVER_NUM },\n            { fake::screen::WRITE_BUFFER_ID },\n        >(allow_ro, &buf)\n        .unwrap();\n\n        // Execute write operation\n        assert!(\n            fake::Syscalls::command(fake::screen::DRIVER_NUM, fake::screen::WRITE, 4, 0)\n                .is_success()\n        );\n    });\n}\n\n#[test]\nfn kernel_integration() {\n    use fake::Kernel;\n\n    let kernel = Kernel::new();\n    let screen = Screen::new();\n    kernel.add_driver(&screen);\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 0, 0).is_success());\n\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, SCREEN_SETUP, 0, 0).get_success_u32(),\n        Some(3)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, SET_POWER, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GET_POWER, 0, 0).get_success_u32(),\n        Some(1)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, SET_BRIGHTNESS, 50, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GET_BRIGHTNESS, 0, 0).get_success_u32(),\n        Some(50)\n    );\n\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, PIXEL_MODES_COUNT, 0, 0).get_success_u32(),\n        Some(5)\n    );\n\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, PIXEL_FORMAT, 0, 0).get_success_u32(),\n        Some(332)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, SET_ROTATION, 90, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GET_ROTATION, 0, 0).get_success_u32(),\n        Some(90)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, SET_RESOLUTION, 1280, 720).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GET_RESOLUTION, 0, 0).get_success_2_u32(),\n        Some((1280, 720))\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, SET_INVERT, 1, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GET_INVERT, 0, 0).get_success_u32(),\n        Some(1)\n    );\n\n    assert!(fake::Syscalls::command(DRIVER_NUM, SET_WRITE_FRAME, 360, 720).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, GET_WRITE_FRAME, 0, 0).get_success_2_u32(),\n        Some((360, 720))\n    );\n}\n"
  },
  {
    "path": "unittest/src/fake/sound_pressure/mod.rs",
    "content": "//! Fake implementation of the SoundPressure API, documented here:\n//!\n//! Like the real API, `SoundPressure` controls a fake sound pressure sensor. It provides\n//! a function `set_value` used to immediately call an upcall with a sound pressure value read by the sensor\n//! and a function 'set_value_sync' used to call the upcall when the read command is received.\nuse crate::{DriverInfo, DriverShareRef};\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::cell::Cell;\n\n// The `upcall_on_command` field is set to Some(value) if an upcall(with value as its argument) should be called when read command is received,\n// or None otherwise. It was needed for testing `read_sync` library function which simulates a synchronous sound pressure read,\n// because it was impossible to schedule an upcall during the `synchronous` read in other ways.\npub struct SoundPressure {\n    busy: Cell<bool>,\n    upcall_on_command: Cell<Option<u8>>,\n    share_ref: DriverShareRef,\n}\n\nimpl SoundPressure {\n    pub fn new() -> std::rc::Rc<SoundPressure> {\n        std::rc::Rc::new(SoundPressure {\n            busy: Cell::new(false),\n            upcall_on_command: Cell::new(None),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn is_busy(&self) -> bool {\n        self.busy.get()\n    }\n\n    pub fn set_value(&self, value: u8) {\n        if self.busy.get() {\n            self.share_ref\n                .schedule_upcall(0, (value as u32, 0, 0))\n                .expect(\"Unable to schedule upcall\");\n            self.busy.set(false);\n        }\n    }\n\n    pub fn set_value_sync(&self, value: u8) {\n        self.upcall_on_command.set(Some(value));\n    }\n}\n\nimpl crate::fake::SyscallDriver for SoundPressure {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_id {\n            EXISTS => crate::command_return::success(),\n\n            READ_PRESSURE => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_command.take() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60006;\n\n// Command IDs\nconst EXISTS: u32 = 0;\nconst READ_PRESSURE: u32 = 1;\n"
  },
  {
    "path": "unittest/src/fake/sound_pressure/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::sound_pressure::*;\nuse libtock_platform::{share, DefaultConfig, YieldNoWaitReturn};\n\n//Test the command implementation\n#[test]\nfn command() {\n    let sound_pressure = SoundPressure::new();\n\n    assert!(sound_pressure.command(EXISTS, 1, 2).is_success());\n\n    assert!(sound_pressure.command(READ_PRESSURE, 0, 0).is_success());\n\n    assert_eq!(\n        sound_pressure.command(READ_PRESSURE, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    sound_pressure.set_value(100);\n    assert!(sound_pressure.command(READ_PRESSURE, 0, 1).is_success());\n    sound_pressure.set_value(100);\n\n    sound_pressure.set_value_sync(100);\n    assert!(sound_pressure.command(READ_PRESSURE, 0, 1).is_success());\n    assert!(sound_pressure.command(READ_PRESSURE, 0, 1).is_success());\n}\n\n// Integration test that verifies SoundPressure works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let sound_pressure = SoundPressure::new();\n    kernel.add_driver(&sound_pressure);\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_PRESSURE, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, READ_PRESSURE, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    sound_pressure.set_value(100);\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_PRESSURE, 0, 1).is_success());\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        sound_pressure.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        sound_pressure.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_PRESSURE, 0, 1).is_success());\n        sound_pressure.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((200,)));\n    });\n}\n"
  },
  {
    "path": "unittest/src/fake/syscall_driver.rs",
    "content": "use crate::{DriverInfo, DriverShareRef, RoAllowBuffer, RwAllowBuffer};\nuse libtock_platform::{CommandReturn, ErrorCode};\n\n/// The `fake::SyscallDriver` trait is implemented by fake versions of Tock's\n/// kernel APIs. It is used by `fake::Kernel` to route system calls to the fake\n/// kernel APIs.\npub trait SyscallDriver: 'static {\n    // -------------------------------------------------------------------------\n    // Functions called by `fake::Kernel` during driver registration.\n    // -------------------------------------------------------------------------\n\n    /// Returns information about this driver, including its driver number.\n    fn info(&self) -> DriverInfo;\n\n    /// Called by `fake::Kernel` to link this driver to the `fake::Kernel`.\n    /// Passes a reference to data shared with the kernel (e.g. registered\n    /// upcalls).\n    fn register(&self, share_ref: DriverShareRef) {\n        let _ = share_ref; // Silence the unused variable warning.\n    }\n\n    // -------------------------------------------------------------------------\n    // Command\n    // -------------------------------------------------------------------------\n\n    /// Process a Command system call. Fake drivers should use the methods in\n    /// `libtock_unittest::command_return` to construct the return value.\n    fn command(&self, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn;\n\n    // -------------------------------------------------------------------------\n    // Allow\n    // -------------------------------------------------------------------------\n\n    /// Process a Read-Only Allow call. Because not all `SyscallDriver`\n    /// implementations need to support Read-Only Allow, a default\n    /// implementation is provided that rejects all Read-Only Allow calls.\n    fn allow_readonly(\n        &self,\n        buffer_num: u32,\n        buffer: RoAllowBuffer,\n    ) -> Result<RoAllowBuffer, (RoAllowBuffer, ErrorCode)> {\n        let _ = buffer_num; // Silences the unused variable warning.\n        Err((buffer, ErrorCode::NoSupport))\n    }\n\n    /// Process a Read-Write Allow call. Because not all SyscallDriver\n    /// implementations need to support Read-Write Allow, a default\n    /// implementation is provided that rejects all Read-Write Allow calls.\n    fn allow_readwrite(\n        &self,\n        buffer_num: u32,\n        buffer: RwAllowBuffer,\n    ) -> Result<RwAllowBuffer, (RwAllowBuffer, ErrorCode)> {\n        let _ = buffer_num; // Silences the unused variable warning.\n        Err((buffer, ErrorCode::NoSupport))\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/allow_ro_impl.rs",
    "content": "use crate::kernel_data::with_kernel_data;\nuse crate::{ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{return_variant, ErrorCode, Register};\nuse std::convert::TryInto;\n\npub(super) unsafe fn allow_ro(\n    driver_num: Register,\n    buffer_num: Register,\n    address: Register,\n    len: Register,\n) -> [Register; 4] {\n    let driver_num = driver_num.try_into().expect(\"Too large driver number\");\n    let buffer_num = buffer_num.try_into().expect(\"Too large buffer number\");\n    let result = with_kernel_data(|option_kernel_data| {\n        let kernel_data =\n            option_kernel_data.expect(\"Read-Only Allow called but no fake::Kernel exists\");\n\n        kernel_data.syscall_log.push(SyscallLogEntry::AllowRo {\n            driver_num,\n            buffer_num,\n            len: len.into(),\n        });\n\n        // Check for an expected syscall entry. Returns an error from the lambda\n        // if this syscall was expected and return_error was specified. Panics\n        // if a different syscall was expected.\n        match kernel_data.expected_syscalls.pop_front() {\n            None => {}\n            Some(ExpectedSyscall::AllowRo {\n                driver_num: expected_driver_num,\n                buffer_num: expected_buffer_num,\n                return_error,\n            }) => {\n                assert_eq!(\n                    driver_num, expected_driver_num,\n                    \"expected different driver_num\"\n                );\n                assert_eq!(\n                    buffer_num, expected_buffer_num,\n                    \"expected different buffer_num\"\n                );\n                if let Some(error_code) = return_error {\n                    return Err(error_code);\n                }\n            }\n            Some(expected_syscall) => expected_syscall.panic_wrong_call(\"Read-Only Allow\"),\n        };\n\n        let driver = match kernel_data.drivers.get(&driver_num) {\n            None => return Err(ErrorCode::NoDevice),\n            Some(driver_data) => driver_data.driver.clone(),\n        };\n\n        // Safety: RawSyscall requires the caller to specify address and len as\n        // required by TRD 104. That trivially satisfies the precondition of\n        // insert_ro_buffer, which also requires address and len to follow TRD\n        // 104.\n        let buffer = unsafe { kernel_data.allow_db.insert_ro_buffer(address, len) }\n            .expect(\"Read-Only Allow called with a buffer that overlaps an already-Allowed buffer\");\n\n        Ok((driver, buffer))\n    });\n\n    let (driver, buffer) = match result {\n        Ok((driver, buffer)) => (driver, buffer),\n        Err(error_code) => {\n            let r0: u32 = return_variant::FAILURE_2_U32.into();\n            let r1: u32 = error_code as u32;\n            return [r0.into(), r1.into(), address, len];\n        }\n    };\n\n    let (error_code, buffer_out) = match driver.allow_readonly(buffer_num, buffer) {\n        Ok(buffer_out) => (None, buffer_out),\n        Err((buffer_out, error_code)) => (Some(error_code), buffer_out),\n    };\n\n    let (address_out, len_out) = with_kernel_data(|option_kernel_data| {\n        let kernel_data = option_kernel_data\n            .expect(\"fake::Kernel dropped during fake::SyscallDriver::allow_readonly\");\n        kernel_data.allow_db.remove_ro_buffer(buffer_out)\n    });\n\n    match error_code {\n        None => {\n            let r0: u32 = return_variant::SUCCESS_2_U32.into();\n            // The value of r3 isn't specified in TRD 104, but in practice the\n            // kernel won't change it. This mimics that behavior, for lack of a\n            // better option.\n            [r0.into(), address_out, len_out, len]\n        }\n        Some(error_code) => {\n            let r0: u32 = return_variant::FAILURE_2_U32.into();\n            let r1: u32 = error_code as u32;\n            [r0.into(), r1.into(), address_out, len_out]\n        }\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/allow_ro_impl_tests.rs",
    "content": "use crate::{fake, ExpectedSyscall, SyscallLogEntry};\nuse fake::syscalls::allow_ro_impl::*;\nuse libtock_platform::{return_variant, ErrorCode};\nuse std::convert::TryInto;\nuse std::panic::catch_unwind;\n\n// TODO: Add a TestDriver, and add tests that use a driver:\n// 1. A test that passes buffers to the driver and retrieves them.\n// 2. A test with a driver that doesn't swap buffers (i.e. one that maintains a\n//    longer list of buffers).\n// 3. Fuzz tests\n// 4. Test the driver error handling code.\n\n// Tests calls that do not match the expected system call.\n#[test]\nfn expected_wrong() {\n    let kernel = fake::Kernel::new();\n\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: 1,\n        command_id: 2,\n        argument0: 3,\n        argument1: 4,\n        override_return: None,\n    });\n    assert!(catch_unwind(|| unsafe {\n        allow_ro(1u32.into(), 2u32.into(), 0u32.into(), 0u32.into())\n    })\n    .expect_err(\"failed to catch wrong syscall class\")\n    .downcast_ref::<String>()\n    .expect(\"wrong panic payload type\")\n    .contains(\"but Read-Only Allow was called instead\"));\n\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: 1,\n        buffer_num: 2,\n        return_error: None,\n    });\n    assert!(catch_unwind(|| unsafe {\n        allow_ro(7u32.into(), 2u32.into(), 0u32.into(), 0u32.into())\n    })\n    .expect_err(\"failed to catch wrong driver number\")\n    .downcast_ref::<String>()\n    .expect(\"wrong panic payload type\")\n    .contains(\"expected different driver_num\"));\n\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRo {\n        driver_num: 1,\n        buffer_num: 2,\n        return_error: None,\n    });\n    assert!(catch_unwind(|| unsafe {\n        allow_ro(1u32.into(), 7u32.into(), 0u32.into(), 0u32.into())\n    })\n    .expect_err(\"failed to catch wrong buffer number\")\n    .downcast_ref::<String>()\n    .expect(\"wrong panic payload type\")\n    .contains(\"expected different buffer_num\"));\n}\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    let [r0, r1, r2, r3] = unsafe { allow_ro(7u32.into(), 1u32.into(), 0u32.into(), 0u32.into()) };\n    assert_eq!(\n        r0.try_into(),\n        Ok(Into::<u32>::into(return_variant::FAILURE_2_U32))\n    );\n    assert_eq!(r1.try_into(), Ok(ErrorCode::NoDevice as u32));\n    assert_eq!(r2.try_into(), Ok(0u32));\n    assert_eq!(r3.try_into(), Ok(0u32));\n}\n\n#[test]\nfn no_kernel() {\n    let result =\n        catch_unwind(|| unsafe { allow_ro(1u32.into(), 1u32.into(), 0u32.into(), 0u32.into()) });\n    assert!(result\n        .expect_err(\"failed to catch missing kernel\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"no fake::Kernel exists\"));\n}\n\n#[test]\nfn syscall_log() {\n    let kernel = fake::Kernel::new();\n    // We want to pass a buffer of nonzero length to verify the length is logged\n    // correctly.\n    let buffer = [0; 3];\n    unsafe {\n        allow_ro(\n            1u32.into(),\n            2u32.into(),\n            buffer.as_ptr().into(),\n            buffer.len().into(),\n        );\n    }\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRo {\n            driver_num: 1,\n            buffer_num: 2,\n            len: 3,\n        }]\n    );\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_buffer_number() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| unsafe {\n        allow_ro(\n            1u32.into(),\n            (u32::MAX as usize + 1).into(),\n            0u32.into(),\n            0u32.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large buffer number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large buffer number\"));\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_driver_number() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| unsafe {\n        allow_ro(\n            (u32::MAX as usize + 1).into(),\n            1u32.into(),\n            0u32.into(),\n            0u32.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large driver number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large driver number\"));\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/allow_rw_impl.rs",
    "content": "use crate::kernel_data::with_kernel_data;\nuse crate::{ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{return_variant, ErrorCode, Register};\nuse std::convert::TryInto;\n\npub(super) unsafe fn allow_rw(\n    driver_num: Register,\n    buffer_num: Register,\n    address: Register,\n    len: Register,\n) -> [Register; 4] {\n    let driver_num = driver_num.try_into().expect(\"Too large driver number\");\n    let buffer_num = buffer_num.try_into().expect(\"Too large buffer number\");\n    let result = with_kernel_data(|option_kernel_data| {\n        let kernel_data =\n            option_kernel_data.expect(\"Read-Write Allow called but no fake::Kernel exists\");\n\n        kernel_data.syscall_log.push(SyscallLogEntry::AllowRw {\n            driver_num,\n            buffer_num,\n            len: len.into(),\n        });\n\n        // Check for an expected syscall entry. Returns an error from the lambda\n        // if this syscall was expected and return_error was specified. Panics\n        // if a different syscall was expected.\n        match kernel_data.expected_syscalls.pop_front() {\n            None => {}\n            Some(ExpectedSyscall::AllowRw {\n                driver_num: expected_driver_num,\n                buffer_num: expected_buffer_num,\n                return_error,\n            }) => {\n                assert_eq!(\n                    driver_num, expected_driver_num,\n                    \"expected different driver_num\"\n                );\n                assert_eq!(\n                    buffer_num, expected_buffer_num,\n                    \"expected different buffer_num\"\n                );\n                if let Some(error_code) = return_error {\n                    return Err(error_code);\n                }\n            }\n            Some(expected_syscall) => expected_syscall.panic_wrong_call(\"Read-Write Allow\"),\n        };\n\n        let driver = match kernel_data.drivers.get(&driver_num) {\n            None => return Err(ErrorCode::NoDevice),\n            Some(driver_data) => driver_data.driver.clone(),\n        };\n\n        // Safety: RawSyscall requires the caller to specify address and len as\n        // required by TRD 104. That trivially satisfies the precondition of\n        // insert_rw_buffer, which also requires address and len to follow TRD\n        // 104.\n        let buffer = unsafe { kernel_data.allow_db.insert_rw_buffer(address, len) }.expect(\n            \"Read-Write Allow called with a buffer that overlaps an already-Allowed buffer\",\n        );\n\n        Ok((driver, buffer))\n    });\n\n    let (driver, buffer) = match result {\n        Ok((driver, buffer)) => (driver, buffer),\n        Err(error_code) => {\n            let r0: u32 = return_variant::FAILURE_2_U32.into();\n            let r1: u32 = error_code as u32;\n            return [r0.into(), r1.into(), address, len];\n        }\n    };\n\n    let (error_code, buffer_out) = match driver.allow_readwrite(buffer_num, buffer) {\n        Ok(buffer_out) => (None, buffer_out),\n        Err((buffer_out, error_code)) => (Some(error_code), buffer_out),\n    };\n\n    let (address_out, len_out) = with_kernel_data(|option_kernel_data| {\n        let kernel_data = option_kernel_data\n            .expect(\"fake::Kernel dropped during fake::SyscallDriver::allow_readwrite\");\n        kernel_data.allow_db.remove_rw_buffer(buffer_out)\n    });\n\n    match error_code {\n        None => {\n            let r0: u32 = return_variant::SUCCESS_2_U32.into();\n            // The value of r3 isn't specified in TRD 104, but in practice the\n            // kernel won't change it. This mimics that behavior, for lack of a\n            // better option.\n            [r0.into(), address_out, len_out, len]\n        }\n        Some(error_code) => {\n            let r0: u32 = return_variant::FAILURE_2_U32.into();\n            let r1: u32 = error_code as u32;\n            [r0.into(), r1.into(), address_out, len_out]\n        }\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/allow_rw_impl_tests.rs",
    "content": "use crate::{fake, ExpectedSyscall, SyscallLogEntry};\nuse fake::syscalls::allow_rw_impl::*;\nuse libtock_platform::{return_variant, ErrorCode};\nuse std::convert::TryInto;\nuse std::panic::catch_unwind;\n\n// TODO: Add a TestDriver, and add tests that use a driver:\n// 1. A test that passes buffers to the driver and retrieves them.\n// 2. A test with a driver that doesn't swap buffers (i.e. one that maintains a\n//    longer list of buffers).\n// 3. Fuzz tests\n// 4. Test the driver error handling code.\n\n// Tests calls that do not match the expected system call.\n#[test]\nfn expected_wrong() {\n    let kernel = fake::Kernel::new();\n\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: 1,\n        command_id: 2,\n        argument0: 3,\n        argument1: 4,\n        override_return: None,\n    });\n    assert!(catch_unwind(|| unsafe {\n        allow_rw(1u32.into(), 2u32.into(), 0u32.into(), 0u32.into())\n    })\n    .expect_err(\"failed to catch wrong syscall class\")\n    .downcast_ref::<String>()\n    .expect(\"wrong panic payload type\")\n    .contains(\"but Read-Write Allow was called instead\"));\n\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRw {\n        driver_num: 1,\n        buffer_num: 2,\n        return_error: None,\n    });\n    assert!(catch_unwind(|| unsafe {\n        allow_rw(7u32.into(), 2u32.into(), 0u32.into(), 0u32.into())\n    })\n    .expect_err(\"failed to catch wrong driver number\")\n    .downcast_ref::<String>()\n    .expect(\"wrong panic payload type\")\n    .contains(\"expected different driver_num\"));\n\n    kernel.add_expected_syscall(ExpectedSyscall::AllowRw {\n        driver_num: 1,\n        buffer_num: 2,\n        return_error: None,\n    });\n    assert!(catch_unwind(|| unsafe {\n        allow_rw(1u32.into(), 7u32.into(), 0u32.into(), 0u32.into())\n    })\n    .expect_err(\"failed to catch wrong buffer number\")\n    .downcast_ref::<String>()\n    .expect(\"wrong panic payload type\")\n    .contains(\"expected different buffer_num\"));\n}\n\n#[test]\nfn no_driver() {\n    let _kernel = fake::Kernel::new();\n    let [r0, r1, r2, r3] = unsafe { allow_rw(7u32.into(), 1u32.into(), 0u32.into(), 0u32.into()) };\n    assert_eq!(\n        r0.try_into(),\n        Ok(Into::<u32>::into(return_variant::FAILURE_2_U32))\n    );\n    assert_eq!(r1.try_into(), Ok(ErrorCode::NoDevice as u32));\n    assert_eq!(r2.try_into(), Ok(0u32));\n    assert_eq!(r3.try_into(), Ok(0u32));\n}\n\n#[test]\nfn no_kernel() {\n    let result =\n        catch_unwind(|| unsafe { allow_rw(1u32.into(), 1u32.into(), 0u32.into(), 0u32.into()) });\n    assert!(result\n        .expect_err(\"failed to catch missing kernel\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"no fake::Kernel exists\"));\n}\n\n#[test]\nfn syscall_log() {\n    let kernel = fake::Kernel::new();\n    // We want to pass a buffer of nonzero length to verify the length is logged\n    // correctly.\n    let buffer = [0; 3];\n    unsafe {\n        allow_rw(\n            1u32.into(),\n            2u32.into(),\n            buffer.as_ptr().into(),\n            buffer.len().into(),\n        );\n    }\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRw {\n            driver_num: 1,\n            buffer_num: 2,\n            len: 3,\n        }]\n    );\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_buffer_number() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| unsafe {\n        allow_rw(\n            1u32.into(),\n            (u32::MAX as usize + 1).into(),\n            0u32.into(),\n            0u32.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large buffer number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large buffer number\"));\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_driver_number() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| unsafe {\n        allow_rw(\n            (u32::MAX as usize + 1).into(),\n            1u32.into(),\n            0u32.into(),\n            0u32.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large driver number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large driver number\"));\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/command_impl.rs",
    "content": "//! `fake::Kernel`'s implementation of the Command system call.\n\nuse crate::kernel_data::with_kernel_data;\nuse crate::{command_return, ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{ErrorCode, Register};\nuse std::convert::TryInto;\n\npub(super) fn command(\n    driver_id: Register,\n    command_id: Register,\n    argument0: Register,\n    argument1: Register,\n) -> [Register; 4] {\n    let driver_id = driver_id.try_into().expect(\"Too large driver ID\");\n    let command_id = command_id.try_into().expect(\"Too large command ID\");\n    let argument0 = argument0.try_into().expect(\"Too large argument 0\");\n    let argument1 = argument1.try_into().expect(\"Too large argument 1\");\n\n    let (driver, override_return) = with_kernel_data(|option_kernel_data| {\n        let kernel_data = option_kernel_data.expect(\"Command called but no fake::Kernel exists\");\n\n        kernel_data.syscall_log.push(SyscallLogEntry::Command {\n            driver_id,\n            command_id,\n            argument0,\n            argument1,\n        });\n\n        // Check for an expected syscall entry. Sets override_return to None if\n        // the expected syscall queue is empty or if it expected this syscall\n        // but did not specify a return override. Panics if a different syscall\n        // was expected (either a non-Command syscall, or a Command call with\n        // different arguments).\n        let override_return = match kernel_data.expected_syscalls.pop_front() {\n            None => None,\n            Some(ExpectedSyscall::Command {\n                driver_id: expected_driver_id,\n                command_id: expected_command_id,\n                argument0: expected_argument0,\n                argument1: expected_argument1,\n                override_return,\n            }) => {\n                assert_eq!(\n                    driver_id, expected_driver_id,\n                    \"expected different driver_id\"\n                );\n                assert_eq!(\n                    command_id, expected_command_id,\n                    \"expected different command_id\"\n                );\n                assert_eq!(\n                    argument0, expected_argument0,\n                    \"expected different argument0\"\n                );\n                assert_eq!(\n                    argument1, expected_argument1,\n                    \"expected different argument1\"\n                );\n                override_return\n            }\n            Some(expected_syscall) => expected_syscall.panic_wrong_call(\"Command\"),\n        };\n\n        let driver = kernel_data\n            .drivers\n            .get(&driver_id)\n            .map(|driver_data| driver_data.driver.clone());\n\n        (driver, override_return)\n    });\n\n    // Call the driver if one is present. If not, return NoDevice as required by\n    // TRD 104.\n    let driver_return = match driver {\n        Some(driver) => driver.command(command_id, argument0, argument1),\n        None => command_return::failure(ErrorCode::NoDevice),\n    };\n\n    // Convert the override return value (or the driver return value if no\n    // override is present) into the representative register values.\n    let (return_variant, r1, r2, r3) = override_return.unwrap_or(driver_return).raw_values();\n    let r0: u32 = return_variant.into();\n    [r0.into(), r1.into(), r2.into(), r3.into()]\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/command_impl_tests.rs",
    "content": "use super::command_impl::*;\nuse crate::{command_return, fake, DriverInfo, ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{\n    return_variant, syscall_class, CommandReturn, ErrorCode, RawSyscalls, ReturnVariant,\n};\nuse std::convert::TryInto;\nuse std::panic::catch_unwind;\n\n// TODO: When another system call is implemented, add a test for the case\n// where a different system call class is expected.\n\n#[test]\nfn driver_support() {\n    let kernel = fake::Kernel::new();\n\n    // Call command for a nonexistent driver.\n    let [r0, r1, _, _] = command(42u32.into(), 1u32.into(), 0u32.into(), 0u32.into());\n    assert_eq!(\n        r0.try_into(),\n        Ok(Into::<u32>::into(return_variant::FAILURE))\n    );\n    assert_eq!(r1.try_into(), Ok(ErrorCode::NoDevice as u32));\n\n    // A mock driver that returns a fixed value.\n    // TODO: This is growing every time we add a new required method to Driver.\n    // Once we have fake driver inside `crate::fake` (e.g. a fake LowLevelDebug\n    // driver), we should remove MockDriver and replace it with the fake driver,\n    // so we have 1 fewer Driver implementations to maintain.\n    struct MockDriver;\n    impl fake::SyscallDriver for MockDriver {\n        fn info(&self) -> DriverInfo {\n            DriverInfo::new(42)\n        }\n        fn command(&self, _command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n            command_return::success_3_u32(1, 2, 3)\n        }\n    }\n\n    // Call command with the mock driver.\n    let driver = std::rc::Rc::new(MockDriver);\n    kernel.add_driver(&driver);\n    let [r0, r1, r2, r3] = command(42u32.into(), 0u32.into(), 0u32.into(), 0u32.into());\n    assert_eq!(\n        r0.try_into(),\n        Ok(Into::<u32>::into(return_variant::SUCCESS_3_U32))\n    );\n    assert_eq!(r1.try_into(), Ok(1u32));\n    assert_eq!(r2.try_into(), Ok(2u32));\n    assert_eq!(r3.try_into(), Ok(3u32));\n}\n\n// Tests command with expected syscalls that don't match this command call.\n#[test]\nfn expected_wrong_command() {\n    let kernel = fake::Kernel::new();\n    let expected_syscall = ExpectedSyscall::Command {\n        driver_id: 1,\n        command_id: 1,\n        argument0: 1,\n        argument1: 1,\n        override_return: None,\n    };\n\n    kernel.add_expected_syscall(expected_syscall);\n    assert!(\n        catch_unwind(|| command(2u32.into(), 1u32.into(), 1u32.into(), 1u32.into()))\n            .expect_err(\"failed to catch wrong driver_id\")\n            .downcast_ref::<String>()\n            .expect(\"wrong panic payload type\")\n            .contains(\"expected different driver_id\")\n    );\n\n    kernel.add_expected_syscall(expected_syscall);\n    assert!(\n        catch_unwind(|| command(1u32.into(), 2u32.into(), 1u32.into(), 1u32.into()))\n            .expect_err(\"failed to catch wrong command_id\")\n            .downcast_ref::<String>()\n            .expect(\"wrong panic payload type\")\n            .contains(\"expected different command_id\")\n    );\n\n    kernel.add_expected_syscall(expected_syscall);\n    assert!(\n        catch_unwind(|| command(1u32.into(), 1u32.into(), 2u32.into(), 1u32.into()))\n            .expect_err(\"failed to catch wrong argument0\")\n            .downcast_ref::<String>()\n            .expect(\"wrong panic payload type\")\n            .contains(\"expected different argument0\")\n    );\n\n    kernel.add_expected_syscall(expected_syscall);\n    assert!(\n        catch_unwind(|| command(1u32.into(), 1u32.into(), 1u32.into(), 2u32.into()))\n            .expect_err(\"failed to catch wrong argument1\")\n            .downcast_ref::<String>()\n            .expect(\"wrong panic payload type\")\n            .contains(\"expected different argument1\")\n    );\n}\n\n#[test]\nfn no_kernel() {\n    let result = catch_unwind(|| command(1u32.into(), 1u32.into(), 0u32.into(), 0u32.into()));\n    assert!(result\n        .expect_err(\"failed to catch missing kernel\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"no fake::Kernel exists\"));\n}\n\n#[test]\nfn override_return() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::Command {\n        driver_id: 1,\n        command_id: 2,\n        argument0: 3,\n        argument1: 4,\n        override_return: Some(command_return::success_3_u32(1, 2, 3)),\n    });\n    let [r0, r1, r2, r3] = command(1u32.into(), 2u32.into(), 3u32.into(), 4u32.into());\n    let r0: u32 = r0.try_into().expect(\"too large r0\");\n    let r1: u32 = r1.try_into().expect(\"too large r1\");\n    let r2: u32 = r2.try_into().expect(\"too large r2\");\n    let r3: u32 = r3.try_into().expect(\"too large r3\");\n    let return_variant: ReturnVariant = r0.into();\n    assert_eq!(return_variant, return_variant::SUCCESS_3_U32);\n    assert_eq!(r1, 1);\n    assert_eq!(r2, 2);\n    assert_eq!(r3, 3);\n}\n\n// Test that fake::Kernel's implementation of RawSyscalls correctly forwards\n// a command to `command`.\n// TODO: Migrate into raw_syscalls_impl.rs when the other system calls are\n// completed, to avoid git conflicts.\n#[test]\nfn syscall4() {\n    let kernel = fake::Kernel::new();\n    unsafe {\n        fake::Syscalls::syscall4::<{ syscall_class::COMMAND }>([\n            1u32.into(),\n            2u32.into(),\n            3u32.into(),\n            4u32.into(),\n        ]);\n    }\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Command {\n            driver_id: 1,\n            command_id: 2,\n            argument0: 3,\n            argument1: 4,\n        }]\n    );\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_argument0() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| {\n        command(\n            1u32.into(),\n            1u32.into(),\n            (u32::MAX as usize + 1).into(),\n            0u32.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large argument0\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large argument 0\"));\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_argument1() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| {\n        command(\n            1u32.into(),\n            1u32.into(),\n            0u32.into(),\n            (u32::MAX as usize + 1).into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large argument1\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large argument 1\"));\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_command_id() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| {\n        command(\n            1u32.into(),\n            (u32::MAX as usize + 1).into(),\n            0u32.into(),\n            0u32.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large command ID\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large command ID\"));\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_driver_id() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| {\n        command(\n            (u32::MAX as usize + 1).into(),\n            1u32.into(),\n            0u32.into(),\n            0u32.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large driver ID\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large driver ID\"));\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/exit_impl.rs",
    "content": "use core::convert::TryInto;\n\npub(super) fn exit(r0: libtock_platform::Register, r1: libtock_platform::Register) -> ! {\n    let exit_num: u32 = r0.try_into().expect(\"Too large exit number\");\n    let completion_code: u32 = r1.try_into().expect(\"Too large completion code\");\n    match exit_num {\n        libtock_platform::exit_id::TERMINATE => {\n            println!(\"exit-terminate called with code {completion_code}\");\n\n            #[cfg(not(miri))]\n            crate::exit_test::signal_exit(crate::ExitCall::Terminate(completion_code));\n\n            std::process::exit(1);\n        }\n        libtock_platform::exit_id::RESTART => {\n            println!(\"exit-restart called with code {completion_code}\");\n\n            #[cfg(not(miri))]\n            crate::exit_test::signal_exit(crate::ExitCall::Restart(completion_code));\n\n            std::process::exit(1);\n        }\n        _ => panic!(\"Unknown exit number {exit_num} invoked.\"),\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/exit_impl_tests.rs",
    "content": "use super::exit_impl::*;\nuse crate::{exit_test, ExitCall};\n\n#[test]\nfn exit_restart() {\n    let exit_call = exit_test(\"fake::syscalls::exit_impl_tests::exit_restart\", || {\n        exit(libtock_platform::exit_id::RESTART.into(), 31415u32.into())\n    });\n    assert_eq!(exit_call, ExitCall::Restart(31415));\n}\n\n#[test]\nfn exit_terminate() {\n    let exit_call = exit_test(\"fake::syscalls::exit_impl_tests::exit_terminate\", || {\n        exit(libtock_platform::exit_id::TERMINATE.into(), 9265u32.into())\n    });\n    assert_eq!(exit_call, ExitCall::Terminate(9265));\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/memop_impl.rs",
    "content": "//! `fake::Kernel`'s implementation of the Memop system call.\n\nuse crate::kernel_data::with_kernel_data;\nuse crate::{ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{return_variant, ErrorCode, Register};\nuse std::convert::TryInto;\n\npub(super) fn memop(memop_num: Register, argument0: Register) -> [Register; 2] {\n    let memop_num = memop_num.try_into().expect(\"Too large memop num\");\n\n    let (return_error, memop_return, memop_r1) = with_kernel_data(|option_kernel_data| {\n        let kernel_data = option_kernel_data.expect(\"Memop called but no fake::Kernel exists\");\n\n        kernel_data.syscall_log.push(SyscallLogEntry::Memop {\n            memop_num,\n            argument0,\n        });\n\n        // Check for an expected syscall entry. Sets return_error to None if\n        // the expected syscall queue is empty or if it expected this syscall\n        // but did not specify a return override. Panics if a different syscall\n        // was expected (either a non-Memop syscall, or a Memop call with\n        // different arguments).\n        let return_error = match kernel_data.expected_syscalls.pop_front() {\n            None => None,\n            Some(ExpectedSyscall::Memop {\n                memop_num: expected_memop_num,\n                argument0: expected_argument0,\n                return_error,\n            }) => {\n                assert_eq!(\n                    memop_num, expected_memop_num,\n                    \"expected different memop_num\"\n                );\n                assert_eq!(\n                    usize::from(argument0),\n                    usize::from(expected_argument0),\n                    \"expected different argument0\"\n                );\n                return_error\n            }\n            Some(expected_syscall) => expected_syscall.panic_wrong_call(\"Memop\"),\n        };\n\n        // Emulate the memop call\n        // TODO: This emulation could be improved by adding data to kernel_data to allow us to\n        // better track what input arguments might be expected to return errors.\n        let (memop_return, memop_r1) = match memop_num {\n            0 => {\n                /* brk */\n                if Into::<*const u8>::into(argument0).is_null() {\n                    (return_variant::FAILURE, ErrorCode::Invalid.into())\n                } else {\n                    kernel_data.memory_break = argument0.into();\n                    (return_variant::SUCCESS, 0.into())\n                }\n            }\n            1 => {\n                /* sbrk */\n                let current_brk = kernel_data.memory_break;\n                let new_brk = current_brk.wrapping_byte_offset(argument0.as_i32() as isize);\n                kernel_data.memory_break = new_brk;\n                (return_variant::SUCCESS, kernel_data.memory_break.into())\n            }\n            2 => {\n                /* app_ram_start */\n                // just pick a random number to always return, for now\n                (return_variant::SUCCESS, 0x123400.into())\n            }\n            10 => {\n                /* debug_stack_start */\n                (return_variant::SUCCESS, 0.into())\n            }\n            11 => {\n                /* debug_heap_start */\n                (return_variant::SUCCESS, 0.into())\n            }\n            _ => {\n                panic!(\"Memop num not supported by test infrastructure\");\n            }\n        };\n        (return_error, memop_return, memop_r1)\n    });\n\n    // Convert the return value into the representative register values.\n    // If there is an return_error, return a Failure along with that ErrorCode.\n    let (return_variant, r1) = return_error.map_or((memop_return, memop_r1), |override_errcode| {\n        (return_variant::FAILURE, override_errcode.into())\n    });\n    let r0: u32 = return_variant.into();\n    [r0.into(), r1]\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/memop_impl_tests.rs",
    "content": "use super::memop_impl::*;\nuse crate::{fake, ExpectedSyscall};\nuse libtock_platform::{return_variant, ErrorCode, ReturnVariant};\nuse std::convert::TryInto;\nuse std::panic::catch_unwind;\n\n// Tests memop with expected syscalls that don't match this memop call.\n#[test]\nfn expected_wrong_memop() {\n    let kernel = fake::Kernel::new();\n    let expected_syscall = ExpectedSyscall::Memop {\n        memop_num: 1,\n        argument0: 1u32.into(),\n        return_error: None,\n    };\n\n    kernel.add_expected_syscall(expected_syscall);\n    assert!(catch_unwind(|| memop(0u32.into(), 1u32.into()))\n        .expect_err(\"failed to catch wrong memop_num\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"expected different memop_num\"));\n\n    kernel.add_expected_syscall(expected_syscall);\n    assert!(catch_unwind(|| memop(1u32.into(), 0u32.into()))\n        .expect_err(\"failed to catch wrong memop argument0\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"expected different argument0\"));\n}\n\n#[test]\nfn no_kernel() {\n    let result = catch_unwind(|| memop(1u32.into(), 1u32.into()));\n    assert!(result\n        .expect_err(\"failed to catch missing kernel\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"no fake::Kernel exists\"));\n}\n\n#[test]\nfn return_error() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 1,\n        argument0: 4u32.into(),\n        return_error: Some(ErrorCode::NoMem),\n    });\n    let [r0, r1] = memop(1u32.into(), 4u32.into());\n    let r0: u32 = r0.try_into().expect(\"too large r0\");\n    let r1: u32 = r1.try_into().expect(\"too large r1\");\n    let return_variant: ReturnVariant = r0.into();\n    assert_eq!(return_variant, return_variant::FAILURE);\n    assert_eq!(r1, ErrorCode::NoMem as u32);\n}\n\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_memop_num() {\n    let _kernel = fake::Kernel::new();\n    let result = catch_unwind(|| memop((u32::MAX as usize + 1).into(), 1u32.into()));\n    assert!(result\n        .expect_err(\"failed to catch too-large memop num\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large memop num\"));\n}\n\n#[test]\nfn memop_using_syscall1() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::Memop {\n        memop_num: 2,\n        argument0: 0u32.into(),\n        return_error: None,\n    });\n    let [r0, r1] = memop(2u32.into(), 0u32.into());\n    let r0: u32 = r0.try_into().expect(\"too large r0\");\n    let _r1: u32 = r1.try_into().expect(\"too large r1\");\n    let return_variant: ReturnVariant = r0.into();\n    assert_eq!(return_variant, return_variant::SUCCESS);\n    // No assertion for return value, could be any value from real kernel.\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/mod.rs",
    "content": "mod allow_ro_impl;\nmod allow_rw_impl;\nmod command_impl;\nmod exit_impl;\nmod memop_impl;\nmod raw_syscalls_impl;\nmod subscribe_impl;\nmod yield_impl;\n\n/// `fake::Syscalls` implements `libtock_platform::Syscalls` by forwarding the\n/// system calls to the thread's `fake::Kernel` instance. It is used by unit\n/// tests to provide the code under test access to Tock's system calls.\npub struct Syscalls;\n\n#[cfg(test)]\nmod allow_ro_impl_tests;\n#[cfg(test)]\nmod allow_rw_impl_tests;\n#[cfg(test)]\nmod command_impl_tests;\n#[cfg(all(not(miri), test))]\nmod exit_impl_tests;\n#[cfg(test)]\nmod memop_impl_tests;\n#[cfg(test)]\nmod raw_syscalls_impl_tests;\n#[cfg(test)]\nmod subscribe_impl_tests;\n#[cfg(test)]\nmod yield_impl_tests;\n\n// Miri does not always check that values are valid (see `doc/MiriTips.md` in\n// the root of this repository). This function uses a hack to verify a value is\n// valid. If the value is invalid, Miri will detect undefined behavior when it\n// executes this. It is used by submodules of fake::syscalls.\nfn assert_valid<T: core::fmt::Debug>(_value: T) {\n    #[cfg(miri)]\n    let _ = format!(\"{:?}\", _value);\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/raw_syscalls_impl.rs",
    "content": "use libtock_platform::{syscall_class, yield_id, RawSyscalls, Register};\nuse std::convert::TryInto;\n\nunsafe impl RawSyscalls for crate::fake::Syscalls {\n    unsafe fn yield1([r0]: [Register; 1]) {\n        crate::fake::syscalls::assert_valid(r0);\n        match r0.try_into().expect(\"too-large Yield ID passed\") {\n            yield_id::NO_WAIT => panic!(\"yield-no-wait called without an argument\"),\n            yield_id::WAIT => super::yield_impl::yield_wait(),\n            id => panic!(\"unknown yield ID {id}\"),\n        }\n    }\n\n    unsafe fn yield2([r0, r1]: [Register; 2]) {\n        crate::fake::syscalls::assert_valid((r0, r1));\n        match r0.try_into().expect(\"too-large Yield ID passed\") {\n            yield_id::NO_WAIT => unsafe { super::yield_impl::yield_no_wait(r1.into()) },\n            yield_id::WAIT => {\n                // Technically it is acceptable to call yield_wait with an\n                // argument, but it shouldn't be done because it's wasteful so\n                // we fail the test case regardless.\n                panic!(\"yield-wait called with an argument\");\n            }\n            id => panic!(\"unknown yield ID {id}\"),\n        }\n    }\n\n    unsafe fn syscall1<const CLASS: usize>([r0]: [Register; 1]) -> [Register; 2] {\n        match CLASS {\n            syscall_class::MEMOP => super::memop_impl::memop(r0, 0u32.into()),\n            _ => panic!(\"Unknown syscall1 call. Class: {CLASS}\"),\n        }\n    }\n\n    unsafe fn syscall2<const CLASS: usize>([r0, r1]: [Register; 2]) -> [Register; 2] {\n        crate::fake::syscalls::assert_valid((r0, r1));\n        match CLASS {\n            syscall_class::MEMOP => super::memop_impl::memop(r0, r1),\n            syscall_class::EXIT => super::exit_impl::exit(r0, r1),\n            _ => panic!(\"Unknown syscall2 call. Class: {CLASS}\"),\n        }\n    }\n\n    unsafe fn syscall4<const CLASS: usize>([r0, r1, r2, r3]: [Register; 4]) -> [Register; 4] {\n        crate::fake::syscalls::assert_valid((r0, r1, r2, r3));\n        match CLASS {\n            syscall_class::SUBSCRIBE => unsafe { super::subscribe_impl::subscribe(r0, r1, r2, r3) },\n            syscall_class::COMMAND => super::command_impl::command(r0, r1, r2, r3),\n            syscall_class::ALLOW_RW => unsafe { super::allow_rw_impl::allow_rw(r0, r1, r2, r3) },\n            syscall_class::ALLOW_RO => unsafe { super::allow_ro_impl::allow_ro(r0, r1, r2, r3) },\n            _ => panic!(\"Unknown syscall4 call. Class: {CLASS}\"),\n        }\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/raw_syscalls_impl_tests.rs",
    "content": "// These tests verify the RawSyscalls implementation routes system calls to the\n// fake implementations (e.g. command(), yield_wait, etc) correctly. It does not\n// test the fake syscall implementations themselves, as they have their own unit\n// tests.\n\nuse crate::{fake, SyscallLogEntry};\nuse libtock_platform::{syscall_class, RawSyscalls};\n\n#[test]\nfn allow_ro() {\n    let kernel = fake::Kernel::new();\n    unsafe {\n        fake::Syscalls::syscall4::<{ syscall_class::ALLOW_RO }>([\n            1u32.into(),\n            2u32.into(),\n            0u32.into(),\n            0u32.into(),\n        ]);\n    }\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRo {\n            driver_num: 1,\n            buffer_num: 2,\n            len: 0,\n        }]\n    );\n}\n\n#[test]\nfn allow_rw() {\n    let kernel = fake::Kernel::new();\n    unsafe {\n        fake::Syscalls::syscall4::<{ syscall_class::ALLOW_RW }>([\n            1u32.into(),\n            2u32.into(),\n            0u32.into(),\n            0u32.into(),\n        ]);\n    }\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::AllowRw {\n            driver_num: 1,\n            buffer_num: 2,\n            len: 0,\n        }]\n    );\n}\n\n// TODO: Move the syscall4 Command test here.\n\n// TODO: Implement Exit.\n\n#[test]\nfn memop() {\n    let kernel = fake::Kernel::new();\n    unsafe {\n        fake::Syscalls::syscall2::<{ syscall_class::MEMOP }>([1u32.into(), 2u32.into()]);\n        fake::Syscalls::syscall1::<{ syscall_class::MEMOP }>([2u32.into()]);\n    }\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [\n            SyscallLogEntry::Memop {\n                memop_num: 1,\n                argument0: 2.into(),\n            },\n            SyscallLogEntry::Memop {\n                memop_num: 2,\n                argument0: 0.into(),\n            }\n        ]\n    );\n}\n\n// TODO: Implement Subscribe.\n\n// TODO: Move the yield1 and yield2 tests here.\n"
  },
  {
    "path": "unittest/src/fake/syscalls/subscribe_impl.rs",
    "content": "use crate::kernel_data::with_kernel_data;\nuse crate::{ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{return_variant, ErrorCode, Register};\nuse std::convert::TryInto;\n\n// Safety: The arguments must represent a valid Subscribe call as specified by\n// TRD 104.\npub(super) unsafe fn subscribe(\n    driver_num: Register,\n    subscribe_num: Register,\n    upcall_fn: Register,\n    data: Register,\n) -> [Register; 4] {\n    let driver_num = driver_num.try_into().expect(\"Too large driver number\");\n    let subscribe_num = subscribe_num\n        .try_into()\n        .expect(\"Too large subscribe number\");\n    let (skip_with_error, num_upcalls) = with_kernel_data(|option_kernel_data| {\n        let kernel_data = option_kernel_data.expect(\"Subscribe called but no fake::Kernel exists\");\n\n        kernel_data.syscall_log.push(SyscallLogEntry::Subscribe {\n            driver_num,\n            subscribe_num,\n        });\n\n        // Check for an expected syscall. Panics if an expected syscall exists\n        // and it does not match this syscall. Otherwise sets skip_with_error to\n        // skip_with_error from the expected syscall, or None if none was\n        // provided.\n        let skip_with_error = match kernel_data.expected_syscalls.pop_front() {\n            None => None,\n            Some(ExpectedSyscall::Subscribe {\n                driver_num: expected_driver_num,\n                subscribe_num: expected_subscribe_num,\n                skip_with_error,\n            }) => {\n                assert_eq!(\n                    driver_num, expected_driver_num,\n                    \"expected different driver number\"\n                );\n                assert_eq!(\n                    subscribe_num, expected_subscribe_num,\n                    \"expected different subscribe number\"\n                );\n                skip_with_error\n            }\n            Some(expected_syscall) => expected_syscall.panic_wrong_call(\"Subscribe\"),\n        };\n\n        // Retrieve the number of upcalls for this driver, or None if there is\n        // no driver with this number.\n        let num_upcalls = kernel_data\n            .drivers\n            .get(&driver_num)\n            .map(|driver_data| driver_data.num_upcalls);\n\n        (skip_with_error, num_upcalls)\n    });\n\n    // Convenience function to produce an error return.\n    let failure_registers = |error_code: ErrorCode| {\n        [\n            return_variant::FAILURE_2_U32.into(),\n            error_code.into(),\n            upcall_fn,\n            data,\n        ]\n    };\n\n    // If skip_with_error was specified, we skip the remainder of this logic and\n    // return an error directly.\n    if let Some(error_code) = skip_with_error {\n        return failure_registers(error_code);\n    }\n\n    // Verify the given driver ID was present. If no driver with this ID is\n    // present, the kernel returns NODEVICE.\n    let num_upcalls = match num_upcalls {\n        Some(num_upcalls) => num_upcalls,\n        None => return failure_registers(ErrorCode::NoDevice),\n    };\n\n    // If a too-large subscribe number is passed, the kernel returns the Invalid\n    // error code.\n    if subscribe_num >= num_upcalls {\n        return failure_registers(ErrorCode::Invalid);\n    }\n\n    // At this point, we know the Subscribe call should succeed.\n\n    let upcall = crate::upcall::Upcall {\n        fn_pointer: match upcall_fn.into() {\n            0usize => None,\n            // Safety: RawSyscalls guarantees that if upcall_fn is not 0, then\n            // it is a valid unsafe extern fn(u32, u32, u32, Register). We've\n            // already verified upcall_fn is not 0. The niche optimization\n            // guarantees that an unsafe extern fn(u32, u32, u32, Register) can\n            // be transmuted into an Option<unsafe extern fn(u32, u32, u32,\n            // Register)>.\n            _ => unsafe {\n                core::mem::transmute::<\n                    Register,\n                    std::option::Option<unsafe extern \"C\" fn(u32, u32, u32, Register)>,\n                >(upcall_fn)\n            },\n        },\n        data,\n    };\n\n    let upcall_id = crate::upcall::UpcallId {\n        driver_num,\n        subscribe_num,\n    };\n\n    // Go back into the kernel data to update the stored upcall and purge the\n    // previous upcall from the upcall queue (as required by TRD 104).\n    let out_upcall = with_kernel_data(|option_kernel_data| {\n        let kernel_data = option_kernel_data.unwrap();\n        kernel_data\n            .upcall_queue\n            .retain(|existing_queue_entry| existing_queue_entry.id != upcall_id);\n        kernel_data\n            .drivers\n            .get_mut(&driver_num)\n            .unwrap()\n            .upcalls\n            .insert(subscribe_num, upcall)\n    });\n\n    let out_upcall_fn = out_upcall\n        .map_or(0, |out_upcall| match out_upcall.fn_pointer {\n            None => 0,\n            Some(fn_pointer) => fn_pointer as usize,\n        })\n        .into();\n\n    let out_upcall_data = out_upcall.map_or(0usize.into(), |out_upcall| out_upcall.data);\n\n    // The Success with 2 U32 variant doesn't specify what is returned in r3. In\n    // practice, the kernel will leave that register alone, so we echo data\n    // (passed in via r3) out as r3.\n    [\n        return_variant::SUCCESS_2_U32.into(),\n        out_upcall_fn,\n        out_upcall_data,\n        data,\n    ]\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/subscribe_impl_tests.rs",
    "content": "use super::subscribe_impl::*;\nuse crate::{fake, ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{return_variant, syscall_class, ErrorCode, RawSyscalls, Register};\nuse std::convert::TryInto;\nuse std::panic::catch_unwind;\n\n// TODO: Once a fake driver that supports upcalls is added, add the following\n// test cases:\n// 1. A test with a subscribe_id that is too large.\n// 2. A test that should pass -- and verify the upcall is set correctly.\n// 3. A test that verifies that upcalls are correctly cleared from the queue\n//    when they are replaced by a subsequent Subscribe call.\n\n// Tests Subscribe calls that do not match the expected syscall.\n#[test]\nfn expected_wrong() {\n    let kernel = fake::Kernel::new();\n\n    // Test with a non-Subscribe expected syscall.\n    kernel.add_expected_syscall(ExpectedSyscall::YieldWait { skip_upcall: false });\n    let result = catch_unwind(|| unsafe {\n        subscribe(1u32.into(), 2u32.into(), 0usize.into(), 0usize.into())\n    });\n    assert!(result\n        .expect_err(\"failed to catch wrong syscall\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"but Subscribe was called instead\"));\n\n    let expected_syscall = ExpectedSyscall::Subscribe {\n        driver_num: 1,\n        subscribe_num: 2,\n        skip_with_error: None,\n    };\n\n    // Tests with an incorrect driver number\n    kernel.add_expected_syscall(expected_syscall);\n    let result = catch_unwind(|| unsafe {\n        subscribe(7u32.into(), 2u32.into(), 0usize.into(), 0usize.into())\n    });\n    assert!(result\n        .expect_err(\"failed to catch wrong driver number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"expected different driver number\"));\n\n    // Tests with an incorrect subscribe number\n    kernel.add_expected_syscall(expected_syscall);\n    let result = catch_unwind(|| unsafe {\n        subscribe(1u32.into(), 7u32.into(), 0usize.into(), 0usize.into())\n    });\n    assert!(result\n        .expect_err(\"failed to catch wrong subscribe number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"expected different subscribe number\"));\n}\n\n// Test Subscribe with a driver number that does not exist.\n#[test]\nfn missing_driver() {\n    let _kernel = fake::Kernel::new();\n    let [r0, r1, r2, r3] =\n        unsafe { subscribe(1u32.into(), 2u32.into(), 0usize.into(), 0usize.into()) };\n    let (r0, r1, r2, r3): (u32, u32, usize, usize) = (\n        r0.try_into().expect(\"too large r0\"),\n        r1.try_into().expect(\"too large r1\"),\n        r2.into(),\n        r3.into(),\n    );\n    assert_eq!(r0, return_variant::FAILURE_2_U32.into());\n    assert_eq!(r1, ErrorCode::NoDevice as u32);\n    assert_eq!(r2, 0);\n    assert_eq!(r3, 0);\n}\n\n#[test]\nfn no_kernel() {\n    let result = catch_unwind(|| unsafe {\n        subscribe(1u32.into(), 2u32.into(), 0usize.into(), 0usize.into())\n    });\n    assert!(result\n        .expect_err(\"failed to catch missing kernel\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"no fake::Kernel exists\"));\n}\n\n#[test]\nfn skip_with_error() {\n    let kernel = fake::Kernel::new();\n    kernel.add_expected_syscall(ExpectedSyscall::Subscribe {\n        driver_num: 1,\n        subscribe_num: 2,\n        skip_with_error: Some(ErrorCode::NoAck),\n    });\n    unsafe extern \"C\" fn upcall_fn(_: u32, _: u32, _: u32, _: Register) {}\n    // Convert to a raw pointer to get a stable address.\n    let upcall_fn_ptr = upcall_fn as *const ();\n    let [r0, r1, r2, r3] = unsafe {\n        subscribe(\n            1u32.into(),\n            2u32.into(),\n            upcall_fn_ptr.into(),\n            1234usize.into(),\n        )\n    };\n    let (r0, r1, r2, r3): (u32, u32, *const (), usize) = (\n        r0.try_into().expect(\"too large r0\"),\n        r1.try_into().expect(\"too large r1\"),\n        r2.into(),\n        r3.into(),\n    );\n    assert_eq!(r0, return_variant::FAILURE_2_U32.into());\n    assert_eq!(r1, ErrorCode::NoAck as u32);\n    assert_eq!(r2, upcall_fn_ptr);\n    assert_eq!(r3, 1234);\n}\n\n// TODO: Move the syscall4_subscribe test into raw_syscalls_impl_tests.rs, once\n// raw_syscalls_impl_tests.rs has been created.\n\n#[test]\nfn syscall4_subscribe() {\n    let kernel = fake::Kernel::new();\n    unsafe {\n        fake::Syscalls::syscall4::<{ syscall_class::SUBSCRIBE }>([\n            1u32.into(),\n            2u32.into(),\n            0u32.into(),\n            0u32.into(),\n        ]);\n    }\n    assert_eq!(\n        kernel.take_syscall_log(),\n        [SyscallLogEntry::Subscribe {\n            driver_num: 1,\n            subscribe_num: 2,\n        }]\n    );\n}\n\n// Tests Subscribe with too large inputs (driver_num and subscribe_num)\n#[cfg(target_pointer_width = \"64\")]\n#[test]\nfn too_large_inputs() {\n    let _kernel = fake::Kernel::new();\n\n    let result = catch_unwind(|| unsafe {\n        subscribe(\n            (u32::MAX as usize + 1).into(),\n            2u32.into(),\n            0usize.into(),\n            0usize.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large driver number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large driver number\"));\n\n    let result = catch_unwind(|| unsafe {\n        subscribe(\n            1u32.into(),\n            (u32::MAX as usize + 1).into(),\n            0usize.into(),\n            0usize.into(),\n        )\n    });\n    assert!(result\n        .expect_err(\"failed to catch too-large subscribe number\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"Too large subscribe number\"));\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/yield_impl.rs",
    "content": "//! Implementations of Yield system calls.\n\nuse crate::kernel_data::{with_kernel_data, KERNEL_DATA};\nuse crate::{ExpectedSyscall, SyscallLogEntry};\n\n/// # Safety\n/// It must be valid to write a `libtock_platform::YieldNoWaitReturn` into the\n/// value pointed to by `return_ptr`. When `yield_no_wait` returns, the value\n/// pointed to by `return_ptr` will be set.\npub(super) unsafe fn yield_no_wait(return_ptr: *mut libtock_platform::YieldNoWaitReturn) {\n    let override_return = KERNEL_DATA.with(|refcell| {\n        let mut refmut = refcell.borrow_mut();\n        let kernel_data = refmut\n            .as_mut()\n            .expect(\"yield-no-wait called but no fake::Kernel exists\");\n\n        kernel_data.syscall_log.push(SyscallLogEntry::YieldNoWait);\n\n        match kernel_data.expected_syscalls.pop_front() {\n            None => None,\n            Some(ExpectedSyscall::YieldNoWait { override_return }) => override_return,\n            Some(expected_syscall) => expected_syscall.panic_wrong_call(\"yield-no-wait\"),\n        }\n    });\n\n    let upcall_ran = match invoke_next_upcall() {\n        true => libtock_platform::YieldNoWaitReturn::Upcall,\n        false => libtock_platform::YieldNoWaitReturn::NoUpcall,\n    };\n\n    unsafe {\n        core::ptr::write(return_ptr, override_return.unwrap_or(upcall_ran));\n    }\n}\n\npub(super) fn yield_wait() {\n    let skip_upcall = KERNEL_DATA.with(|refcell| {\n        let mut refmut = refcell.borrow_mut();\n        let kernel_data = refmut\n            .as_mut()\n            .expect(\"yield-wait called but no fake::Kernel exists\");\n\n        kernel_data.syscall_log.push(SyscallLogEntry::YieldWait);\n\n        match kernel_data.expected_syscalls.pop_front() {\n            None => false,\n            Some(ExpectedSyscall::YieldWait { skip_upcall }) => skip_upcall,\n            Some(expected_syscall) => expected_syscall.panic_wrong_call(\"yield-wait\"),\n        }\n    });\n\n    if skip_upcall {\n        return;\n    }\n\n    // In a real Tock system, a process that calls yield-wait with no queued\n    // upcalls would be put to sleep until an upcall was queued (e.g. by an\n    // interrupt). However, in this single-threaded test environment, there is\n    // no possibility a new upcall will be enqueued while we wait. Panicing is\n    // friendlier than hanging, so we panic if there's no upcall.\n    assert!(\n        invoke_next_upcall(),\n        \"yield-wait called with no queued upcall\"\n    );\n}\n\n// Pops the next upcall off the kernel data's upcall queue and invokes it, or\n// does nothing if the upcall queue was entry. The return value indicates\n// whether an upcall was run. Panics if no kernel data is present.\nfn invoke_next_upcall() -> bool {\n    let option_queue_entry =\n        with_kernel_data(|option_kernel_data| option_kernel_data.unwrap().upcall_queue.pop_front());\n    match option_queue_entry {\n        None => false,\n        Some(queue_entry) => {\n            unsafe {\n                queue_entry.upcall.invoke(queue_entry.args);\n            }\n            true\n        }\n    }\n}\n"
  },
  {
    "path": "unittest/src/fake/syscalls/yield_impl_tests.rs",
    "content": "use crate::kernel_data::with_kernel_data;\nuse crate::upcall::{Upcall, UpcallId, UpcallQueueEntry};\nuse crate::{fake, ExpectedSyscall, SyscallLogEntry};\nuse libtock_platform::{RawSyscalls, YieldNoWaitReturn};\nuse std::panic::catch_unwind;\n\nuse fake::syscalls::yield_impl::*;\n\n// Upcall function that copies its arguments into the [u32; 3] pointed to by\n// `output`. Used by multiple tests in this file.\nunsafe extern \"C\" fn copy_args(\n    arg0: u32,\n    arg1: u32,\n    arg2: u32,\n    output: libtock_platform::Register,\n) {\n    let output: *mut [u32; 3] = output.into();\n    unsafe {\n        *output = [arg0, arg1, arg2];\n    }\n}\n\n#[test]\nfn yield_no_wait_test() {\n    // Test calling yield_no_wait with no fake::Kernel present.\n    let result = catch_unwind(|| {\n        let mut return_value = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n        unsafe {\n            yield_no_wait(return_value.as_mut_ptr());\n        }\n    });\n    assert!(result\n        .expect_err(\"failed to catch missing fake::Kernel\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"no fake::Kernel\"));\n\n    let kernel = fake::Kernel::new();\n\n    // Test yield_no_wait with an empty upcall queue and empty expected syscall\n    // queue.\n    let mut return_value = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n    unsafe {\n        yield_no_wait(return_value.as_mut_ptr());\n    }\n    let return_value = unsafe { return_value.assume_init() };\n    fake::syscalls::assert_valid(return_value);\n    assert_eq!(return_value, YieldNoWaitReturn::NoUpcall);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n\n    // Test yield_no_wait with a return override in an expected syscall.\n    kernel.add_expected_syscall(ExpectedSyscall::YieldNoWait {\n        override_return: Some(YieldNoWaitReturn::Upcall),\n    });\n    let mut return_value = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n    unsafe {\n        yield_no_wait(return_value.as_mut_ptr());\n    }\n    let return_value = unsafe { return_value.assume_init() };\n    fake::syscalls::assert_valid(return_value);\n    assert_eq!(return_value, YieldNoWaitReturn::Upcall);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n\n    // Test yield_no_wait with a mismatched expected syscall.\n    kernel.add_expected_syscall(ExpectedSyscall::YieldWait { skip_upcall: false });\n    let result = catch_unwind(|| {\n        let mut return_value = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n        unsafe {\n            yield_no_wait(return_value.as_mut_ptr());\n        }\n    });\n    assert!(result\n        .expect_err(\"failed to catch mismatched expected syscall\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"yield-no-wait was called instead\"));\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n\n    // Upcall structures for using copy_args.\n    let mut output_array = [0u32; 3];\n    let upcall_id = UpcallId {\n        driver_num: 1,\n        subscribe_num: 2,\n    };\n    let upcall = Upcall {\n        fn_pointer: Some(copy_args),\n        data: (&mut output_array as *mut u32).into(),\n    };\n\n    // Test yield_no_wait with an upcall queued.\n    with_kernel_data(|option_kernel_data| {\n        option_kernel_data\n            .unwrap()\n            .upcall_queue\n            .push_back(UpcallQueueEntry {\n                args: (1, 2, 3),\n                id: upcall_id,\n                upcall,\n            });\n    });\n    let mut return_value = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n    unsafe {\n        yield_no_wait(return_value.as_mut_ptr());\n    }\n    assert_eq!(output_array, [1, 2, 3]);\n    let return_value = unsafe { return_value.assume_init() };\n    fake::syscalls::assert_valid(return_value);\n    assert_eq!(return_value, YieldNoWaitReturn::Upcall);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n\n    // Test yield_no_wait with an upcall queued and a return override in an\n    // expected syscall.\n    kernel.add_expected_syscall(ExpectedSyscall::YieldNoWait {\n        override_return: Some(YieldNoWaitReturn::NoUpcall),\n    });\n    with_kernel_data(|option_kernel_data| {\n        option_kernel_data\n            .unwrap()\n            .upcall_queue\n            .push_back(UpcallQueueEntry {\n                args: (4, 5, 6),\n                id: upcall_id,\n                upcall,\n            });\n    });\n    let mut return_value = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n    unsafe {\n        yield_no_wait(return_value.as_mut_ptr());\n    }\n    assert_eq!(output_array, [4, 5, 6]);\n    let return_value = unsafe { return_value.assume_init() };\n    fake::syscalls::assert_valid(return_value);\n    assert_eq!(return_value, YieldNoWaitReturn::NoUpcall);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n}\n\n#[test]\nfn yield_wait_test() {\n    // Test calling yield_wait with no fake::Kernel present.\n    assert!(catch_unwind(yield_wait)\n        .expect_err(\"failed to catch missing fake::Kernel\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"no fake::Kernel\"));\n\n    let kernel = fake::Kernel::new();\n\n    // Test yield_wait with a mismatched expected syscall.\n    kernel.add_expected_syscall(ExpectedSyscall::YieldNoWait {\n        override_return: None,\n    });\n    assert!(catch_unwind(yield_wait)\n        .expect_err(\"failed to catch mismatched expected syscall\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"yield-wait was called instead\"));\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldWait]);\n\n    // Upcall structures for using copy_args.\n    let mut output_array = [0u32; 3];\n    let upcall_id = UpcallId {\n        driver_num: 1,\n        subscribe_num: 2,\n    };\n    let upcall = Upcall {\n        fn_pointer: Some(copy_args),\n        data: (&mut output_array as *mut u32).into(),\n    };\n\n    // Test yield_wait with a skipped upcall in an expected syscall.\n    with_kernel_data(|option_kernel_data| {\n        option_kernel_data\n            .unwrap()\n            .upcall_queue\n            .push_back(UpcallQueueEntry {\n                args: (1, 2, 3),\n                id: upcall_id,\n                upcall,\n            });\n    });\n    kernel.add_expected_syscall(ExpectedSyscall::YieldWait { skip_upcall: true });\n    yield_wait();\n    assert_eq!(output_array, [0; 3]);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldWait]);\n\n    // Test that yield_wait correctly invokes a queued upcall. The upcall was\n    // queued for the previous test (which confirmed that skip_upcall works).\n    yield_wait();\n    assert_eq!(output_array, [1, 2, 3]);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldWait]);\n}\n\n// TODO: Move the yield1 and yield2 tests into a raw_syscalls_impl test module,\n// once all system calls have been implemented.\n\n#[test]\nfn yield1() {\n    let kernel = fake::Kernel::new();\n\n    #[cfg(target_pointer_width = \"64\")]\n    {\n        let result =\n            catch_unwind(|| unsafe { fake::Syscalls::yield1([(u32::MAX as usize + 1).into()]) });\n        assert!(result\n            .expect_err(\"failed to catch too large yield ID\")\n            .downcast_ref::<String>()\n            .expect(\"wrong panic payload type\")\n            .contains(\"too-large Yield ID\"));\n    }\n\n    // Call yield-no-wait through yield1, which is not valid.\n    let result = catch_unwind(|| unsafe { fake::Syscalls::yield1([0u32.into()]) });\n    assert!(result\n        .expect_err(\"failed to catch yield-no-wait without arg\")\n        .downcast_ref::<&'static str>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"yield-no-wait called without an argument\"));\n\n    // Test a successful invocation of yield-wait.\n    kernel.add_expected_syscall(ExpectedSyscall::YieldWait { skip_upcall: true });\n    unsafe {\n        fake::Syscalls::yield1([1u32.into()]);\n    }\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldWait]);\n\n    // Call yield1 with a yield ID that is unknown but which fits in a u32.\n    let result = catch_unwind(|| unsafe { fake::Syscalls::yield1([2u32.into()]) });\n    assert!(result\n        .expect_err(\"failed to catch incorrect yield ID -- new ID added?\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"unknown yield ID\"));\n}\n\n// Tests RawSyscalls::yield2's handling of bad yield IDs.\n#[test]\nfn yield2() {\n    let kernel = fake::Kernel::new();\n\n    #[cfg(target_pointer_width = \"64\")]\n    {\n        let result = catch_unwind(|| unsafe {\n            fake::Syscalls::yield2([(u32::MAX as usize + 1).into(), 0u32.into()])\n        });\n        assert!(result\n            .expect_err(\"failed to catch too large yield ID\")\n            .downcast_ref::<String>()\n            .expect(\"wrong panic payload type\")\n            .contains(\"too-large Yield ID\"));\n    }\n\n    // Test a successful invocation of yield-no-wait.\n    kernel.add_expected_syscall(ExpectedSyscall::YieldNoWait {\n        override_return: Some(YieldNoWaitReturn::Upcall),\n    });\n    let mut return_value = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();\n    unsafe {\n        fake::Syscalls::yield2([0u32.into(), return_value.as_mut_ptr().into()]);\n    }\n    let return_value = unsafe { return_value.assume_init() };\n    fake::syscalls::assert_valid(return_value);\n    assert_eq!(kernel.take_syscall_log(), [SyscallLogEntry::YieldNoWait]);\n    assert_eq!(return_value, YieldNoWaitReturn::Upcall);\n\n    // Call yield-wait through yield2, which should be rejected.\n    let result = catch_unwind(|| unsafe { fake::Syscalls::yield2([1u32.into(), 0u32.into()]) });\n    assert!(result\n        .expect_err(\"failed to catch yield-wait with arg\")\n        .downcast_ref::<&'static str>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"yield-wait called with an argument\"));\n\n    // Call yield2 with a yield ID that is unknown but which fits in a u32.\n    let result = catch_unwind(|| unsafe { fake::Syscalls::yield2([2u32.into(), 0u32.into()]) });\n    assert!(result\n        .expect_err(\"failed to catch incorrect yield ID -- new ID added?\")\n        .downcast_ref::<String>()\n        .expect(\"wrong panic payload type\")\n        .contains(\"unknown yield ID\"));\n}\n"
  },
  {
    "path": "unittest/src/fake/temperature/mod.rs",
    "content": "//! Fake implementation of the Temperature API, documented here:\n//! https://github.com/tock/tock/blob/master/doc/syscalls/60000_ambient_temperature.md\n//!\n//! Like the real API, `Temperature` controls a fake temperature sensor. It provides\n//! a function `set_value` used to immediately call an upcall with a temperature value read by the sensor\n//! and a function 'set_value_sync' used to call the upcall when the read command is received.\n\nuse crate::{DriverInfo, DriverShareRef};\nuse libtock_platform::{CommandReturn, ErrorCode};\nuse std::cell::Cell;\n\n// The `upcall_on_command` field is set to Some(value) if an upcall(with value as its argument) should be called when read command is received,\n// or None otherwise. It was needed for testing `read_sync` library function which simulates a synchronous temperature read,\n// because it was impossible to schedule an upcall during the `synchronous` read in other ways.\npub struct Temperature {\n    busy: Cell<bool>,\n    upcall_on_command: Cell<Option<i32>>,\n    share_ref: DriverShareRef,\n}\n\nimpl Temperature {\n    pub fn new() -> std::rc::Rc<Temperature> {\n        std::rc::Rc::new(Temperature {\n            busy: Cell::new(false),\n            upcall_on_command: Cell::new(None),\n            share_ref: Default::default(),\n        })\n    }\n\n    pub fn is_busy(&self) -> bool {\n        self.busy.get()\n    }\n    pub fn set_value(&self, value: i32) {\n        if self.busy.get() {\n            self.share_ref\n                .schedule_upcall(0, (value as u32, 0, 0))\n                .expect(\"Unable to schedule upcall\");\n            self.busy.set(false);\n        }\n    }\n    pub fn set_value_sync(&self, value: i32) {\n        self.upcall_on_command.set(Some(value));\n    }\n}\n\nimpl crate::fake::SyscallDriver for Temperature {\n    fn info(&self) -> DriverInfo {\n        DriverInfo::new(DRIVER_NUM).upcall_count(1)\n    }\n\n    fn register(&self, share_ref: DriverShareRef) {\n        self.share_ref.replace(share_ref);\n    }\n\n    fn command(&self, command_id: u32, _argument0: u32, _argument1: u32) -> CommandReturn {\n        match command_id {\n            EXISTS => crate::command_return::success(),\n\n            READ_TEMP => {\n                if self.busy.get() {\n                    return crate::command_return::failure(ErrorCode::Busy);\n                }\n                self.busy.set(true);\n                if let Some(val) = self.upcall_on_command.take() {\n                    self.set_value(val);\n                }\n                crate::command_return::success()\n            }\n            _ => crate::command_return::failure(ErrorCode::NoSupport),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests;\n// -----------------------------------------------------------------------------\n// Driver number and command IDs\n// -----------------------------------------------------------------------------\n\nconst DRIVER_NUM: u32 = 0x60000;\n\n// Command IDs\n\nconst EXISTS: u32 = 0;\nconst READ_TEMP: u32 = 1;\n"
  },
  {
    "path": "unittest/src/fake/temperature/tests.rs",
    "content": "use crate::fake::{self, SyscallDriver};\nuse fake::temperature::*;\nuse libtock_platform::{share, DefaultConfig, YieldNoWaitReturn};\n\n//Test the command implementation\n#[test]\nfn command() {\n    let temp = Temperature::new();\n\n    assert!(temp.command(EXISTS, 1, 2).is_success());\n\n    assert!(temp.command(READ_TEMP, 0, 0).is_success());\n\n    assert_eq!(\n        temp.command(READ_TEMP, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n\n    temp.set_value(100);\n    assert!(temp.command(READ_TEMP, 0, 1).is_success());\n    temp.set_value(100);\n\n    temp.set_value_sync(100);\n    assert!(temp.command(READ_TEMP, 0, 1).is_success());\n    assert!(temp.command(READ_TEMP, 0, 1).is_success());\n}\n\n// Integration test that verifies Temperature works with fake::Kernel and\n// libtock_platform::Syscalls.\n#[test]\nfn kernel_integration() {\n    use libtock_platform::Syscalls;\n    let kernel = fake::Kernel::new();\n    let temp = Temperature::new();\n    kernel.add_driver(&temp);\n    assert!(fake::Syscalls::command(DRIVER_NUM, EXISTS, 1, 2).is_success());\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_TEMP, 0, 0).is_success());\n    assert_eq!(\n        fake::Syscalls::command(DRIVER_NUM, READ_TEMP, 0, 0).get_failure(),\n        Some(ErrorCode::Busy)\n    );\n    temp.set_value(100);\n    assert!(fake::Syscalls::command(DRIVER_NUM, READ_TEMP, 0, 1).is_success());\n\n    let listener = Cell::<Option<(u32,)>>::new(None);\n    share::scope(|subscribe| {\n        assert_eq!(\n            fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener),\n            Ok(())\n        );\n\n        temp.set_value(100);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n        assert_eq!(listener.get(), Some((100,)));\n\n        temp.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall);\n\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_TEMP, 0, 1).is_success());\n        temp.set_value(200);\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n\n        temp.set_value_sync(200);\n        assert!(fake::Syscalls::command(DRIVER_NUM, READ_TEMP, 0, 1).is_success());\n        assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall);\n    });\n}\n"
  },
  {
    "path": "unittest/src/kernel_data.rs",
    "content": "//! `KernelData` contains the data corresponding to a `fake::Kernel`. It is\n//! stored in the thread-local variable `KERNEL_DATA`.\n//!\n//! The data is stored separately from the `fake::Kernel` because in addition to\n//! being accessed through the `fake::Kernel`, it is also accessed by\n//! `fake::Syscalls` and `upcall::schedule`. `fake::Syscalls` is reentrant (a\n//! Yield invocation can run a callback that executes another system call),\n//! which easily results in messy code. To keep things understandable, code that\n//! uses `KERNEL_DATA` should avoid calling user-supplied functions (such as\n//! upcalls) while holding a reference to `KERNEL_DATA`.\n\nuse std::cell::RefCell;\n\npub(crate) struct KernelData {\n    pub allow_db: crate::allow_db::AllowDb,\n\n    // The location of the call to `fake::Kernel::new`. Used in the event a\n    // duplicate `fake::Kernel` is created to tell the user which kernel they\n    // did not clean up in a unit test.\n    pub create_location: &'static std::panic::Location<'static>,\n\n    pub drivers: std::collections::HashMap<u32, DriverData>,\n    pub expected_syscalls: std::collections::VecDeque<crate::ExpectedSyscall>,\n    pub syscall_log: Vec<crate::SyscallLogEntry>,\n    pub upcall_queue: crate::upcall::UpcallQueue,\n    pub memory_break: *const u8,\n}\n\n// KERNEL_DATA is set to Some in `fake::Kernel::new` and set to None when the\n// `fake::Kernel` is dropped.\nthread_local!(pub(crate) static KERNEL_DATA: RefCell<Option<KernelData>> = const { RefCell::new(None) });\n\n// Convenience function to get mutable access to KERNEL_DATA.\npub(crate) fn with_kernel_data<F: FnOnce(Option<&mut KernelData>) -> R, R>(f: F) -> R {\n    KERNEL_DATA.with(|refcell| f(refcell.borrow_mut().as_mut()))\n}\n\n// Per-driver data stored in KernelData.\npub struct DriverData {\n    pub driver: std::rc::Rc<dyn crate::fake::SyscallDriver>,\n    pub num_upcalls: u32,\n\n    // Currently-valid upcalls passed to Subscribe. The key is the subscribe\n    // number.\n    pub upcalls: std::collections::HashMap<u32, crate::upcall::Upcall>,\n}\n"
  },
  {
    "path": "unittest/src/lib.rs",
    "content": "//! `libtock_unittest` provides testing tools needed by `libtock-rs`'s own unit\n//! tests as well as unit tests of code that uses `libtock-rs`.\n\n#![deny(unsafe_op_in_unsafe_fn)]\n\nmod allow_db;\npub mod command_return;\nmod driver_info;\n#[cfg(not(miri))]\nmod exit_test;\nmod expected_syscall;\npub mod fake;\nmod kernel_data;\nmod share_data;\nmod syscall_log;\npub mod upcall;\n\npub use allow_db::{RoAllowBuffer, RwAllowBuffer};\npub use driver_info::DriverInfo;\n#[cfg(not(miri))]\npub use exit_test::{exit_test, ExitCall};\npub use expected_syscall::ExpectedSyscall;\npub use share_data::DriverShareRef;\npub use syscall_log::SyscallLogEntry;\n\n#[cfg(test)]\nmod allow_db_test;\n"
  },
  {
    "path": "unittest/src/share_data.rs",
    "content": "use crate::kernel_data::with_kernel_data;\nuse crate::upcall::{UpcallId, UpcallQueueEntry};\nuse std::cell::Cell;\n\n/// A reference used by a `fake::SyscallDriver` to access data shared between it\n/// and the `fake::Kernel`, such as upcalls.\n///\n/// A `Default`-initialized `DriverShareRef` links to an empty share. It can be\n/// used as normal, but is generally a no-op. This allows `fake::SyscallDriver`\n/// implementations to store a `DriverShareRef` directly, rather than having to\n/// contain a `Cell<Option<DriverShareRef>>`.\n#[derive(Default)]\npub struct DriverShareRef {\n    pub(crate) driver_num: Cell<u32>,\n}\n\nimpl DriverShareRef {\n    /// Replaces this DriverShareRef with another. `fake:SyscallDrivers` can use\n    /// `replace` to implement `register` to avoid having to store their\n    /// `DriverShareRef` inside a `Cell`.\n    pub fn replace(&self, new: Self) {\n        self.driver_num.set(new.driver_num.get());\n    }\n\n    /// Schedules the upcall with the specified subscribe number. Like the real\n    /// kernel, this does nothing if there is no upcall with number\n    /// `subscribe_num` or the upcall is the null upcall.\n    pub fn schedule_upcall(\n        &self,\n        subscribe_num: u32,\n        args: (u32, u32, u32),\n    ) -> Result<(), InvalidSubscribeNum> {\n        with_kernel_data(|kernel_data| {\n            let kernel_data = match kernel_data {\n                Some(kernel_data) => kernel_data,\n                None => return Ok(()),\n            };\n            let driver_data = kernel_data\n                .drivers\n                .get(&self.driver_num.get())\n                .expect(\"DriverShareRef: registered but nonexistent?\");\n            if subscribe_num >= driver_data.num_upcalls {\n                return Err(InvalidSubscribeNum {\n                    upcall_count: driver_data.num_upcalls,\n                    requested: subscribe_num,\n                });\n            }\n            let upcall = match driver_data.upcalls.get(&subscribe_num) {\n                Some(&upcall) => upcall,\n                None => return Ok(()),\n            };\n            // Don't bother queueing a null upcall, as they don't do anything\n            // when invoked anyway, and the core kernel does not queue them\n            // either.\n            if upcall.is_null() {\n                return Ok(());\n            }\n            kernel_data.upcall_queue.push_back(UpcallQueueEntry {\n                args,\n                id: UpcallId {\n                    driver_num: self.driver_num.get(),\n                    subscribe_num,\n                },\n                upcall,\n            });\n            Ok(())\n        })\n    }\n}\n\n#[derive(Debug, Eq, PartialEq, thiserror::Error)]\n#[error(\"Upcall number {requested} too large, expected < {upcall_count}.\")]\npub struct InvalidSubscribeNum {\n    requested: u32,\n    upcall_count: u32,\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::upcall::Upcall;\n    use crate::DriverInfo;\n    use libtock_platform::Register;\n    use std::ptr::fn_addr_eq;\n    use std::rc::Rc;\n\n    #[derive(Default)]\n    struct MockDriver {\n        share_ref: DriverShareRef,\n    }\n    impl crate::fake::SyscallDriver for MockDriver {\n        fn info(&self) -> DriverInfo {\n            DriverInfo::new(1).upcall_count(10)\n        }\n        fn register(&self, share_ref: DriverShareRef) {\n            self.share_ref.replace(share_ref);\n        }\n        fn command(&self, _: u32, _: u32, _: u32) -> libtock_platform::CommandReturn {\n            crate::command_return::failure(libtock_platform::ErrorCode::NoSupport)\n        }\n    }\n\n    #[test]\n    fn schedule_errors() {\n        let mock_driver = Rc::new(MockDriver::default());\n        let kernel = crate::fake::Kernel::new();\n        kernel.add_driver(&mock_driver);\n        assert_eq!(\n            mock_driver.share_ref.schedule_upcall(10, (3, 4, 5)),\n            Err(InvalidSubscribeNum {\n                upcall_count: 10,\n                requested: 10\n            })\n        );\n    }\n\n    #[test]\n    fn schedule_success() {\n        let mock_driver = Rc::new(MockDriver::default());\n        let kernel = crate::fake::Kernel::new();\n        kernel.add_driver(&mock_driver);\n\n        // Call schedule with no registered upcall.\n        assert_eq!(mock_driver.share_ref.schedule_upcall(2, (3, 4, 5)), Ok(()));\n        with_kernel_data(|kernel_data| {\n            let kernel_data = kernel_data.unwrap();\n\n            // There was no upcall to schedule, so the queue should still be\n            // empty.\n            assert!(kernel_data.upcall_queue.is_empty());\n\n            // Register a null upcall.\n            kernel_data.drivers.get_mut(&1).unwrap().upcalls.insert(\n                2,\n                Upcall {\n                    fn_pointer: None,\n                    data: 1234u32.into(),\n                },\n            );\n        });\n        // Call schedule again. This should still do nothing, because the upcall\n        // is a null upcall.\n        assert_eq!(mock_driver.share_ref.schedule_upcall(2, (3, 4, 5)), Ok(()));\n        unsafe extern \"C\" fn upcall(_: u32, _: u32, _: u32, _: libtock_platform::Register) {}\n        // Cast to a pointer to get a stable address.\n        let upcall_ptr = upcall as unsafe extern \"C\" fn(u32, u32, u32, Register);\n        with_kernel_data(|kernel_data| {\n            let kernel_data = kernel_data.unwrap();\n\n            // Verify the upcall was not queued.\n            assert!(kernel_data.upcall_queue.is_empty());\n\n            // Register a non-null upcall.\n            kernel_data.drivers.get_mut(&1).unwrap().upcalls.insert(\n                2,\n                Upcall {\n                    fn_pointer: Some(upcall_ptr),\n                    data: 1111usize.into(),\n                },\n            );\n        });\n        // Call schedule again. This should schedule the upcall.\n        assert_eq!(mock_driver.share_ref.schedule_upcall(2, (3, 4, 5)), Ok(()));\n        with_kernel_data(|kernel_data| {\n            let kernel_data = kernel_data.unwrap();\n\n            // Verify the upcall was queued.\n            assert_eq!(kernel_data.upcall_queue.len(), 1);\n            let upcall_queue_entry = kernel_data.upcall_queue.front().expect(\"Upcall not queued\");\n            assert_eq!(upcall_queue_entry.args, (3, 4, 5));\n            assert_eq!(\n                upcall_queue_entry.id,\n                UpcallId {\n                    driver_num: 1,\n                    subscribe_num: 2\n                }\n            );\n            assert!(fn_addr_eq(\n                upcall_queue_entry.upcall.fn_pointer.unwrap(),\n                upcall_ptr\n            ));\n            let data: usize = upcall_queue_entry.upcall.data.into();\n            assert_eq!(data, 1111);\n\n            // Register a non-null upcall.\n            kernel_data.drivers.get_mut(&1).unwrap().upcalls.insert(\n                2,\n                Upcall {\n                    fn_pointer: Some(upcall_ptr),\n                    data: 2222u32.into(),\n                },\n            );\n        });\n        // Call schedule again. This should schedule another upcall, after the\n        // first.\n        assert_eq!(\n            mock_driver.share_ref.schedule_upcall(2, (30, 40, 50)),\n            Ok(())\n        );\n        with_kernel_data(|kernel_data| {\n            let kernel_data = kernel_data.unwrap();\n\n            // Very the upcall was queued.\n            assert_eq!(kernel_data.upcall_queue.len(), 2);\n            let front_queue_entry = kernel_data.upcall_queue.front().expect(\"Upcall not queued\");\n            assert_eq!(front_queue_entry.args, (3, 4, 5));\n            assert_eq!(\n                front_queue_entry.id,\n                UpcallId {\n                    driver_num: 1,\n                    subscribe_num: 2\n                }\n            );\n            assert!(fn_addr_eq(\n                front_queue_entry.upcall.fn_pointer.unwrap(),\n                upcall_ptr\n            ));\n            let front_data: usize = front_queue_entry.upcall.data.into();\n            assert_eq!(front_data, 1111);\n            let back_queue_entry = kernel_data.upcall_queue.back().expect(\"Upcall not queued\");\n            assert_eq!(back_queue_entry.args, (30, 40, 50));\n            assert_eq!(\n                back_queue_entry.id,\n                UpcallId {\n                    driver_num: 1,\n                    subscribe_num: 2\n                }\n            );\n            assert!(fn_addr_eq(\n                back_queue_entry.upcall.fn_pointer.unwrap(),\n                upcall_ptr\n            ));\n            let back_data: usize = back_queue_entry.upcall.data.into();\n            assert_eq!(back_data, 2222);\n        });\n    }\n}\n"
  },
  {
    "path": "unittest/src/syscall_log.rs",
    "content": "use libtock_platform::Register;\n\n/// SyscallLogEntry represents a system call made during test execution.\n#[derive(Debug, Eq, PartialEq)]\npub enum SyscallLogEntry {\n    // -------------------------------------------------------------------------\n    // Yield\n    // -------------------------------------------------------------------------\n    YieldNoWait,\n\n    YieldWait,\n\n    // -------------------------------------------------------------------------\n    // Subscribe\n    // -------------------------------------------------------------------------\n    Subscribe {\n        driver_num: u32,\n        subscribe_num: u32,\n    },\n\n    // -------------------------------------------------------------------------\n    // Command\n    // -------------------------------------------------------------------------\n    Command {\n        driver_id: u32,\n        command_id: u32,\n        argument0: u32,\n        argument1: u32,\n    },\n\n    // -------------------------------------------------------------------------\n    // Read-Only Allow\n    // -------------------------------------------------------------------------\n    AllowRo {\n        driver_num: u32,\n        buffer_num: u32,\n        len: usize,\n    },\n\n    // -------------------------------------------------------------------------\n    // Read-Write Allow\n    // -------------------------------------------------------------------------\n    AllowRw {\n        driver_num: u32,\n        buffer_num: u32,\n        len: usize,\n    },\n\n    // -------------------------------------------------------------------------\n    // Memop\n    // -------------------------------------------------------------------------\n    Memop {\n        memop_num: u32,\n        argument0: Register, // Necessary for Miri ptr provenance of brk()\n    },\n    // TODO: Add Exit.\n}\n"
  },
  {
    "path": "unittest/src/upcall.rs",
    "content": "/// Raw upcall data, as it was passed to Subscribe. This upcall is not\n/// guaranteed to still be valid.\n#[derive(Clone, Copy)]\npub struct Upcall {\n    pub fn_pointer: Option<unsafe extern \"C\" fn(u32, u32, u32, libtock_platform::Register)>,\n    pub data: libtock_platform::Register,\n}\n\nimpl Upcall {\n    /// Returns true if this is a null callback, false otherwise.\n    pub fn is_null(&self) -> bool {\n        self.fn_pointer.is_none()\n    }\n\n    /// # Safety\n    /// An upcall may only be invoked if it is still active. As described in TRD\n    /// 104, an upcall is still active if it has not been replaced by another\n    /// Subscribe call with the same upcall ID. All upcalls in the upcall queue\n    /// in KernelData are active.\n    pub unsafe fn invoke(&self, args: (u32, u32, u32)) {\n        if let Some(fn_pointer) = self.fn_pointer {\n            unsafe {\n                fn_pointer(args.0, args.1, args.2, self.data);\n            }\n        }\n    }\n}\n\n// The type of the upcall queue in KernelData. Contains queued upcalls, which\n// are waiting to be invoked during a Yield call.\n//\n// Based on this discussion:\n// https://mailman.stanford.edu/pipermail/tock-version2/2020-November/000025.html\n// this queue is a FIFO queue. New entries should be pushed to the back of the\n// queue, and Yield should invoke upcalls starting with the front of the queue.\n//\n// A note on performance: When an upcall is replaced via Subscribe and becomes\n// invalid, Subscribe has to iterate through this queue and remove all instances\n// of that upcall. That takes linear time in the length of the queue, so it can\n// be slow if the queue is long. A long queue is unrealistic, so we shouldn't\n// need a long queue in test cases, so that is acceptable. There are alternative\n// data structures that avoid that slowdown, but they are more complex and\n// likely slower in the common case.\npub(crate) type UpcallQueue = std::collections::VecDeque<UpcallQueueEntry>;\n\n// An entry in the fake kernel's upcall queue.\npub(crate) struct UpcallQueueEntry {\n    pub args: (u32, u32, u32),\n    pub id: UpcallId,\n    pub upcall: Upcall,\n}\n\n#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]\npub(crate) struct UpcallId {\n    pub driver_num: u32,\n    pub subscribe_num: u32,\n}\n"
  }
]