From ff12bd0818c4001b0efc196648d027e5ad5460f4 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Wed, 9 Aug 2023 22:42:03 -0400 Subject: [PATCH 01/16] Add test-runner as a dependency and fix build errs Luckily, Cargo doesn't mind circular dev-dependencies and we can patch to ensure it's using the same version. We can also leave this as a `git = "..."` dependency if we want, since it's a dev dependency. --- Cargo.toml | 4 ++- ctru-rs/Cargo.toml | 8 +++-- ctru-rs/src/lib.rs | 8 ++--- ctru-rs/src/test_runner.rs | 73 -------------------------------------- ctru-sys/Cargo.toml | 2 +- ctru-sys/build.rs | 3 +- ctru-sys/src/lib.rs | 8 +++++ 7 files changed, 22 insertions(+), 84 deletions(-) delete mode 100644 ctru-rs/src/test_runner.rs diff --git a/Cargo.toml b/Cargo.toml index 33abd1c..065d39b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,7 @@ default-members = ["ctru-rs", "ctru-sys"] resolver = "2" [patch.'https://github.com/rust3ds/ctru-rs'] -# Make sure all dependencies use the local ctru-sys package +# Make sure all dependencies use the local packages. This is needed for things +# like pthread-3ds that rely on ctru-sys, and test-runner which relies on ctru-rs +ctru-rs = { path = "ctru-rs" } ctru-sys = { path = "ctru-sys" } diff --git a/ctru-rs/Cargo.toml b/ctru-rs/Cargo.toml index 0523b27..bdd7a4d 100644 --- a/ctru-rs/Cargo.toml +++ b/ctru-rs/Cargo.toml @@ -29,13 +29,15 @@ widestring = "0.2.2" toml = "0.5" [dev-dependencies] +bytemuck = "1.12.3" +cfg-if = "1.0.0" ferris-says = "0.2.1" futures = "0.3" +lewton = "0.10.2" +# TODO: switch to rust3ds org once migrated there. Also, rename? +test-runner = { git = "https://github.com/ian-h-chamberlain/test-runner-3ds" } time = "0.3.7" tokio = { version = "1.16", features = ["rt", "time", "sync", "macros"] } -cfg-if = "1.0.0" -bytemuck = "1.12.3" -lewton = "0.10.2" [features] default = ["romfs", "big-stack"] diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index ecc7dd9..87e1343 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -22,7 +22,7 @@ #![feature(custom_test_frameworks)] #![feature(try_trait_v2)] #![feature(allocator_api)] -#![test_runner(test_runner::run)] +#![test_runner(test_runner::run_gdb)] // TODO: does this make sense to have configurable? #![doc( html_favicon_url = "https://user-images.githubusercontent.com/11131775/225929072-2fa1741c-93ae-4b47-9bdf-af70f3d59910.png" )] @@ -73,9 +73,10 @@ pub fn use_panic_handler() { /// When `test` is enabled, this function will be ignored. #[cfg(not(test))] fn panic_hook_setup() { - use crate::services::hid::{Hid, KeyPad}; use std::panic::PanicInfo; + use crate::services::hid::{Hid, KeyPad}; + let main_thread = std::thread::current().id(); // Panic Hook setup @@ -110,7 +111,4 @@ pub mod mii; pub mod prelude; pub mod services; -#[cfg(test)] -mod test_runner; - pub use crate::error::{Error, Result}; diff --git a/ctru-rs/src/test_runner.rs b/ctru-rs/src/test_runner.rs deleted file mode 100644 index 97aa5f4..0000000 --- a/ctru-rs/src/test_runner.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Custom test runner for building/running unit tests on the 3DS. - -extern crate test; - -use std::io; - -use test::{ColorConfig, OutputFormat, TestDescAndFn, TestFn, TestOpts}; - -use crate::prelude::*; - -/// A custom runner to be used with `#[test_runner]`. This simple implementation -/// runs all tests in series, "failing" on the first one to panic (really, the -/// panic is just treated the same as any normal application panic). -pub(crate) fn run(tests: &[&TestDescAndFn]) { - let gfx = Gfx::new().unwrap(); - let mut hid = Hid::new().unwrap(); - let apt = Apt::new().unwrap(); - - let mut top_screen = gfx.top_screen.borrow_mut(); - top_screen.set_wide_mode(true); - let _console = Console::new(top_screen); - - let opts = TestOpts { - force_run_in_process: true, - run_tests: true, - // TODO: color doesn't work because of TERM/TERMINFO. - // With RomFS we might be able to fake this out nicely... - color: ColorConfig::AutoColor, - format: OutputFormat::Pretty, - // Hopefully this interface is more stable vs specifying individual options, - // and parsing the empty list of args should always work, I think. - // TODO Ideally we could pass actual std::env::args() here too - ..test::test::parse_opts(&[]).unwrap().unwrap() - }; - // Use the default test implementation with our hardcoded options - let _success = run_static_tests(&opts, tests).unwrap(); - - // Make sure the user can actually see the results before we exit - println!("Press START to exit."); - - while apt.main_loop() { - gfx.wait_for_vblank(); - - hid.scan_input(); - if hid.keys_down().contains(KeyPad::START) { - break; - } - } -} - -/// Adapted from [`test::test_main_static`] and [`test::make_owned_test`]. -fn run_static_tests(opts: &TestOpts, tests: &[&TestDescAndFn]) -> io::Result { - let tests = tests.iter().map(make_owned_test).collect(); - test::run_tests_console(opts, tests) -} - -/// Clones static values for putting into a dynamic vector, which test_main() -/// needs to hand out ownership of tests to parallel test runners. -/// -/// This will panic when fed any dynamic tests, because they cannot be cloned. -fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn { - match test.testfn { - TestFn::StaticTestFn(f) => TestDescAndFn { - testfn: TestFn::StaticTestFn(f), - desc: test.desc.clone(), - }, - TestFn::StaticBenchFn(f) => TestDescAndFn { - testfn: TestFn::StaticBenchFn(f), - desc: test.desc.clone(), - }, - _ => panic!("non-static tests passed to test::test_main_static"), - } -} diff --git a/ctru-sys/Cargo.toml b/ctru-sys/Cargo.toml index 0041d0c..552f206 100644 --- a/ctru-sys/Cargo.toml +++ b/ctru-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ctru-sys" version = "22.2.0+2.2.2-1" -authors = [ "Rust3DS Org", "Ronald Kinard " ] +authors = ["Rust3DS Org", "Ronald Kinard "] description = "Raw bindings to libctru" repository = "https://github.com/rust3ds/ctru-rs" keywords = ["3ds", "libctru"] diff --git a/ctru-sys/build.rs b/ctru-sys/build.rs index 7c55caa..0bf3369 100644 --- a/ctru-sys/build.rs +++ b/ctru-sys/build.rs @@ -68,7 +68,8 @@ fn check_libctru_version() -> Result<(String, String, String), Box> { if lib_version != crate_built_version { return Err(format!( "libctru version is {lib_version} but this crate was built for {crate_built_version}" - ))?; + ) + .into()); } let Output { stdout, .. } = Command::new(pacman) diff --git a/ctru-sys/src/lib.rs b/ctru-sys/src/lib.rs index 474e1d2..98ffb1f 100644 --- a/ctru-sys/src/lib.rs +++ b/ctru-sys/src/lib.rs @@ -16,3 +16,11 @@ pub use result::*; pub unsafe fn errno() -> s32 { *__errno() } + +// TODO: not sure if there's a better way to do this, but I have gotten myself +// with this a couple times so having the hint seems nice to have. +#[cfg(test)] +compile_error!(concat!( + "ctru-sys doesn't have tests and its lib test will fail to build at link time. ", + "Try specifying `--package ctru-rs` to build those tests.", +)); From 3a74c5bcaf875eae6144867bb66afb50e04dd414 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Wed, 9 Aug 2023 23:03:55 -0400 Subject: [PATCH 02/16] Use actions from test-runner-3ds repo Actually run tests now!!! --- .github/actions/setup/action.yml | 46 -------------------------------- .github/workflows/ci.yml | 45 ++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 59 deletions(-) delete mode 100644 .github/actions/setup/action.yml diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml deleted file mode 100644 index a86d6f6..0000000 --- a/.github/actions/setup/action.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Setup -description: Set up CI environment for Rust + 3DS development - -inputs: - toolchain: - description: The Rust toolchain to use for the steps - required: true - default: nightly - -runs: - using: composite - steps: - # https://github.com/nektos/act/issues/917#issuecomment-1074421318 - - if: ${{ env.ACT }} - shell: bash - name: Hack container for local development - run: | - curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - - sudo apt-get install -y nodejs - - - name: Setup default Rust toolchain - # Use this helper action so we get matcher support - # https://github.com/actions-rust-lang/setup-rust-toolchain/pull/15 - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - components: clippy, rustfmt, rust-src - toolchain: ${{ inputs.toolchain }} - - - name: Install build tools for host - shell: bash - run: sudo apt-get update && sudo apt-get install -y build-essential - - - name: Install cargo-3ds - uses: actions-rs/cargo@v1 - with: - command: install - # TODO: this should probably just be a released version from crates.io - # once cargo-3ds gets published somewhere... - args: >- - --git https://github.com/rust3ds/cargo-3ds - --rev 78a652fdfb01e2614a792d1a56b10c980ee1dae9 - - - name: Set PATH to include devkitARM - shell: bash - # For some reason devkitARM/bin is not part of the default PATH in the container - run: echo "${DEVKITARM}/bin" >> $GITHUB_PATH diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee97ccc..08c26f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,11 +33,13 @@ jobs: - name: Checkout branch uses: actions/checkout@v2 - - uses: ./.github/actions/setup + # TODO update to to rust3ds/$something once migrated. Also, this is a bit + # wordy, it might be nicer to put the actions at the top level of the repo + - uses: ian-h-chamberlain/test-runner-3ds/.github/actions/setup@v1 with: toolchain: ${{ matrix.toolchain }} - - name: Hide duplicate warnings from lint job + - name: Hide duplicate warnings from nightly if: ${{ matrix.toolchain == 'nightly' }} run: | echo "::remove-matcher owner=clippy::" @@ -46,14 +48,13 @@ jobs: - name: Check formatting run: cargo fmt --all --verbose -- --check - - name: Cargo check - run: cargo 3ds clippy --color=always --verbose --all-targets - # --deny=warnings would be nice, but can easily break CI for new clippy - # lints getting added. I'd also like to use Github's "inline warnings" - # feature, but https://github.com/actions/runner/issues/2341 means we - # can't have both that *and* colored output. + - name: Cargo check ctru-sys (without tests) + run: cargo 3ds clippy --package ctru-sys --color=always --verbose - doctests: + - name: Cargo check ctru-rs (including tests) + run: cargo 3ds clippy --package ctru-rs --color=always --verbose --all-targets + + test: strategy: matrix: toolchain: @@ -66,15 +67,33 @@ jobs: - name: Checkout branch uses: actions/checkout@v2 - - uses: ./.github/actions/setup + - uses: ian-h-chamberlain/test-runner-3ds/.github/actions/setup@v1 with: toolchain: ${{ matrix.toolchain }} - name: Hide duplicated warnings from lint job run: echo "::remove-matcher owner=clippy::" + - name: Build lib + integration tests + # Technically this will only build one 3dsx even if there's more than one executable, + # but we only run the `.elf` outputs so it doesn't really matter. + run: cargo 3ds test --no-run --tests --package ctru-rs + - name: Build doc tests - run: cargo 3ds test --doc --verbose + run: cargo 3ds test --no-run --doc + + - name: Run lib + integration tests + uses: ian-h-chamberlain/test-runner-3ds/.github/actions/citra@v1 + with: + executable: ./target/armv6k-nintendo-3ds/debug/deps/*.elf + + # TODO: run doc tests https://github.com/ian-h-chamberlain/test-runner-3ds/issues/4 - # TODO: it would be nice to actually build 3dsx for examples/tests, etc. - # and run it somehow, but exactly how remains to be seen. + - name: Upload citra logs and capture videos + uses: actions/upload-artifact@v3 + if: success() || failure() # always run unless the workflow was cancelled + with: + name: citra-logs-${{ matrix.toolchain }} + path: | + target/armv6k-nintendo-3ds/debug/deps/*.txt + target/armv6k-nintendo-3ds/debug/deps/*.webm From 7cd4ae0deb994afbb025c4e667df7a30e04b609b Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Wed, 9 Aug 2023 23:47:25 -0400 Subject: [PATCH 03/16] Fix link error with multiply-defined stack size We don't want to define __stacksize__ more than once, since the linker will reject it even if the definition is the same. For some reason this seems to link fine with devkitARM release 62, but not 61 (which is the version in the latest upstream docker images). This is probably safer anyway, since there are technically two copies of `ctru-rs` at play here. --- ctru-rs/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index 87e1343..aeda735 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -18,7 +18,6 @@ #![crate_type = "rlib"] #![crate_name = "ctru"] #![warn(missing_docs)] -#![feature(test)] #![feature(custom_test_frameworks)] #![feature(try_trait_v2)] #![feature(allocator_api)] @@ -40,7 +39,11 @@ extern crate shim_3ds; /// /// This value was chosen to support crate dependencies which expected more stack than provided. It's suggested to use less stack if possible. #[no_mangle] -#[cfg(feature = "big-stack")] +// When building lib tests, we don't want to redefine the same symbol twice, +// since ctru-rs is both the crate under test and a dev-dependency (non-test). +// We might also be able to use #[linkage] for similar effect, but this way +// works without depending on another unstable feature. +#[cfg(all(feature = "big-stack", not(test)))] static __stacksize__: usize = 2 * 1024 * 1024; // 2MB macro_rules! from_impl { From 318c341271fb8c09d553d0a70ceddeb472b51d9e Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Thu, 10 Aug 2023 00:05:36 -0400 Subject: [PATCH 04/16] Fix test failures from running tests These mostly have to do with the test environment itself, so we might not want to keep these changes, if they are fixed in the runner. --- ctru-rs/src/services/gfx.rs | 7 ++++--- ctru-rs/src/services/romfs.rs | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ctru-rs/src/services/gfx.rs b/ctru-rs/src/services/gfx.rs index 68ac957..77198cf 100644 --- a/ctru-rs/src/services/gfx.rs +++ b/ctru-rs/src/services/gfx.rs @@ -344,7 +344,7 @@ impl Gfx { /// // Simple main loop. /// while apt.main_loop() { /// // Main program logic - /// + /// /// // Wait for the screens to refresh. /// // This blocks the current thread to make it run at 60Hz. /// gfx.wait_for_vblank(); @@ -499,7 +499,8 @@ mod tests { #[test] fn gfx_duplicate() { - // We don't need to build a `Gfx` because the test runner has one already - assert!(matches!(Gfx::new(), Err(Error::ServiceAlreadyActive))); + // NOTE: this will fail if using the console test runner, since that creates + // a Gfx as part of its test setup. + Gfx::new().unwrap(); } } diff --git a/ctru-rs/src/services/romfs.rs b/ctru-rs/src/services/romfs.rs index e6f1c3b..bc0896d 100644 --- a/ctru-rs/src/services/romfs.rs +++ b/ctru-rs/src/services/romfs.rs @@ -84,6 +84,7 @@ mod tests { use super::*; #[test] + #[ignore = "library test .elf doesn't have the romfs in it. citra runner needs to support 3dsx"] fn romfs_counter() { let _romfs = RomFS::new().unwrap(); let value = *ROMFS_ACTIVE.lock().unwrap(); From 685ea7f16816dc74758bfc04a1e79ed6b6122778 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Thu, 10 Aug 2023 09:07:08 -0400 Subject: [PATCH 05/16] Bump toolchain version by 1 day The old `cargo-3ds` we were using didn't care about the commit date being 05-30, but the new one used by the `test-runner` action does. Since the rustc version is one day older than the toolchain date, we should be able to work with just the 06-01 toolchain instead. --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08c26f9..08c9a44 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,8 @@ jobs: strategy: matrix: toolchain: - # Run against a "known good" nightly - - nightly-2023-05-31 + # Run against a "known good" nightly. Rustc version is 1 day behind the toolchain date + - nightly-2023-06-01 # Check for breakage on latest nightly - nightly @@ -58,7 +58,7 @@ jobs: strategy: matrix: toolchain: - - nightly-2023-05-31 + - nightly-2023-06-01 - nightly continue-on-error: ${{ matrix.toolchain == 'nightly' }} runs-on: ubuntu-latest From 1905c0ca1b1b520765a3f925ea5016a61dbba352 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sun, 24 Sep 2023 17:46:29 -0400 Subject: [PATCH 06/16] More cleanup after updates to test-runner-3ds --- .github/workflows/ci.yml | 37 +++++++++++++-------------------- ctru-rs/examples/hello-world.rs | 2 ++ ctru-rs/src/services/gfx.rs | 8 ++++--- ctru-rs/src/services/romfs.rs | 3 +-- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08c9a44..9bd4f8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,12 +9,6 @@ on: - master workflow_dispatch: -env: - # https://blog.rust-lang.org/2022/06/22/sparse-registry-testing.html - CARGO_UNSTABLE_SPARSE_REGISTRY: "true" - # actions-rust-lang/setup-rust-toolchain sets some default RUSTFLAGS - RUSTFLAGS: "" - jobs: lint: strategy: @@ -33,13 +27,15 @@ jobs: - name: Checkout branch uses: actions/checkout@v2 - # TODO update to to rust3ds/$something once migrated. Also, this is a bit - # wordy, it might be nicer to put the actions at the top level of the repo - - uses: ian-h-chamberlain/test-runner-3ds/.github/actions/setup@v1 + # TODO point to to rust3ds/test-runner once migrated + - uses: ian-h-chamberlain/test-runner-3ds/setup@v1 with: toolchain: ${{ matrix.toolchain }} - - name: Hide duplicate warnings from nightly + # https://github.com/actions/runner/issues/504 + # Removing the matchers won't keep the job from failing if there are errors, + # but will at least declutter pull request annotations (especially for warnings). + - name: Hide duplicate annotations from nightly if: ${{ matrix.toolchain == 'nightly' }} run: | echo "::remove-matcher owner=clippy::" @@ -67,27 +63,22 @@ jobs: - name: Checkout branch uses: actions/checkout@v2 - - uses: ian-h-chamberlain/test-runner-3ds/.github/actions/setup@v1 + - uses: ian-h-chamberlain/test-runner-3ds/setup@v1 with: toolchain: ${{ matrix.toolchain }} - name: Hide duplicated warnings from lint job run: echo "::remove-matcher owner=clippy::" - - name: Build lib + integration tests - # Technically this will only build one 3dsx even if there's more than one executable, - # but we only run the `.elf` outputs so it doesn't really matter. - run: cargo 3ds test --no-run --tests --package ctru-rs - - - name: Build doc tests - run: cargo 3ds test --no-run --doc - - - name: Run lib + integration tests - uses: ian-h-chamberlain/test-runner-3ds/.github/actions/citra@v1 + - name: Build and run lib and integration tests + uses: ian-h-chamberlain/test-runner-3ds/run-tests@v1 with: - executable: ./target/armv6k-nintendo-3ds/debug/deps/*.elf + args: --tests --package ctru-rs - # TODO: run doc tests https://github.com/ian-h-chamberlain/test-runner-3ds/issues/4 + - name: Build and run doc tests + uses: ian-h-chamberlain/test-runner-3ds/run-tests@v1 + with: + args: --doc --package ctru-rs - name: Upload citra logs and capture videos uses: actions/upload-artifact@v3 diff --git a/ctru-rs/examples/hello-world.rs b/ctru-rs/examples/hello-world.rs index 9210484..c3c2791 100644 --- a/ctru-rs/examples/hello-world.rs +++ b/ctru-rs/examples/hello-world.rs @@ -31,6 +31,8 @@ fn main() { String::from_utf8_lossy(&writer.into_inner().unwrap()) ); + dbg!(std::env::args()); + println!("\x1b[29;16HPress Start to exit"); // Main application loop. This checks whether the app is normally running in the foreground. diff --git a/ctru-rs/src/services/gfx.rs b/ctru-rs/src/services/gfx.rs index 77198cf..7768ee1 100644 --- a/ctru-rs/src/services/gfx.rs +++ b/ctru-rs/src/services/gfx.rs @@ -499,8 +499,10 @@ mod tests { #[test] fn gfx_duplicate() { - // NOTE: this will fail if using the console test runner, since that creates - // a Gfx as part of its test setup. - Gfx::new().unwrap(); + // NOTE: this is expected to fail if using the console test runner, since + // that necessarily creates a Gfx as part of its test setup: + let _gfx = Gfx::new().unwrap(); + + assert!(matches!(Gfx::new(), Err(Error::ServiceAlreadyActive))); } } diff --git a/ctru-rs/src/services/romfs.rs b/ctru-rs/src/services/romfs.rs index bc0896d..d697e8a 100644 --- a/ctru-rs/src/services/romfs.rs +++ b/ctru-rs/src/services/romfs.rs @@ -27,10 +27,10 @@ #![doc(alias = "embed")] #![doc(alias = "filesystem")] -use crate::error::ResultCode; use std::ffi::CStr; use std::sync::Mutex; +use crate::error::ResultCode; use crate::services::ServiceReference; /// Handle to the RomFS service. @@ -84,7 +84,6 @@ mod tests { use super::*; #[test] - #[ignore = "library test .elf doesn't have the romfs in it. citra runner needs to support 3dsx"] fn romfs_counter() { let _romfs = RomFS::new().unwrap(); let value = *ROMFS_ACTIVE.lock().unwrap(); From ee68d9d806cf1220b808b23d681262216aee3748 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Mon, 25 Sep 2023 22:06:36 -0400 Subject: [PATCH 07/16] Enable running all tests and fix issues We had a couple `fs` examples unwrapping expected errors, but mostly everything passed! --- ctru-rs/examples/audio-filters.rs | 6 +-- ctru-rs/examples/camera-image.rs | 4 +- ctru-rs/examples/file-explorer.rs | 6 +-- ctru-rs/examples/futures-basic.rs | 4 +- ctru-rs/examples/futures-tokio.rs | 4 +- ctru-rs/examples/hello-world.rs | 3 +- ctru-rs/examples/network-sockets.rs | 4 +- ctru-rs/examples/thread-basic.rs | 4 +- ctru-rs/examples/thread-info.rs | 4 +- ctru-rs/examples/thread-locals.rs | 4 +- ctru-rs/src/applets/mii_selector.rs | 28 ++++++---- ctru-rs/src/applets/swkbd.rs | 34 +++++++----- ctru-rs/src/console.rs | 11 ++-- ctru-rs/src/error.rs | 10 ++-- ctru-rs/src/prelude.rs | 10 ++-- ctru-rs/src/services/am.rs | 18 ++++--- ctru-rs/src/services/apt.rs | 6 ++- ctru-rs/src/services/cam.rs | 25 +++++---- ctru-rs/src/services/cfgu.rs | 18 ++++--- ctru-rs/src/services/fs.rs | 83 ++++++++++++++++------------- ctru-rs/src/services/gfx.rs | 21 +++++--- ctru-rs/src/services/hid.rs | 24 ++++++--- ctru-rs/src/services/ndsp/mod.rs | 59 ++++++++++++-------- ctru-rs/src/services/ndsp/wave.rs | 12 +++-- ctru-rs/src/services/ps.rs | 12 +++-- ctru-rs/src/services/reference.rs | 3 +- ctru-rs/src/services/romfs.rs | 3 +- ctru-rs/src/services/soc.rs | 15 ++++-- ctru-rs/src/services/sslc.rs | 3 +- 29 files changed, 268 insertions(+), 170 deletions(-) diff --git a/ctru-rs/examples/audio-filters.rs b/ctru-rs/examples/audio-filters.rs index 75941b7..706d65f 100644 --- a/ctru-rs/examples/audio-filters.rs +++ b/ctru-rs/examples/audio-filters.rs @@ -8,10 +8,8 @@ use std::f32::consts::PI; use ctru::linear::LinearAllocator; use ctru::prelude::*; -use ctru::services::ndsp::{ - wave::{Status, Wave}, - AudioFormat, AudioMix, InterpolationType, Ndsp, OutputMode, -}; +use ctru::services::ndsp::wave::{Status, Wave}; +use ctru::services::ndsp::{AudioFormat, AudioMix, InterpolationType, Ndsp, OutputMode}; // Configuration for the NDSP process and channels. const SAMPLE_RATE: usize = 22050; diff --git a/ctru-rs/examples/camera-image.rs b/ctru-rs/examples/camera-image.rs index 851aa2a..ca9abcc 100644 --- a/ctru-rs/examples/camera-image.rs +++ b/ctru-rs/examples/camera-image.rs @@ -2,13 +2,13 @@ //! //! This example demonstrates how to use the built-in cameras to take a picture and display it to the screen. +use std::time::Duration; + use ctru::prelude::*; use ctru::services::cam::{Cam, Camera, OutputFormat, ShutterSound, ViewSize}; use ctru::services::gfx::{Flush, Screen, Swap}; use ctru::services::gspgpu::FramebufferFormat; -use std::time::Duration; - const WIDTH: usize = 400; const HEIGHT: usize = 240; diff --git a/ctru-rs/examples/file-explorer.rs b/ctru-rs/examples/file-explorer.rs index 6fa1183..d0a8718 100644 --- a/ctru-rs/examples/file-explorer.rs +++ b/ctru-rs/examples/file-explorer.rs @@ -3,13 +3,13 @@ //! This (rather complex) example creates a working text-based file explorer which shows off using standard library file system APIs to //! read the SD card and RomFS (if properly read via the `romfs:/` prefix). -use ctru::applets::swkbd::{Button, SoftwareKeyboard}; -use ctru::prelude::*; - use std::fs::DirEntry; use std::os::horizon::fs::MetadataExt; use std::path::{Path, PathBuf}; +use ctru::applets::swkbd::{Button, SoftwareKeyboard}; +use ctru::prelude::*; + fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/futures-basic.rs b/ctru-rs/examples/futures-basic.rs index c41245c..e2159c3 100644 --- a/ctru-rs/examples/futures-basic.rs +++ b/ctru-rs/examples/futures-basic.rs @@ -7,10 +7,10 @@ #![feature(horizon_thread_ext)] -use ctru::prelude::*; +use std::os::horizon::thread::BuilderExt; +use ctru::prelude::*; use futures::StreamExt; -use std::os::horizon::thread::BuilderExt; fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/futures-tokio.rs b/ctru-rs/examples/futures-tokio.rs index 986e930..9aa5647 100644 --- a/ctru-rs/examples/futures-tokio.rs +++ b/ctru-rs/examples/futures-tokio.rs @@ -1,10 +1,10 @@ #![feature(horizon_thread_ext)] -use ctru::prelude::*; - use std::os::horizon::thread::BuilderExt; use std::time::Duration; +use ctru::prelude::*; + fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/hello-world.rs b/ctru-rs/examples/hello-world.rs index c3c2791..230d25a 100644 --- a/ctru-rs/examples/hello-world.rs +++ b/ctru-rs/examples/hello-world.rs @@ -2,9 +2,10 @@ //! //! Simple "Hello World" application to showcase the basic setup needed for any user-oriented app to work. -use ctru::prelude::*; use std::io::BufWriter; +use ctru::prelude::*; + fn main() { // Setup the custom panic handler in case any errors arise. // Thanks to it the user will get promptly notified of any panics. diff --git a/ctru-rs/examples/network-sockets.rs b/ctru-rs/examples/network-sockets.rs index d55e29c..98faa26 100644 --- a/ctru-rs/examples/network-sockets.rs +++ b/ctru-rs/examples/network-sockets.rs @@ -2,12 +2,12 @@ //! //! This example showcases the use of network sockets via the `Soc` service and the standard library's implementations. -use ctru::prelude::*; - use std::io::{self, Read, Write}; use std::net::{Shutdown, TcpListener}; use std::time::Duration; +use ctru::prelude::*; + fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/thread-basic.rs b/ctru-rs/examples/thread-basic.rs index 3e4604b..b59a644 100644 --- a/ctru-rs/examples/thread-basic.rs +++ b/ctru-rs/examples/thread-basic.rs @@ -1,10 +1,10 @@ #![feature(horizon_thread_ext)] -use ctru::prelude::*; - use std::os::horizon::thread::BuilderExt; use std::time::Duration; +use ctru::prelude::*; + fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/thread-info.rs b/ctru-rs/examples/thread-info.rs index 46d34d3..54b82c0 100644 --- a/ctru-rs/examples/thread-info.rs +++ b/ctru-rs/examples/thread-info.rs @@ -2,10 +2,10 @@ #![feature(horizon_thread_ext)] -use ctru::prelude::*; - use std::os::horizon::thread::BuilderExt; +use ctru::prelude::*; + fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/thread-locals.rs b/ctru-rs/examples/thread-locals.rs index 72458c9..310244d 100644 --- a/ctru-rs/examples/thread-locals.rs +++ b/ctru-rs/examples/thread-locals.rs @@ -1,10 +1,10 @@ #![feature(horizon_thread_ext)] -use ctru::prelude::*; - use std::cell::RefCell; use std::os::horizon::thread::BuilderExt; +use ctru::prelude::*; + std::thread_local! { static MY_LOCAL: RefCell<&'static str> = RefCell::new("initial value"); } diff --git a/ctru-rs/src/applets/mii_selector.rs b/ctru-rs/src/applets/mii_selector.rs index bd0e4b4..9bcfbbb 100644 --- a/ctru-rs/src/applets/mii_selector.rs +++ b/ctru-rs/src/applets/mii_selector.rs @@ -3,9 +3,12 @@ //! This applet opens a window which lets the player/user choose a Mii from the ones present on their console. //! The selected Mii is readable as a [`Mii`](crate::mii::Mii). -use crate::mii::Mii; +use std::ffi::CString; +use std::fmt; + use bitflags::bitflags; -use std::{ffi::CString, fmt}; + +use crate::mii::Mii; /// Index of a Mii on the [`MiiSelector`] interface. /// @@ -97,7 +100,8 @@ impl MiiSelector { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// use ctru::applets::mii_selector::MiiSelector; /// @@ -121,7 +125,8 @@ impl MiiSelector { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// use ctru::applets::mii_selector::{MiiSelector, Options}; /// let mut mii_selector = MiiSelector::new(); @@ -145,7 +150,8 @@ impl MiiSelector { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -174,7 +180,8 @@ impl MiiSelector { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -198,7 +205,8 @@ impl MiiSelector { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -222,7 +230,8 @@ impl MiiSelector { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -260,7 +269,8 @@ impl MiiSelector { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/applets/swkbd.rs b/ctru-rs/src/applets/swkbd.rs index 8861ace..931b1c7 100644 --- a/ctru-rs/src/applets/swkbd.rs +++ b/ctru-rs/src/applets/swkbd.rs @@ -5,14 +5,15 @@ // TODO: Split the Parental PIN lock operations into a different type. #![doc(alias = "keyboard")] +use std::fmt::Display; +use std::iter::once; +use std::str; + use bitflags::bitflags; use ctru_sys::{ self, swkbdInit, swkbdInputText, swkbdSetButton, swkbdSetFeatures, swkbdSetHintText, SwkbdState, }; use libc; -use std::fmt::Display; -use std::iter::once; -use std::str; /// Configuration structure to setup the Software Keyboard applet. #[doc(alias = "SwkbdState")] @@ -160,7 +161,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::swkbd::{SoftwareKeyboard, Kind}; @@ -191,7 +193,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -235,7 +238,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -266,7 +270,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::swkbd::{SoftwareKeyboard, Features}; @@ -286,7 +291,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::swkbd::{SoftwareKeyboard, ValidInput, Filters}; @@ -309,7 +315,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::swkbd::{SoftwareKeyboard, ValidInput, Filters}; @@ -336,7 +343,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::swkbd::SoftwareKeyboard; @@ -363,7 +371,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::swkbd::{SoftwareKeyboard, Button, Kind}; @@ -402,7 +411,8 @@ impl SoftwareKeyboard { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # fn main() { /// # /// use ctru::applets::swkbd::{SoftwareKeyboard, Button, Kind}; diff --git a/ctru-rs/src/console.rs b/ctru-rs/src/console.rs index 6768d47..6d25d93 100644 --- a/ctru-rs/src/console.rs +++ b/ctru-rs/src/console.rs @@ -52,12 +52,13 @@ impl<'screen> Console<'screen> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # - /// use ctru::services::gfx::Gfx; /// use ctru::console::Console; + /// use ctru::services::gfx::Gfx; /// /// // Initialize graphics. /// let gfx = Gfx::new()?; @@ -94,7 +95,8 @@ impl<'screen> Console<'screen> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -131,7 +133,8 @@ impl<'screen> Console<'screen> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/error.rs b/ctru-rs/src/error.rs index 41b09f8..a91da3f 100644 --- a/ctru-rs/src/error.rs +++ b/ctru-rs/src/error.rs @@ -3,10 +3,9 @@ //! This module holds the generic error and result types to interface with `ctru_sys` and the [`ctru-rs`](crate) safe wrapper. use std::borrow::Cow; -use std::error; use std::ffi::CStr; -use std::fmt; use std::ops::{ControlFlow, FromResidual, Try}; +use std::{error, fmt}; use ctru_sys::result::{R_DESCRIPTION, R_LEVEL, R_MODULE, R_SUMMARY}; @@ -21,13 +20,14 @@ pub type Result = ::std::result::Result; /// /// # Example /// -/// ```no_run +/// ``` /// use ctru::error::{Result, ResultCode}; /// -/// pub fn hid_init() -> Result<()> { +/// pub fn main() -> Result<()> { +/// # let _runner = test_runner::GdbRunner::default(); /// // We run an unsafe function which returns a `ctru_sys::Result`. /// let result: ctru_sys::Result = unsafe { ctru_sys::hidInit() }; -/// +/// /// // The result code is parsed and any possible error gets returned by the function. /// ResultCode(result)?; /// Ok(()) diff --git a/ctru-rs/src/prelude.rs b/ctru-rs/src/prelude.rs index ee18eab..4e9bd68 100644 --- a/ctru-rs/src/prelude.rs +++ b/ctru-rs/src/prelude.rs @@ -3,9 +3,7 @@ //! Particularly useful when writing very small applications. pub use crate::console::Console; -pub use crate::services::{ - apt::Apt, - gfx::Gfx, - hid::{Hid, KeyPad}, - soc::Soc, -}; +pub use crate::services::apt::Apt; +pub use crate::services::gfx::Gfx; +pub use crate::services::hid::{Hid, KeyPad}; +pub use crate::services::soc::Soc; diff --git a/ctru-rs/src/services/am.rs b/ctru-rs/src/services/am.rs index 68b3af3..33c145f 100644 --- a/ctru-rs/src/services/am.rs +++ b/ctru-rs/src/services/am.rs @@ -8,9 +8,10 @@ #![doc(alias = "app")] #![doc(alias = "manager")] +use std::marker::PhantomData; + use crate::error::ResultCode; use crate::services::fs::FsMediaType; -use std::marker::PhantomData; /// General information about a specific title entry. #[doc(alias = "AM_TitleEntry")] @@ -61,7 +62,8 @@ impl Am { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -84,11 +86,13 @@ impl Am { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # - /// use ctru::services::{fs::FsMediaType, am::Am}; + /// use ctru::services::am::Am; + /// use ctru::services::fs::FsMediaType; /// let app_manager = Am::new()?; /// /// // Number of titles installed on the Nand storage. @@ -113,11 +117,13 @@ impl Am { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # - /// use ctru::services::{fs::FsMediaType, am::Am}; + /// use ctru::services::am::Am; + /// use ctru::services::fs::FsMediaType; /// let app_manager = Am::new()?; /// /// // Number of apps installed on the SD card storage diff --git a/ctru-rs/src/services/apt.rs b/ctru-rs/src/services/apt.rs index b30be85..89ad255 100644 --- a/ctru-rs/src/services/apt.rs +++ b/ctru-rs/src/services/apt.rs @@ -16,7 +16,8 @@ impl Apt { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -44,7 +45,8 @@ impl Apt { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// use std::error::Error; /// use ctru::services::apt::Apt; /// diff --git a/ctru-rs/src/services/cam.rs b/ctru-rs/src/services/cam.rs index 8d4af7b..596741c 100644 --- a/ctru-rs/src/services/cam.rs +++ b/ctru-rs/src/services/cam.rs @@ -4,10 +4,12 @@ //! in the form of byte vectors which can be displayed to the screen or used in other ways. #![doc(alias = "camera")] +use std::time::Duration; + +use ctru_sys::Handle; + use crate::error::{Error, ResultCode}; use crate::services::gspgpu::FramebufferFormat; -use ctru_sys::Handle; -use std::time::Duration; /// Handle to the Camera service. #[non_exhaustive] @@ -343,7 +345,8 @@ pub trait Camera { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -372,7 +375,8 @@ pub trait Camera { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -841,12 +845,13 @@ pub trait Camera { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # use std::time::Duration; /// # fn main() -> Result<(), Box> { /// # - /// use ctru::services::cam::{Cam, Camera, ViewSize, OutputFormat}; + /// use ctru::services::cam::{Cam, Camera, OutputFormat, ViewSize}; /// let mut cam = Cam::new()?; /// /// // We borrow the inward facing `Camera`. @@ -859,7 +864,7 @@ pub trait Camera { /// inward.set_auto_white_balance(true)?; /// /// // Size of the top screen buffer at 2 bytes per pixel (RGB565). - /// let mut buffer = vec![0; 400*240*2]; + /// let mut buffer = vec![0; 400 * 240 * 2]; /// /// // Take picture with 3 seconds of timeout. /// inward.take_picture(&mut buffer, 400, 240, Duration::from_secs(3)); @@ -951,7 +956,8 @@ impl Cam { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -984,7 +990,8 @@ impl Cam { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/cfgu.rs b/ctru-rs/src/services/cfgu.rs index b1cbe76..981f8e6 100644 --- a/ctru-rs/src/services/cfgu.rs +++ b/ctru-rs/src/services/cfgu.rs @@ -84,7 +84,8 @@ impl Cfgu { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -105,7 +106,8 @@ impl Cfgu { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -129,7 +131,8 @@ impl Cfgu { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -153,7 +156,8 @@ impl Cfgu { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -177,7 +181,8 @@ impl Cfgu { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -205,7 +210,8 @@ impl Cfgu { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/fs.rs b/ctru-rs/src/services/fs.rs index 821b8b9..2ae9bfb 100644 --- a/ctru-rs/src/services/fs.rs +++ b/ctru-rs/src/services/fs.rs @@ -5,17 +5,15 @@ // TODO: Refactor service to accomodate for various changes (such as SMDH support). Properly document the public API. #![doc(alias = "filesystem")] -use bitflags::bitflags; use std::ffi::OsString; -use std::io::Error as IoError; -use std::io::ErrorKind as IoErrorKind; -use std::io::Result as IoResult; -use std::io::{Read, Seek, SeekFrom, Write}; -use std::mem; +use std::io::{ + Error as IoError, ErrorKind as IoErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write, +}; use std::path::{Path, PathBuf}; -use std::ptr; -use std::slice; use std::sync::Arc; +use std::{mem, ptr, slice}; + +use bitflags::bitflags; use widestring::{WideCStr, WideCString}; bitflags! { @@ -136,7 +134,8 @@ pub struct Fs(()); /// /// # Examples /// -/// ```no_run +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); /// use ctru::services::fs::Fs; /// /// let mut fs = Fs::new().unwrap(); @@ -158,12 +157,14 @@ pub struct Archive { /// /// Create a new file and write bytes to it: /// -/// ```no_run +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # /// use std::io::prelude::*; -/// use ctru::services::fs::{Fs, File}; +/// +/// use ctru::services::fs::{File, Fs}; /// /// let mut fs = Fs::new()?; /// let mut sdmc = fs.sdmc()?; @@ -174,12 +175,14 @@ pub struct Archive { /// /// Read the contents of a file into a `String`:: /// -/// ```no_run +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # /// use std::io::prelude::*; -/// use ctru::services::fs::{Fs, File}; +/// +/// use ctru::services::fs::{File, Fs}; /// /// let mut fs = Fs::new()?; /// let mut sdmc = fs.sdmc()?; @@ -196,13 +199,15 @@ pub struct Archive { /// It can be more efficient to read the contents of a file with a buffered /// `Read`er. This can be accomplished with `BufReader`: /// -/// ```no_run +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # -/// use std::io::BufReader; /// use std::io::prelude::*; -/// use ctru::services::fs::{Fs, File}; +/// use std::io::BufReader; +/// +/// use ctru::services::fs::{File, Fs}; /// /// let mut fs = Fs::new()?; /// let mut sdmc = fs.sdmc()?; @@ -247,33 +252,36 @@ pub struct Metadata { /// /// Opening a file to read: /// -/// ```no_run +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); /// use ctru::services::fs::{Fs, OpenOptions}; /// /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); -/// let file = OpenOptions::new() -/// .read(true) -/// .archive(&sdmc_archive) -/// .open("foo.txt") -/// .unwrap(); +/// let result = OpenOptions::new() +/// .read(true) +/// .archive(&sdmc_archive) +/// .open("foo.txt"); +/// +/// assert!(result.is_err()); /// ``` /// /// Opening a file for both reading and writing, as well as creating it if it /// doesn't exist: /// -/// ```no_run +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); /// use ctru::services::fs::{Fs, OpenOptions}; /// /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let file = OpenOptions::new() -/// .read(true) -/// .write(true) -/// .create(true) -/// .archive(&sdmc_archive) -/// .open("foo.txt") -/// .unwrap(); +/// .read(true) +/// .write(true) +/// .create(true) +/// .archive(&sdmc_archive) +/// .open("/foo.txt") +/// .unwrap(); /// ``` #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct OpenOptions { @@ -380,12 +388,14 @@ impl File { /// /// # Examples /// - /// ```no_run - /// use ctru::services::fs::{Fs, File}; + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); + /// use ctru::services::fs::{File, Fs}; /// - /// let mut fs = Fs::new().unwrap(); + /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); - /// let mut f = File::open(&sdmc_archive, "/foo.txt").unwrap(); + /// // Non-existent file: + /// assert!(File::open(&sdmc_archive, "/foo.txt").is_err()); /// ``` pub fn open>(arch: &Archive, path: P) -> IoResult { OpenOptions::new() @@ -407,10 +417,11 @@ impl File { /// /// # Examples /// - /// ```no_run - /// use ctru::services::fs::{Fs, File}; + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); + /// use ctru::services::fs::{File, Fs}; /// - /// let mut fs = Fs::new().unwrap(); + /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let mut f = File::create(&mut sdmc_archive, "/foo.txt").unwrap(); /// ``` diff --git a/ctru-rs/src/services/gfx.rs b/ctru-rs/src/services/gfx.rs index 7768ee1..4c64c2b 100644 --- a/ctru-rs/src/services/gfx.rs +++ b/ctru-rs/src/services/gfx.rs @@ -253,7 +253,8 @@ impl Gfx { /// /// It's the same as calling: /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -268,7 +269,8 @@ impl Gfx { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -290,11 +292,13 @@ impl Gfx { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # - /// use ctru::services::{gfx::Gfx, gspgpu::FramebufferFormat}; + /// use ctru::services::gfx::Gfx; + /// use ctru::services::gspgpu::FramebufferFormat; /// /// // Top screen uses RGBA8, bottom screen uses RGB565. /// // The screen buffers are allocated in the standard HEAP memory, and not in VRAM. @@ -333,11 +337,13 @@ impl Gfx { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # - /// use ctru::services::{apt::Apt, gfx::Gfx}; + /// use ctru::services::apt::Apt; + /// use ctru::services::gfx::Gfx; /// let apt = Apt::new()?; /// let gfx = Gfx::new()?; /// @@ -376,7 +382,8 @@ impl TopScreen3D<'_> { /// /// # Example /// -/// ```no_run +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/hid.rs b/ctru-rs/src/services/hid.rs index 56a6035..4b2a360 100644 --- a/ctru-rs/src/services/hid.rs +++ b/ctru-rs/src/services/hid.rs @@ -7,9 +7,10 @@ #![doc(alias = "controller")] #![doc(alias = "gamepad")] -use crate::error::ResultCode; use bitflags::bitflags; +use crate::error::ResultCode; + bitflags! { /// A set of flags corresponding to the button and directional pad inputs present on the 3DS. #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] @@ -87,7 +88,8 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -113,7 +115,8 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -135,7 +138,8 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -164,7 +168,8 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -193,7 +198,8 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -225,7 +231,8 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -258,7 +265,8 @@ impl Hid { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index 8cda802..b9717eb 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -6,17 +6,16 @@ #![doc(alias = "audio")] pub mod wave; +use std::cell::{RefCell, RefMut}; +use std::default::Default; +use std::sync::Mutex; +use std::{error, fmt}; + use wave::{Status, Wave}; use crate::error::ResultCode; use crate::services::ServiceReference; -use std::cell::{RefCell, RefMut}; -use std::default::Default; -use std::error; -use std::fmt; -use std::sync::Mutex; - const NUMBER_OF_CHANNELS: u8 = 24; /// Audio output mode. @@ -118,7 +117,8 @@ impl Ndsp { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -158,7 +158,8 @@ impl Ndsp { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -189,7 +190,8 @@ impl Ndsp { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -213,7 +215,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -235,7 +238,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -257,7 +261,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -280,7 +285,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -303,7 +309,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -339,7 +346,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -366,7 +374,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -390,7 +399,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -415,7 +425,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # use std::default::Default; /// # fn main() -> Result<(), Box> { @@ -439,7 +450,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -464,7 +476,8 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -493,13 +506,15 @@ impl Channel<'_> { /// /// # Example /// - /// ```no_run + /// ``` /// # #![feature(allocator_api)] /// # use std::error::Error; /// # fn main() -> Result<(), Box> { + /// # let _runner = test_runner::GdbRunner::default(); /// # /// # use ctru::linear::LinearAllocator; - /// use ctru::services::ndsp::{AudioFormat, Ndsp, wave::Wave}; + /// use ctru::services::ndsp::wave::Wave; + /// use ctru::services::ndsp::{AudioFormat, Ndsp}; /// let ndsp = Ndsp::new()?; /// let mut channel_0 = ndsp.channel(0)?; /// diff --git a/ctru-rs/src/services/ndsp/wave.rs b/ctru-rs/src/services/ndsp/wave.rs index 1a383ca..79659fd 100644 --- a/ctru-rs/src/services/ndsp/wave.rs +++ b/ctru-rs/src/services/ndsp/wave.rs @@ -36,12 +36,14 @@ impl Wave { /// /// # Example /// - /// ```no_run + /// ``` /// # #![feature(allocator_api)] /// # fn main() { + /// # let _runner = test_runner::GdbRunner::default(); /// # /// use ctru::linear::LinearAllocator; - /// use ctru::services::ndsp::{AudioFormat, wave::Wave}; + /// use ctru::services::ndsp::wave::Wave; + /// use ctru::services::ndsp::AudioFormat; /// /// // Zeroed box allocated in the LINEAR memory. /// let audio_data = Box::new_in([0u8; 96], LinearAllocator); @@ -110,14 +112,16 @@ impl Wave { /// /// # Example /// - /// ```no_run + /// ``` /// # #![feature(allocator_api)] /// # fn main() { + /// # let _runner = test_runner::GdbRunner::default(); /// # /// # use ctru::linear::LinearAllocator; /// # let _audio_data = Box::new_in([0u8; 96], LinearAllocator); /// # - /// use ctru::services::ndsp::{AudioFormat, wave::{Wave, Status}}; + /// use ctru::services::ndsp::wave::{Status, Wave}; + /// use ctru::services::ndsp::AudioFormat; /// /// // Provide your own audio data. /// let wave = Wave::new(_audio_data, AudioFormat::PCM16Stereo, false); diff --git a/ctru-rs/src/services/ps.rs b/ctru-rs/src/services/ps.rs index fc20a78..27f21a2 100644 --- a/ctru-rs/src/services/ps.rs +++ b/ctru-rs/src/services/ps.rs @@ -63,7 +63,8 @@ impl Ps { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -86,7 +87,8 @@ impl Ps { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -110,7 +112,8 @@ impl Ps { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -134,7 +137,8 @@ impl Ps { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/reference.rs b/ctru-rs/src/services/reference.rs index 41319a7..7f6f5ed 100644 --- a/ctru-rs/src/services/reference.rs +++ b/ctru-rs/src/services/reference.rs @@ -1,5 +1,6 @@ -use crate::Error; use std::sync::Mutex; + +use crate::Error; pub(crate) struct ServiceReference { counter: &'static Mutex, close: Box, diff --git a/ctru-rs/src/services/romfs.rs b/ctru-rs/src/services/romfs.rs index d697e8a..c1a9a57 100644 --- a/ctru-rs/src/services/romfs.rs +++ b/ctru-rs/src/services/romfs.rs @@ -45,7 +45,8 @@ impl RomFS { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/soc.rs b/ctru-rs/src/services/soc.rs index d418919..2797ae6 100644 --- a/ctru-rs/src/services/soc.rs +++ b/ctru-rs/src/services/soc.rs @@ -5,10 +5,11 @@ #![doc(alias = "socket")] #![doc(alias = "network")] -use libc::memalign; use std::net::Ipv4Addr; use std::sync::Mutex; +use libc::memalign; + use crate::error::ResultCode; use crate::services::ServiceReference; use crate::Error; @@ -30,7 +31,8 @@ impl Soc { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -56,7 +58,8 @@ impl Soc { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -97,7 +100,8 @@ impl Soc { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -130,7 +134,8 @@ impl Soc { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/services/sslc.rs b/ctru-rs/src/services/sslc.rs index af8b65d..81674ad 100644 --- a/ctru-rs/src/services/sslc.rs +++ b/ctru-rs/src/services/sslc.rs @@ -12,7 +12,8 @@ impl SslC { /// /// # Example /// - /// ```no_run + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # From 6881dce541a428e3431981e677d3ebef79c303b0 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Wed, 27 Sep 2023 00:21:59 -0400 Subject: [PATCH 08/16] Don't run NDSP doctests --- ctru-rs/src/services/ndsp/mod.rs | 61 +++++++++++++++----------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index b9717eb..a85a325 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -3,8 +3,17 @@ //! The NDSP service is used to handle communications to the DSP processor present on the console's motherboard. //! Thanks to the DSP processor the program can play sound effects and music on the console's built-in speakers or to any audio device //! connected via the audio jack. +//! +//! To use NDSP audio, you will need to dump DSP firmware from a real 3DS using +//! something like [DSP1](https://www.gamebrew.org/wiki/DSP1_3DS). +//! +//! `libctru` expects to find it at `sdmc:/3ds/dspfirm.cdc` when initializing the NDSP service. #![doc(alias = "audio")] +// As a result of requiring DSP firmware to initialize, all of the doctests in +// this module are `no_run`, since Citra doesn't provide a stub for the DSP firmware: +// https://github.com/citra-emu/citra/issues/6111 + pub mod wave; use std::cell::{RefCell, RefMut}; use std::default::Default; @@ -113,12 +122,12 @@ impl Ndsp { /// # Errors /// /// This function will return an error if an instance of the [`Ndsp`] struct already exists - /// or if there are any issues during initialization. + /// or if there are any issues during initialization (for example, DSP firmware + /// cannot be found. See [module documentation](super::ndsp) for more details.). /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -158,8 +167,7 @@ impl Ndsp { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -190,8 +198,7 @@ impl Ndsp { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -215,8 +222,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -238,8 +244,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -261,8 +266,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -285,8 +289,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -309,8 +312,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -346,8 +348,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -374,8 +375,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -399,8 +399,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -425,8 +424,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # use std::default::Default; /// # fn main() -> Result<(), Box> { @@ -450,8 +448,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -476,8 +473,7 @@ impl Channel<'_> { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # @@ -506,11 +502,10 @@ impl Channel<'_> { /// /// # Example /// - /// ``` + /// ```no_run /// # #![feature(allocator_api)] /// # use std::error::Error; /// # fn main() -> Result<(), Box> { - /// # let _runner = test_runner::GdbRunner::default(); /// # /// # use ctru::linear::LinearAllocator; /// use ctru::services::ndsp::wave::Wave; @@ -518,10 +513,10 @@ impl Channel<'_> { /// let ndsp = Ndsp::new()?; /// let mut channel_0 = ndsp.channel(0)?; /// - /// # let _audio_data = Box::new_in([0u8; 96], LinearAllocator); + /// # let audio_data = Box::new_in([0u8; 96], LinearAllocator); /// /// // Provide your own audio data. - /// let mut wave = Wave::new(_audio_data, AudioFormat::PCM16Stereo, false); + /// let mut wave = Wave::new(audio_data, AudioFormat::PCM16Stereo, false); /// /// // Clear the audio queue and stop playback. /// channel_0.queue_wave(&mut wave); From ce2023307dca21587e48e60b576b24f03aba7b3b Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sat, 30 Sep 2023 09:15:05 -0400 Subject: [PATCH 09/16] Fix some small bugs / workarounds for CI --- .github/workflows/ci.yml | 10 +++++++++- ctru-rs/examples/hello-world.rs | 2 -- ctru-rs/src/services/romfs.rs | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bd4f8f..8c43d8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,15 @@ jobs: - name: Hide duplicated warnings from lint job run: echo "::remove-matcher owner=clippy::" - - name: Build and run lib and integration tests + # This needs to be done separately from running the tests to ensure the + # lib tests' .3dsx is built before the test is run (for romfs). We don't + # really have a good way to build the 3dsx in between the build + test, + # unless cargo-3ds actually runs them as separate commands. See + # https://github.com/rust3ds/cargo-3ds/issues/44 for more details + - name: Build lib and integration tests + run: cargo 3ds test --no-run --tests --package ctru-rs + + - name: Run lib and integration tests uses: ian-h-chamberlain/test-runner-3ds/run-tests@v1 with: args: --tests --package ctru-rs diff --git a/ctru-rs/examples/hello-world.rs b/ctru-rs/examples/hello-world.rs index 230d25a..1be0107 100644 --- a/ctru-rs/examples/hello-world.rs +++ b/ctru-rs/examples/hello-world.rs @@ -32,8 +32,6 @@ fn main() { String::from_utf8_lossy(&writer.into_inner().unwrap()) ); - dbg!(std::env::args()); - println!("\x1b[29;16HPress Start to exit"); // Main application loop. This checks whether the app is normally running in the foreground. diff --git a/ctru-rs/src/services/romfs.rs b/ctru-rs/src/services/romfs.rs index c1a9a57..fdf65d7 100644 --- a/ctru-rs/src/services/romfs.rs +++ b/ctru-rs/src/services/romfs.rs @@ -85,6 +85,8 @@ mod tests { use super::*; #[test] + // NOTE: this test only passes when run with a .3dsx, which for now requires separate build + // and run steps so the 3dsx is built before the runner looks for the executable fn romfs_counter() { let _romfs = RomFS::new().unwrap(); let value = *ROMFS_ACTIVE.lock().unwrap(); From 33268566c86cf47f19a7e589c9161f942f500158 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sat, 30 Sep 2023 09:33:04 -0400 Subject: [PATCH 10/16] Revert accidental formatting changes --- ctru-rs/examples/audio-filters.rs | 6 ++++-- ctru-rs/examples/camera-image.rs | 4 ++-- ctru-rs/examples/file-explorer.rs | 6 +++--- ctru-rs/examples/futures-basic.rs | 4 ++-- ctru-rs/examples/futures-tokio.rs | 4 ++-- ctru-rs/examples/hello-world.rs | 3 +-- ctru-rs/examples/network-sockets.rs | 4 ++-- ctru-rs/examples/thread-basic.rs | 4 ++-- ctru-rs/examples/thread-info.rs | 4 ++-- ctru-rs/examples/thread-locals.rs | 4 ++-- ctru-rs/src/applets/mii_selector.rs | 28 ++++++++----------------- ctru-rs/src/applets/swkbd.rs | 7 +++---- ctru-rs/src/error.rs | 5 +++-- ctru-rs/src/lib.rs | 3 +-- ctru-rs/src/prelude.rs | 10 +++++---- ctru-rs/src/services/am.rs | 3 +-- ctru-rs/src/services/cam.rs | 8 +++----- ctru-rs/src/services/fs.rs | 32 +++++++++++++++-------------- ctru-rs/src/services/hid.rs | 3 +-- ctru-rs/src/services/ndsp/mod.rs | 11 +++++----- ctru-rs/src/services/ndsp/wave.rs | 6 ++---- ctru-rs/src/services/reference.rs | 3 +-- ctru-rs/src/services/romfs.rs | 2 +- ctru-rs/src/services/soc.rs | 3 +-- 24 files changed, 77 insertions(+), 90 deletions(-) diff --git a/ctru-rs/examples/audio-filters.rs b/ctru-rs/examples/audio-filters.rs index 706d65f..75941b7 100644 --- a/ctru-rs/examples/audio-filters.rs +++ b/ctru-rs/examples/audio-filters.rs @@ -8,8 +8,10 @@ use std::f32::consts::PI; use ctru::linear::LinearAllocator; use ctru::prelude::*; -use ctru::services::ndsp::wave::{Status, Wave}; -use ctru::services::ndsp::{AudioFormat, AudioMix, InterpolationType, Ndsp, OutputMode}; +use ctru::services::ndsp::{ + wave::{Status, Wave}, + AudioFormat, AudioMix, InterpolationType, Ndsp, OutputMode, +}; // Configuration for the NDSP process and channels. const SAMPLE_RATE: usize = 22050; diff --git a/ctru-rs/examples/camera-image.rs b/ctru-rs/examples/camera-image.rs index ca9abcc..851aa2a 100644 --- a/ctru-rs/examples/camera-image.rs +++ b/ctru-rs/examples/camera-image.rs @@ -2,13 +2,13 @@ //! //! This example demonstrates how to use the built-in cameras to take a picture and display it to the screen. -use std::time::Duration; - use ctru::prelude::*; use ctru::services::cam::{Cam, Camera, OutputFormat, ShutterSound, ViewSize}; use ctru::services::gfx::{Flush, Screen, Swap}; use ctru::services::gspgpu::FramebufferFormat; +use std::time::Duration; + const WIDTH: usize = 400; const HEIGHT: usize = 240; diff --git a/ctru-rs/examples/file-explorer.rs b/ctru-rs/examples/file-explorer.rs index d0a8718..6fa1183 100644 --- a/ctru-rs/examples/file-explorer.rs +++ b/ctru-rs/examples/file-explorer.rs @@ -3,13 +3,13 @@ //! This (rather complex) example creates a working text-based file explorer which shows off using standard library file system APIs to //! read the SD card and RomFS (if properly read via the `romfs:/` prefix). +use ctru::applets::swkbd::{Button, SoftwareKeyboard}; +use ctru::prelude::*; + use std::fs::DirEntry; use std::os::horizon::fs::MetadataExt; use std::path::{Path, PathBuf}; -use ctru::applets::swkbd::{Button, SoftwareKeyboard}; -use ctru::prelude::*; - fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/futures-basic.rs b/ctru-rs/examples/futures-basic.rs index e2159c3..c41245c 100644 --- a/ctru-rs/examples/futures-basic.rs +++ b/ctru-rs/examples/futures-basic.rs @@ -7,10 +7,10 @@ #![feature(horizon_thread_ext)] -use std::os::horizon::thread::BuilderExt; - use ctru::prelude::*; + use futures::StreamExt; +use std::os::horizon::thread::BuilderExt; fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/futures-tokio.rs b/ctru-rs/examples/futures-tokio.rs index 9aa5647..986e930 100644 --- a/ctru-rs/examples/futures-tokio.rs +++ b/ctru-rs/examples/futures-tokio.rs @@ -1,10 +1,10 @@ #![feature(horizon_thread_ext)] +use ctru::prelude::*; + use std::os::horizon::thread::BuilderExt; use std::time::Duration; -use ctru::prelude::*; - fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/hello-world.rs b/ctru-rs/examples/hello-world.rs index 1be0107..9210484 100644 --- a/ctru-rs/examples/hello-world.rs +++ b/ctru-rs/examples/hello-world.rs @@ -2,9 +2,8 @@ //! //! Simple "Hello World" application to showcase the basic setup needed for any user-oriented app to work. -use std::io::BufWriter; - use ctru::prelude::*; +use std::io::BufWriter; fn main() { // Setup the custom panic handler in case any errors arise. diff --git a/ctru-rs/examples/network-sockets.rs b/ctru-rs/examples/network-sockets.rs index 98faa26..d55e29c 100644 --- a/ctru-rs/examples/network-sockets.rs +++ b/ctru-rs/examples/network-sockets.rs @@ -2,12 +2,12 @@ //! //! This example showcases the use of network sockets via the `Soc` service and the standard library's implementations. +use ctru::prelude::*; + use std::io::{self, Read, Write}; use std::net::{Shutdown, TcpListener}; use std::time::Duration; -use ctru::prelude::*; - fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/thread-basic.rs b/ctru-rs/examples/thread-basic.rs index b59a644..3e4604b 100644 --- a/ctru-rs/examples/thread-basic.rs +++ b/ctru-rs/examples/thread-basic.rs @@ -1,10 +1,10 @@ #![feature(horizon_thread_ext)] +use ctru::prelude::*; + use std::os::horizon::thread::BuilderExt; use std::time::Duration; -use ctru::prelude::*; - fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/thread-info.rs b/ctru-rs/examples/thread-info.rs index 54b82c0..46d34d3 100644 --- a/ctru-rs/examples/thread-info.rs +++ b/ctru-rs/examples/thread-info.rs @@ -2,10 +2,10 @@ #![feature(horizon_thread_ext)] -use std::os::horizon::thread::BuilderExt; - use ctru::prelude::*; +use std::os::horizon::thread::BuilderExt; + fn main() { ctru::use_panic_handler(); diff --git a/ctru-rs/examples/thread-locals.rs b/ctru-rs/examples/thread-locals.rs index 310244d..72458c9 100644 --- a/ctru-rs/examples/thread-locals.rs +++ b/ctru-rs/examples/thread-locals.rs @@ -1,10 +1,10 @@ #![feature(horizon_thread_ext)] +use ctru::prelude::*; + use std::cell::RefCell; use std::os::horizon::thread::BuilderExt; -use ctru::prelude::*; - std::thread_local! { static MY_LOCAL: RefCell<&'static str> = RefCell::new("initial value"); } diff --git a/ctru-rs/src/applets/mii_selector.rs b/ctru-rs/src/applets/mii_selector.rs index 9bcfbbb..bd0e4b4 100644 --- a/ctru-rs/src/applets/mii_selector.rs +++ b/ctru-rs/src/applets/mii_selector.rs @@ -3,12 +3,9 @@ //! This applet opens a window which lets the player/user choose a Mii from the ones present on their console. //! The selected Mii is readable as a [`Mii`](crate::mii::Mii). -use std::ffi::CString; -use std::fmt; - -use bitflags::bitflags; - use crate::mii::Mii; +use bitflags::bitflags; +use std::{ffi::CString, fmt}; /// Index of a Mii on the [`MiiSelector`] interface. /// @@ -100,8 +97,7 @@ impl MiiSelector { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # fn main() { /// use ctru::applets::mii_selector::MiiSelector; /// @@ -125,8 +121,7 @@ impl MiiSelector { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # fn main() { /// use ctru::applets::mii_selector::{MiiSelector, Options}; /// let mut mii_selector = MiiSelector::new(); @@ -150,8 +145,7 @@ impl MiiSelector { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -180,8 +174,7 @@ impl MiiSelector { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -205,8 +198,7 @@ impl MiiSelector { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -230,8 +222,7 @@ impl MiiSelector { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # fn main() { /// # /// use ctru::applets::mii_selector::{Index, MiiSelector}; @@ -269,8 +260,7 @@ impl MiiSelector { /// /// # Example /// - /// ``` - /// # let _runner = test_runner::GdbRunner::default(); + /// ```no_run /// # use std::error::Error; /// # fn main() -> Result<(), Box> { /// # diff --git a/ctru-rs/src/applets/swkbd.rs b/ctru-rs/src/applets/swkbd.rs index 931b1c7..8497233 100644 --- a/ctru-rs/src/applets/swkbd.rs +++ b/ctru-rs/src/applets/swkbd.rs @@ -5,15 +5,14 @@ // TODO: Split the Parental PIN lock operations into a different type. #![doc(alias = "keyboard")] -use std::fmt::Display; -use std::iter::once; -use std::str; - use bitflags::bitflags; use ctru_sys::{ self, swkbdInit, swkbdInputText, swkbdSetButton, swkbdSetFeatures, swkbdSetHintText, SwkbdState, }; use libc; +use std::fmt::Display; +use std::iter::once; +use std::str; /// Configuration structure to setup the Software Keyboard applet. #[doc(alias = "SwkbdState")] diff --git a/ctru-rs/src/error.rs b/ctru-rs/src/error.rs index a91da3f..b01d898 100644 --- a/ctru-rs/src/error.rs +++ b/ctru-rs/src/error.rs @@ -3,9 +3,10 @@ //! This module holds the generic error and result types to interface with `ctru_sys` and the [`ctru-rs`](crate) safe wrapper. use std::borrow::Cow; +use std::error; use std::ffi::CStr; +use std::fmt; use std::ops::{ControlFlow, FromResidual, Try}; -use std::{error, fmt}; use ctru_sys::result::{R_DESCRIPTION, R_LEVEL, R_MODULE, R_SUMMARY}; @@ -27,7 +28,7 @@ pub type Result = ::std::result::Result; /// # let _runner = test_runner::GdbRunner::default(); /// // We run an unsafe function which returns a `ctru_sys::Result`. /// let result: ctru_sys::Result = unsafe { ctru_sys::hidInit() }; -/// +/// /// // The result code is parsed and any possible error gets returned by the function. /// ResultCode(result)?; /// Ok(()) diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index aeda735..72bdebd 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -76,9 +76,8 @@ pub fn use_panic_handler() { /// When `test` is enabled, this function will be ignored. #[cfg(not(test))] fn panic_hook_setup() { - use std::panic::PanicInfo; - use crate::services::hid::{Hid, KeyPad}; + use std::panic::PanicInfo; let main_thread = std::thread::current().id(); diff --git a/ctru-rs/src/prelude.rs b/ctru-rs/src/prelude.rs index 4e9bd68..ee18eab 100644 --- a/ctru-rs/src/prelude.rs +++ b/ctru-rs/src/prelude.rs @@ -3,7 +3,9 @@ //! Particularly useful when writing very small applications. pub use crate::console::Console; -pub use crate::services::apt::Apt; -pub use crate::services::gfx::Gfx; -pub use crate::services::hid::{Hid, KeyPad}; -pub use crate::services::soc::Soc; +pub use crate::services::{ + apt::Apt, + gfx::Gfx, + hid::{Hid, KeyPad}, + soc::Soc, +}; diff --git a/ctru-rs/src/services/am.rs b/ctru-rs/src/services/am.rs index 33c145f..cab13b3 100644 --- a/ctru-rs/src/services/am.rs +++ b/ctru-rs/src/services/am.rs @@ -8,10 +8,9 @@ #![doc(alias = "app")] #![doc(alias = "manager")] -use std::marker::PhantomData; - use crate::error::ResultCode; use crate::services::fs::FsMediaType; +use std::marker::PhantomData; /// General information about a specific title entry. #[doc(alias = "AM_TitleEntry")] diff --git a/ctru-rs/src/services/cam.rs b/ctru-rs/src/services/cam.rs index 596741c..449972d 100644 --- a/ctru-rs/src/services/cam.rs +++ b/ctru-rs/src/services/cam.rs @@ -4,12 +4,10 @@ //! in the form of byte vectors which can be displayed to the screen or used in other ways. #![doc(alias = "camera")] -use std::time::Duration; - -use ctru_sys::Handle; - use crate::error::{Error, ResultCode}; use crate::services::gspgpu::FramebufferFormat; +use ctru_sys::Handle; +use std::time::Duration; /// Handle to the Camera service. #[non_exhaustive] @@ -864,7 +862,7 @@ pub trait Camera { /// inward.set_auto_white_balance(true)?; /// /// // Size of the top screen buffer at 2 bytes per pixel (RGB565). - /// let mut buffer = vec![0; 400 * 240 * 2]; + /// let mut buffer = vec![0; 400*240*2]; /// /// // Take picture with 3 seconds of timeout. /// inward.take_picture(&mut buffer, 400, 240, Duration::from_secs(3)); diff --git a/ctru-rs/src/services/fs.rs b/ctru-rs/src/services/fs.rs index 2ae9bfb..0be5425 100644 --- a/ctru-rs/src/services/fs.rs +++ b/ctru-rs/src/services/fs.rs @@ -5,15 +5,17 @@ // TODO: Refactor service to accomodate for various changes (such as SMDH support). Properly document the public API. #![doc(alias = "filesystem")] +use bitflags::bitflags; use std::ffi::OsString; -use std::io::{ - Error as IoError, ErrorKind as IoErrorKind, Read, Result as IoResult, Seek, SeekFrom, Write, -}; +use std::io::Error as IoError; +use std::io::ErrorKind as IoErrorKind; +use std::io::Result as IoResult; +use std::io::{Read, Seek, SeekFrom, Write}; +use std::mem; use std::path::{Path, PathBuf}; +use std::ptr; +use std::slice; use std::sync::Arc; -use std::{mem, ptr, slice}; - -use bitflags::bitflags; use widestring::{WideCStr, WideCString}; bitflags! { @@ -259,8 +261,8 @@ pub struct Metadata { /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let result = OpenOptions::new() -/// .read(true) -/// .archive(&sdmc_archive) +/// .read(true) +/// .archive(&sdmc_archive) /// .open("foo.txt"); /// /// assert!(result.is_err()); @@ -276,12 +278,12 @@ pub struct Metadata { /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let file = OpenOptions::new() -/// .read(true) -/// .write(true) -/// .create(true) -/// .archive(&sdmc_archive) +/// .read(true) +/// .write(true) +/// .create(true) +/// .archive(&sdmc_archive) /// .open("/foo.txt") -/// .unwrap(); +/// .unwrap(); /// ``` #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct OpenOptions { @@ -392,7 +394,7 @@ impl File { /// # let _runner = test_runner::GdbRunner::default(); /// use ctru::services::fs::{File, Fs}; /// - /// let mut fs = Fs::new().unwrap(); + /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// // Non-existent file: /// assert!(File::open(&sdmc_archive, "/foo.txt").is_err()); @@ -421,7 +423,7 @@ impl File { /// # let _runner = test_runner::GdbRunner::default(); /// use ctru::services::fs::{File, Fs}; /// - /// let mut fs = Fs::new().unwrap(); + /// let mut fs = Fs::new().unwrap(); /// let mut sdmc_archive = fs.sdmc().unwrap(); /// let mut f = File::create(&mut sdmc_archive, "/foo.txt").unwrap(); /// ``` diff --git a/ctru-rs/src/services/hid.rs b/ctru-rs/src/services/hid.rs index 4b2a360..1e0ceee 100644 --- a/ctru-rs/src/services/hid.rs +++ b/ctru-rs/src/services/hid.rs @@ -7,9 +7,8 @@ #![doc(alias = "controller")] #![doc(alias = "gamepad")] -use bitflags::bitflags; - use crate::error::ResultCode; +use bitflags::bitflags; bitflags! { /// A set of flags corresponding to the button and directional pad inputs present on the 3DS. diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index a85a325..987881a 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -15,16 +15,17 @@ // https://github.com/citra-emu/citra/issues/6111 pub mod wave; -use std::cell::{RefCell, RefMut}; -use std::default::Default; -use std::sync::Mutex; -use std::{error, fmt}; - use wave::{Status, Wave}; use crate::error::ResultCode; use crate::services::ServiceReference; +use std::cell::{RefCell, RefMut}; +use std::default::Default; +use std::error; +use std::fmt; +use std::sync::Mutex; + const NUMBER_OF_CHANNELS: u8 = 24; /// Audio output mode. diff --git a/ctru-rs/src/services/ndsp/wave.rs b/ctru-rs/src/services/ndsp/wave.rs index 79659fd..9c467e0 100644 --- a/ctru-rs/src/services/ndsp/wave.rs +++ b/ctru-rs/src/services/ndsp/wave.rs @@ -42,8 +42,7 @@ impl Wave { /// # let _runner = test_runner::GdbRunner::default(); /// # /// use ctru::linear::LinearAllocator; - /// use ctru::services::ndsp::wave::Wave; - /// use ctru::services::ndsp::AudioFormat; + /// use ctru::services::ndsp::{AudioFormat, wave::Wave}; /// /// // Zeroed box allocated in the LINEAR memory. /// let audio_data = Box::new_in([0u8; 96], LinearAllocator); @@ -120,8 +119,7 @@ impl Wave { /// # use ctru::linear::LinearAllocator; /// # let _audio_data = Box::new_in([0u8; 96], LinearAllocator); /// # - /// use ctru::services::ndsp::wave::{Status, Wave}; - /// use ctru::services::ndsp::AudioFormat; + /// use ctru::services::ndsp::{AudioFormat, wave::{Wave, Status}}; /// /// // Provide your own audio data. /// let wave = Wave::new(_audio_data, AudioFormat::PCM16Stereo, false); diff --git a/ctru-rs/src/services/reference.rs b/ctru-rs/src/services/reference.rs index 7f6f5ed..41319a7 100644 --- a/ctru-rs/src/services/reference.rs +++ b/ctru-rs/src/services/reference.rs @@ -1,6 +1,5 @@ -use std::sync::Mutex; - use crate::Error; +use std::sync::Mutex; pub(crate) struct ServiceReference { counter: &'static Mutex, close: Box, diff --git a/ctru-rs/src/services/romfs.rs b/ctru-rs/src/services/romfs.rs index fdf65d7..4018a7c 100644 --- a/ctru-rs/src/services/romfs.rs +++ b/ctru-rs/src/services/romfs.rs @@ -27,10 +27,10 @@ #![doc(alias = "embed")] #![doc(alias = "filesystem")] +use crate::error::ResultCode; use std::ffi::CStr; use std::sync::Mutex; -use crate::error::ResultCode; use crate::services::ServiceReference; /// Handle to the RomFS service. diff --git a/ctru-rs/src/services/soc.rs b/ctru-rs/src/services/soc.rs index 2797ae6..548e44d 100644 --- a/ctru-rs/src/services/soc.rs +++ b/ctru-rs/src/services/soc.rs @@ -5,11 +5,10 @@ #![doc(alias = "socket")] #![doc(alias = "network")] +use libc::memalign; use std::net::Ipv4Addr; use std::sync::Mutex; -use libc::memalign; - use crate::error::ResultCode; use crate::services::ServiceReference; use crate::Error; From a187a503cce077a7dd221b7cdc037c60040623fd Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sat, 30 Sep 2023 09:38:13 -0400 Subject: [PATCH 11/16] Update references to point at rust3ds/test-runner --- .github/workflows/ci.yml | 8 ++++---- ctru-rs/Cargo.toml | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c43d8a..017fc2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@v2 # TODO point to to rust3ds/test-runner once migrated - - uses: ian-h-chamberlain/test-runner-3ds/setup@v1 + - uses: rust3ds/test-runner/setup@v1 with: toolchain: ${{ matrix.toolchain }} @@ -63,7 +63,7 @@ jobs: - name: Checkout branch uses: actions/checkout@v2 - - uses: ian-h-chamberlain/test-runner-3ds/setup@v1 + - uses: rust3ds/test-runner/setup@v1 with: toolchain: ${{ matrix.toolchain }} @@ -79,12 +79,12 @@ jobs: run: cargo 3ds test --no-run --tests --package ctru-rs - name: Run lib and integration tests - uses: ian-h-chamberlain/test-runner-3ds/run-tests@v1 + uses: rust3ds/test-runner/run-tests@v1 with: args: --tests --package ctru-rs - name: Build and run doc tests - uses: ian-h-chamberlain/test-runner-3ds/run-tests@v1 + uses: rust3ds/test-runner/run-tests@v1 with: args: --doc --package ctru-rs diff --git a/ctru-rs/Cargo.toml b/ctru-rs/Cargo.toml index bdd7a4d..ac10586 100644 --- a/ctru-rs/Cargo.toml +++ b/ctru-rs/Cargo.toml @@ -34,8 +34,7 @@ cfg-if = "1.0.0" ferris-says = "0.2.1" futures = "0.3" lewton = "0.10.2" -# TODO: switch to rust3ds org once migrated there. Also, rename? -test-runner = { git = "https://github.com/ian-h-chamberlain/test-runner-3ds" } +test-runner = { git = "https://github.com/rust3ds/test-runner.git" } time = "0.3.7" tokio = { version = "1.16", features = ["rt", "time", "sync", "macros"] } From c2827aa2691ce4c9dfe5ae7cb98d38ba97bb934b Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sat, 30 Sep 2023 23:54:08 -0400 Subject: [PATCH 12/16] Add `os` module for querying OS and hardware state Most of these are dead simple and don't require any service initialization etc., so all we need is a simple wrapper. I didn't implement everything in <3ds/os.h> yet, but got most of the basic ones which seemed like likely use cases to me. --- ctru-rs/src/error.rs | 4 +- ctru-rs/src/lib.rs | 1 + ctru-rs/src/os.rs | 135 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 ctru-rs/src/os.rs diff --git a/ctru-rs/src/error.rs b/ctru-rs/src/error.rs index 41b09f8..62a4646 100644 --- a/ctru-rs/src/error.rs +++ b/ctru-rs/src/error.rs @@ -27,7 +27,7 @@ pub type Result = ::std::result::Result; /// pub fn hid_init() -> Result<()> { /// // We run an unsafe function which returns a `ctru_sys::Result`. /// let result: ctru_sys::Result = unsafe { ctru_sys::hidInit() }; -/// +/// /// // The result code is parsed and any possible error gets returned by the function. /// ResultCode(result)?; /// Ok(()) @@ -152,6 +152,8 @@ impl fmt::Debug for Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + // TODO: should we consider using ctru_sys::osStrError here as well? + // It might do some of the work for us or provide additional details &Self::Os(err) => write!( f, "libctru result code 0x{err:08X}: [{} {}] {}: {}", diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index ecc7dd9..baa9936 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -107,6 +107,7 @@ pub mod console; pub mod error; pub mod linear; pub mod mii; +pub mod os; pub mod prelude; pub mod services; diff --git a/ctru-rs/src/os.rs b/ctru-rs/src/os.rs new file mode 100644 index 0000000..58a4e87 --- /dev/null +++ b/ctru-rs/src/os.rs @@ -0,0 +1,135 @@ +//! Utilities to get information about the operating system and hardware state. + +/// System version information. +#[derive(Clone, Copy)] +pub struct Version(u32); + +impl Version { + /// Pack a system version from its components + pub fn new(major: u8, minor: u8, revision: u8) -> Self { + let major = u32::from(major); + let minor = u32::from(minor); + let revision = u32::from(revision); + + Self(major << 24 | minor << 16 | revision << 8) + } + + /// Get the major version from a packed system version. + pub fn major(&self) -> u8 { + (self.0 >> 24).try_into().unwrap() + } + + /// Get the minor version from a packed system version. + pub fn minor(&self) -> u8 { + (self.0 >> 16 & 0xFF).try_into().unwrap() + } + + /// Get the revision from a packed system version. + pub fn revision(&self) -> u8 { + (self.0 >> 8 & 0xFF).try_into().unwrap() + } +} + +/// Get the system's FIRM version. +pub fn firm_version() -> Version { + Version(unsafe { ctru_sys::osGetFirmVersion() }) +} + +/// Get the system's kernel version. +pub fn kernel_version() -> Version { + Version(unsafe { ctru_sys::osGetKernelVersion() }) +} + +// TODO: I can't seem to find good documentation on it, but we could probably +// define enums for firmware type (NATIVE_FIRM, SAFE_FIRM etc.) as well as +// application memory layout. Leaving those as future enhancements for now + +/// A region of memory. Most applications will only use [`Application`](MemRegion::Application) +/// memory, but the other types can be used to query memory usage information. +/// See +/// for more details on the different types of memory. +/// +/// # Example +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); +/// let all_memory = ctru::os::MemRegion::All; +/// +/// assert!(all_memory.size() > 0); +/// assert!(all_memory.used() > 0); +/// assert!(all_memory.free() > 0); +/// ``` +#[derive(Clone, Copy, Debug)] +#[non_exhaustive] +#[repr(u32)] +pub enum MemRegion { + /// All memory regions. + All = ctru_sys::MEMREGION_ALL, + /// APPLICATION memory. + Application = ctru_sys::MEMREGION_APPLICATION, + /// SYSTEM memory. + System = ctru_sys::MEMREGION_SYSTEM, + /// BASE memory. + Base = ctru_sys::MEMREGION_BASE, +} + +impl MemRegion { + /// Get the total size of this memory region, in bytes. + pub fn size(&self) -> usize { + unsafe { ctru_sys::osGetMemRegionSize(*self as u32) } + .try_into() + .unwrap() + } + + /// Get the number of bytes used within this memory region. + pub fn used(&self) -> usize { + unsafe { ctru_sys::osGetMemRegionUsed(*self as u32) } + .try_into() + .unwrap() + } + + /// Get the number of bytes free within this memory region. + pub fn free(&self) -> usize { + unsafe { ctru_sys::osGetMemRegionFree(*self as u32) } + .try_into() + .unwrap() + } +} + +/// WiFi signal strength. This enum's [`u8`] representation corresponds with +/// the number of bars displayed in the Home menu. +#[non_exhaustive] +#[repr(u8)] +pub enum WifiStrength { + /// This may indicate a very poor signal quality even worse than `Bad`, + /// or it may indicate that no network is connected at all. + Disconnected = 0, + /// Poor signal strength. + Bad = 1, + /// Medium signal strength. + Decent = 2, + /// Good signal strength. + Good = 3, +} + +impl WifiStrength { + /// Get the current WiFi signal strength. + pub fn current() -> Self { + match unsafe { ctru_sys::osGetWifiStrength() } { + 0 => Self::Disconnected, + 1 => Self::Bad, + 2 => Self::Decent, + 3 => Self::Good, + other => panic!("Got unexpected WiFi strength value {other}"), + } + } +} + +/// Get the current value of the stereoscopic 3D slider on a scale from 0.0­–­1.0. +pub fn current_3d_slider_state() -> f32 { + unsafe { ctru_sys::osGet3DSliderState() } +} + +/// Whether or not a headset is currently plugged into the device. +pub fn is_headset_connected() -> bool { + unsafe { ctru_sys::osIsHeadsetConnected() } +} From 6aa50357c8b6bfbd435a7c745fc1d1d9dcb67443 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sun, 1 Oct 2023 00:07:49 -0400 Subject: [PATCH 13/16] Add some simple doctests for some new functions --- ctru-rs/src/os.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/ctru-rs/src/os.rs b/ctru-rs/src/os.rs index 58a4e87..8be1de1 100644 --- a/ctru-rs/src/os.rs +++ b/ctru-rs/src/os.rs @@ -1,6 +1,16 @@ //! Utilities to get information about the operating system and hardware state. -/// System version information. +/// System version information. This struct is used for both kernel and firmware versions. +/// +/// # Example +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); +/// let firm_version = ctru::os::firm_version(); +/// assert_ne!(firm_version.major(), 0); +/// +/// let kernel_version = ctru::os::kernel_version(); +/// assert_ne!(kernel_version.major(), 0); +/// ``` #[derive(Clone, Copy)] pub struct Version(u32); @@ -95,13 +105,22 @@ impl MemRegion { } } -/// WiFi signal strength. This enum's [`u8`] representation corresponds with +/// WiFi signal strength. This enum's `u8` representation corresponds with /// the number of bars displayed in the Home menu. +/// +/// # Example +/// +/// ``` +/// # let _runner = test_runner::GdbRunner::default(); +/// let strength = ctru::os::WifiStrength::current(); +/// assert!((strength as u8) < 4); +/// ``` +#[derive(Clone, Copy, Debug)] #[non_exhaustive] #[repr(u8)] pub enum WifiStrength { /// This may indicate a very poor signal quality even worse than `Bad`, - /// or it may indicate that no network is connected at all. + /// or that no network is connected at all. Disconnected = 0, /// Poor signal strength. Bad = 1, From 421a09bc37ab8a2311498be1b6a898b15a4697f7 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sun, 8 Oct 2023 17:33:18 -0400 Subject: [PATCH 14/16] Remove references to test_runner temporarily --- ctru-rs/src/os.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ctru-rs/src/os.rs b/ctru-rs/src/os.rs index 8be1de1..8eea697 100644 --- a/ctru-rs/src/os.rs +++ b/ctru-rs/src/os.rs @@ -4,7 +4,7 @@ /// /// # Example /// ``` -/// # let _runner = test_runner::GdbRunner::default(); +/// # // let _runner = test_runner::GdbRunner::default(); /// let firm_version = ctru::os::firm_version(); /// assert_ne!(firm_version.major(), 0); /// @@ -61,7 +61,7 @@ pub fn kernel_version() -> Version { /// /// # Example /// ``` -/// # let _runner = test_runner::GdbRunner::default(); +/// # // let _runner = test_runner::GdbRunner::default(); /// let all_memory = ctru::os::MemRegion::All; /// /// assert!(all_memory.size() > 0); @@ -111,7 +111,7 @@ impl MemRegion { /// # Example /// /// ``` -/// # let _runner = test_runner::GdbRunner::default(); +/// # // let _runner = test_runner::GdbRunner::default(); /// let strength = ctru::os::WifiStrength::current(); /// assert!((strength as u8) < 4); /// ``` From 0ff7cae9b4b43feded0cd48126e2da0ff56753e7 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sat, 21 Oct 2023 14:25:59 -0400 Subject: [PATCH 15/16] Clean up minor leftover comments --- .github/workflows/ci.yml | 1 - ctru-rs/src/os.rs | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 017fc2e..69a3978 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,6 @@ jobs: - name: Checkout branch uses: actions/checkout@v2 - # TODO point to to rust3ds/test-runner once migrated - uses: rust3ds/test-runner/setup@v1 with: toolchain: ${{ matrix.toolchain }} diff --git a/ctru-rs/src/os.rs b/ctru-rs/src/os.rs index 8eea697..baf654c 100644 --- a/ctru-rs/src/os.rs +++ b/ctru-rs/src/os.rs @@ -4,7 +4,7 @@ /// /// # Example /// ``` -/// # // let _runner = test_runner::GdbRunner::default(); +/// # let _runner = test_runner::GdbRunner::default(); /// let firm_version = ctru::os::firm_version(); /// assert_ne!(firm_version.major(), 0); /// @@ -61,7 +61,7 @@ pub fn kernel_version() -> Version { /// /// # Example /// ``` -/// # // let _runner = test_runner::GdbRunner::default(); +/// # let _runner = test_runner::GdbRunner::default(); /// let all_memory = ctru::os::MemRegion::All; /// /// assert!(all_memory.size() > 0); @@ -111,7 +111,7 @@ impl MemRegion { /// # Example /// /// ``` -/// # // let _runner = test_runner::GdbRunner::default(); +/// let _runner = test_runner::GdbRunner::default(); /// let strength = ctru::os::WifiStrength::current(); /// assert!((strength as u8) < 4); /// ``` From 2e442752b47b5b09525560cf2257f1deb3021922 Mon Sep 17 00:00:00 2001 From: Lena Date: Wed, 25 Oct 2023 15:33:12 +0200 Subject: [PATCH 16/16] add `set_initial_text` swkbd method --- ctru-rs/src/applets/swkbd.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/ctru-rs/src/applets/swkbd.rs b/ctru-rs/src/applets/swkbd.rs index 8497233..69d4329 100644 --- a/ctru-rs/src/applets/swkbd.rs +++ b/ctru-rs/src/applets/swkbd.rs @@ -7,7 +7,8 @@ use bitflags::bitflags; use ctru_sys::{ - self, swkbdInit, swkbdInputText, swkbdSetButton, swkbdSetFeatures, swkbdSetHintText, SwkbdState, + self, swkbdInit, swkbdInputText, swkbdSetButton, swkbdSetFeatures, swkbdSetHintText, + swkbdSetInitialText, SwkbdState, }; use libc; use std::fmt::Display; @@ -336,6 +337,30 @@ impl SoftwareKeyboard { self.state.max_digits = digits; } + /// Set the initial text for this software keyboard. + /// + /// The initial text is the text already written when you open the software keyboard. + /// + /// # Example + /// + /// ``` + /// # let _runner = test_runner::GdbRunner::default(); + /// # fn main() { + /// # + /// use ctru::applets::swkbd::SoftwareKeyboard; + /// let mut keyboard = SoftwareKeyboard::default(); + /// + /// keyboard.set_initial_text("Write here what you like!"); + /// # + /// # } + #[doc(alias = "swkbdSetInitialText")] + pub fn set_initial_text(&mut self, text: &str) { + unsafe { + let nul_terminated: String = text.chars().chain(once('\0')).collect(); + swkbdSetInitialText(self.state.as_mut(), nul_terminated.as_ptr()); + } + } + /// Set the hint text for this software keyboard. /// /// The hint text is the text shown in gray before any text gets written in the input box.