1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-13 01:58:08 +00:00
trezor-firmware/core/embed/rust/src/micropython/util.rs
matejcik 2aa427a6e3 feat(core/rust): make Rust buildable without Micropython
Features `micropython` and `protobuf` are defined. Protobuf implies micropython
because our protobuf impl is pretty much _for_ micropython.

The respective subdirs are included only if the matching feature is defined.

util.rs is moved to micropython because it mostly concerns micropython interop

ResultExt, useful only for ui_debug, is moved to ui::util.

A new module `trezorhal::time` is provided. It mirrors functionality of
`micropython::time` via stmlib functions.  The intended use is to always use
functions from `trezorhal::time`. The right micropython variants are used when
micropython is available, otherwise the pure stmlib versions are called.

ui::*::layout is conditional for micropython feature, because it only concerns
micropython layouts. If we want to reuse layouts defined there, we will need to
export them to not depend on Objs and Qstrs etc.
2022-06-16 13:08:07 +02:00

84 lines
2.5 KiB
Rust

use core::slice;
use crate::{
error::Error,
micropython::{
map::{Map, MapElem},
obj::Obj,
runtime::raise_exception,
},
};
/// Perform a call and convert errors into a raised MicroPython exception.
/// Should only called when returning from Rust to C. See `raise_exception` for
/// details.
pub unsafe fn try_or_raise<T>(func: impl FnOnce() -> Result<T, Error>) -> T {
func().unwrap_or_else(|err| unsafe {
raise_exception(err);
})
}
/// Extract kwargs from a C call and pass them into Rust. Raise exception if an
/// error occurs. Should only called when returning from Rust to C. See
/// `raise_exception` for details.
pub unsafe fn try_with_kwargs(
kwargs: *const Map,
func: impl FnOnce(&Map) -> Result<Obj, Error>,
) -> Obj {
let block = || {
let kwargs = unsafe { kwargs.as_ref() }.ok_or(Error::MissingKwargs)?;
func(kwargs)
};
unsafe { try_or_raise(block) }
}
/// Extract args and kwargs from a C call and pass them into Rust. Raise
/// exception if an error occurs. Should only called when returning from Rust to
/// C. See `raise_exception` for details.
pub unsafe fn try_with_args_and_kwargs(
n_args: usize,
args: *const Obj,
kwargs: *const Map,
func: impl FnOnce(&[Obj], &Map) -> Result<Obj, Error>,
) -> Obj {
let block = || {
let args = if args.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(args, n_args) }
};
let kwargs = unsafe { kwargs.as_ref() }.ok_or(Error::MissingKwargs)?;
func(args, kwargs)
};
unsafe { try_or_raise(block) }
}
/// Extract args and kwargs from a C call where args and kwargs are inlined, and
/// pass them into Rust. Raise exception if an error occurs. Should only called
/// when returning from Rust to C. See `raise_exception` for details.
pub unsafe fn try_with_args_and_kwargs_inline(
n_args: usize,
n_kw: usize,
args: *const Obj,
func: impl FnOnce(&[Obj], &Map) -> Result<Obj, Error>,
) -> Obj {
let block = || {
let args_slice: &[Obj];
let kwargs_slice: &[MapElem];
if args.is_null() {
args_slice = &[];
kwargs_slice = &[];
} else {
args_slice = unsafe { slice::from_raw_parts(args, n_args) };
kwargs_slice = unsafe { slice::from_raw_parts(args.add(n_args).cast(), n_kw) };
}
let kw_map = Map::from_fixed(kwargs_slice);
func(args_slice, &kw_map)
};
unsafe { try_or_raise(block) }
}