mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-06 23:02:33 +00:00

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.
86 lines
3.2 KiB
Rust
86 lines
3.2 KiB
Rust
use core::{
|
|
convert::{Infallible, TryInto},
|
|
num::TryFromIntError,
|
|
};
|
|
|
|
use cstr_core::CStr;
|
|
|
|
#[cfg(feature = "micropython")]
|
|
use crate::micropython::{ffi, obj::Obj, qstr::Qstr};
|
|
|
|
#[allow(clippy::enum_variant_names)] // We mimic the Python exception classnames here.
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
TypeError,
|
|
OutOfRange,
|
|
MissingKwargs,
|
|
AllocationFailed,
|
|
#[cfg(feature = "micropython")]
|
|
CaughtException(Obj),
|
|
#[cfg(feature = "micropython")]
|
|
KeyError(Obj),
|
|
#[cfg(feature = "micropython")]
|
|
AttributeError(Qstr),
|
|
#[cfg(feature = "micropython")]
|
|
ValueError(&'static CStr),
|
|
#[cfg(feature = "micropython")]
|
|
ValueErrorParam(&'static CStr, Obj),
|
|
}
|
|
|
|
#[cfg(feature = "micropython")]
|
|
impl Error {
|
|
/// Create an exception instance matching the error code. The result of this
|
|
/// call should only be used to immediately raise the exception, because the
|
|
/// object is not guaranteed to remain intact. MicroPython might reuse the
|
|
/// same space for creating a different exception.
|
|
pub unsafe fn into_obj(self) -> Obj {
|
|
unsafe {
|
|
// SAFETY: First argument is a reference to a valid exception type.
|
|
// EXCEPTION: Sensibly, `new_exception_*` does not raise.
|
|
match self {
|
|
Error::TypeError => ffi::mp_obj_new_exception(&ffi::mp_type_TypeError),
|
|
Error::OutOfRange => ffi::mp_obj_new_exception(&ffi::mp_type_OverflowError),
|
|
Error::MissingKwargs => ffi::mp_obj_new_exception(&ffi::mp_type_TypeError),
|
|
Error::AllocationFailed => ffi::mp_obj_new_exception(&ffi::mp_type_MemoryError),
|
|
Error::CaughtException(obj) => obj,
|
|
Error::KeyError(key) => {
|
|
ffi::mp_obj_new_exception_args(&ffi::mp_type_KeyError, 1, &key)
|
|
}
|
|
Error::ValueError(msg) => {
|
|
if let Ok(msg) = msg.try_into() {
|
|
ffi::mp_obj_new_exception_args(&ffi::mp_type_ValueError, 1, &msg)
|
|
} else {
|
|
ffi::mp_obj_new_exception(&ffi::mp_type_ValueError)
|
|
}
|
|
}
|
|
Error::ValueErrorParam(msg, param) => {
|
|
if let Ok(msg) = msg.try_into() {
|
|
let args = [msg, param];
|
|
ffi::mp_obj_new_exception_args(&ffi::mp_type_ValueError, 2, args.as_ptr())
|
|
} else {
|
|
ffi::mp_obj_new_exception(&ffi::mp_type_ValueError)
|
|
}
|
|
}
|
|
Error::AttributeError(attr) => {
|
|
ffi::mp_obj_new_exception_args(&ffi::mp_type_AttributeError, 1, &attr.into())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Implements a conversion from `core::convert::Infallible` to `Error` to so
|
|
// that code generic over `TryFrom` can work with values covered by the blanket
|
|
// impl for `Into`: `https://doc.rust-lang.org/std/convert/enum.Infallible.html`
|
|
impl From<Infallible> for Error {
|
|
fn from(_: Infallible) -> Self {
|
|
unreachable!()
|
|
}
|
|
}
|
|
|
|
impl From<TryFromIntError> for Error {
|
|
fn from(_: TryFromIntError) -> Self {
|
|
Self::OutOfRange
|
|
}
|
|
}
|