Skip to content

Commit 44e6231

Browse files
committed
rust: move async helper functions to the util crate
So the bitbox02 crate can also use it. It will be needed to be able to use block_on() in the tests there.
1 parent 6d0099b commit 44e6231

File tree

8 files changed

+71
-49
lines changed

8 files changed

+71
-49
lines changed

src/rust/bitbox02-rust/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ app-cardano = [
101101
]
102102

103103
testing = [
104-
"bitbox02/testing"
104+
"bitbox02/testing",
105+
"util/testing"
105106
]
106107

107108
c-unit-testing = []

src/rust/bitbox02-rust/src/bb02_async.rs

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,11 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use alloc::boxed::Box;
1615
use core::cell::RefCell;
17-
use core::pin::Pin;
18-
use core::task::{Context, Poll};
1916

20-
/// Task is the top-level future which can be polled by an executor.
21-
/// Note that other futures awaited inside do not have to be pinned.
22-
/// The 'a lifetime allows to spin a boxed/pinned future that is not
23-
/// 'static, or a future with non-'static input param references.
24-
pub type Task<'a, O> = Pin<Box<dyn core::future::Future<Output = O> + 'a>>;
25-
26-
/// A primitive poll invocation for a task, with no waking functionality.
27-
pub fn spin<O>(task: &mut Task<O>) -> Poll<O> {
28-
// TODO: statically allocate the context.
29-
let waker = crate::waker_fn::waker_fn(|| {});
30-
let context = &mut Context::from_waker(&waker);
31-
task.as_mut().poll(context)
32-
}
33-
34-
/// Implements the Option future, see `option()`.
35-
pub struct AsyncOption<'a, O>(&'a RefCell<Option<O>>);
36-
37-
impl<O> core::future::Future for AsyncOption<'_, O> {
38-
type Output = O;
39-
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
40-
match self.0.borrow_mut().take() {
41-
None => Poll::Pending,
42-
Some(output) => Poll::Ready(output),
43-
}
44-
}
45-
}
17+
#[cfg(feature = "testing")]
18+
pub use util::bb02_async::block_on;
19+
pub use util::bb02_async::{Task, option, spin};
4620

4721
/// Disables the screensaver while waiting for an option to contain a value. Afterwards, it returns that value
4822
pub async fn option_no_screensaver<O>(opt: &RefCell<Option<O>>) -> O {
@@ -51,20 +25,3 @@ pub async fn option_no_screensaver<O>(opt: &RefCell<Option<O>>) -> O {
5125
bitbox02::screen_saver::screen_saver_enable();
5226
result
5327
}
54-
55-
/// Waits for an option to contain a value and returns that value, leaving `None` in its place.
56-
/// E.g. `assert_eq!(option(&Some(42)).await, 42)`.
57-
pub fn option<O>(option: &RefCell<Option<O>>) -> AsyncOption<'_, O> {
58-
AsyncOption(option)
59-
}
60-
61-
/// Polls a future until the result is available.
62-
#[cfg(feature = "testing")]
63-
pub fn block_on<O>(task: impl core::future::Future<Output = O>) -> O {
64-
let mut task: crate::bb02_async::Task<O> = alloc::boxed::Box::pin(task);
65-
loop {
66-
if let Poll::Ready(result) = spin(&mut task) {
67-
return result;
68-
}
69-
}
70-
}

src/rust/bitbox02-rust/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ pub mod secp256k1;
4040
#[cfg(feature = "app-u2f")]
4141
mod u2f;
4242
mod version;
43-
mod waker_fn;
4443
pub mod workflow;
4544
#[cfg(any(feature = "app-bitcoin", feature = "app-litecoin"))]
4645
mod xpubcache;

src/rust/bitbox02/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ bitbox02-rust = { path = "../bitbox02-rust" }
3636

3737
[features]
3838
# Only to be enabled in unit tests and simulators
39-
testing = []
39+
testing = ["util/testing"]
4040
# Enables UI stubs for rust unit tests
4141
unit-testing = []
4242
# Active when the Rust code is compiled to be linked into the C unit tests and simulator.

src/rust/util/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ bitcoin = {workspace = true}
3131

3232
[features]
3333
rtt = ["dep:rtt-target", "dep:cortex-m"]
34+
testing = []
3435
c-unit-testing = []
3536
firmware = []

src/rust/util/src/bb02_async.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2025 Shift Crypto AG
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use alloc::boxed::Box;
16+
use core::cell::RefCell;
17+
use core::pin::Pin;
18+
use core::task::{Context, Poll};
19+
20+
/// Task is the top-level future which can be polled by an executor.
21+
/// Note that other futures awaited inside do not have to be pinned.
22+
/// The 'a lifetime allows to spin a boxed/pinned future that is not
23+
/// 'static, or a future with non-'static input param references.
24+
pub type Task<'a, O> = Pin<Box<dyn core::future::Future<Output = O> + 'a>>;
25+
26+
/// A primitive poll invocation for a task, with no waking functionality.
27+
pub fn spin<O>(task: &mut Task<O>) -> Poll<O> {
28+
// TODO: statically allocate the context.
29+
let waker = crate::waker_fn::waker_fn(|| {});
30+
let context = &mut Context::from_waker(&waker);
31+
task.as_mut().poll(context)
32+
}
33+
34+
/// Implements the Option future, see `option()`.
35+
pub struct AsyncOption<'a, O>(&'a RefCell<Option<O>>);
36+
37+
impl<O> core::future::Future for AsyncOption<'_, O> {
38+
type Output = O;
39+
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
40+
match self.0.borrow_mut().take() {
41+
None => Poll::Pending,
42+
Some(output) => Poll::Ready(output),
43+
}
44+
}
45+
}
46+
47+
/// Waits for an option to contain a value and returns that value, leaving `None` in its place.
48+
/// E.g. `assert_eq!(option(&Some(42)).await, 42)`.
49+
pub fn option<O>(option: &RefCell<Option<O>>) -> AsyncOption<'_, O> {
50+
AsyncOption(option)
51+
}
52+
53+
/// Polls a future until the result is available.
54+
#[cfg(feature = "testing")]
55+
pub fn block_on<O>(task: impl core::future::Future<Output = O>) -> O {
56+
let mut task: crate::bb02_async::Task<O> = alloc::boxed::Box::pin(task);
57+
loop {
58+
if let Poll::Ready(result) = spin(&mut task) {
59+
return result;
60+
}
61+
}
62+
}

src/rust/util/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414

1515
#![cfg_attr(not(test), no_std)]
1616
pub mod ascii;
17+
pub mod bb02_async;
1718
pub mod bip32;
1819
pub mod bytes;
1920
pub mod cell;
2021
pub mod decimal;
2122
pub mod log;
2223
pub mod name;
24+
mod waker_fn;
2325

2426
mod base58;
2527
#[cfg(feature = "p256")]
File renamed without changes.

0 commit comments

Comments
 (0)