1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-31 18:40:56 +00:00

refactor(core/rust): expose obj types and (debug only) type names

This commit is contained in:
matejcik 2023-06-20 11:51:40 +02:00 committed by matejcik
parent ccddc8f5f3
commit b91e225076
4 changed files with 46 additions and 11 deletions

View File

@ -222,6 +222,8 @@ fn generate_micropython_bindings() {
// module
.allowlist_type("mp_obj_module_t")
.allowlist_var("mp_type_module")
// qstr
.allowlist_function("qstr_data")
// `ffi::mp_map_t` type is not allowed to be `Clone` or `Copy` because we tie it
// to the data lifetimes with the `MapRef` type, see `src/micropython/map.rs`.
// TODO: We should disable `Clone` and `Copy` for all types and only allow-list

View File

@ -441,4 +441,21 @@ impl Obj {
let is_type_str = unsafe { ffi::mp_type_str.is_type_of(self) };
is_type_str || self.is_qstr()
}
pub fn type_<'a>(self) -> Option<&'a super::typ::Type> {
if self.is_ptr() {
// SAFETY:
// Safe for pointers, for as long as MicroPython behaves sanely.
// We assume that:
// * The pointer is a valid MicroPython object, which has `ObjBase`
// as its first element.
// * The type pointer points to a valid type object.
// * The pointee has a 'static lifetime, i.e., either is
// ROM-based, or GC allocated.
let base = self.as_ptr() as *const ObjBase;
unsafe { (*base).type_.as_ref() }
} else {
None
}
}
}

View File

@ -2,9 +2,11 @@
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
use core::convert::TryFrom;
use core::{convert::TryFrom, slice, str::from_utf8};
use crate::{error::Error, micropython::obj::Obj};
use crate::error::Error;
use super::{ffi, obj::Obj};
impl Qstr {
pub const fn to_obj(self) -> Obj {
@ -30,6 +32,19 @@ impl Qstr {
// TODO: Change the internal representation of Qstr to u16.
Self(val as _)
}
pub fn as_str(self) -> &'static str {
let mut len = 0usize;
let slice = unsafe {
// SAFETY: qstr_data should always return a valid string, even for unknown ids.
let ptr = ffi::qstr_data(self.0 as _, &mut len as *mut _);
slice::from_raw_parts(ptr, len)
};
// SAFETY: Qstr pools are either ROM-based or permanently allocated in the GC
// arena. The MicroPython runtime holds the respective head pointers so we don't
// need to care.
unwrap!(from_utf8(slice))
}
}
impl From<u16> for Qstr {

View File

@ -7,21 +7,22 @@ pub type Type = ffi::mp_obj_type_t;
impl Type {
pub fn is_type_of(&'static self, obj: Obj) -> bool {
if obj.is_ptr() {
// SAFETY: If `obj` is a pointer, it should always point to an object having
// `ObjBase` as the first field, making this cast safe.
unsafe {
let base = obj.as_ptr() as *const ObjBase;
(*base).type_ == self
}
} else {
false
match obj.type_() {
Some(type_) => core::ptr::eq(type_, self),
None => false,
}
}
pub const fn as_base(&'static self) -> ObjBase {
ObjBase { type_: self }
}
#[cfg(feature = "debug")]
pub fn name(&self) -> &'static str {
use super::qstr::Qstr;
Qstr::from(self.name).as_str()
}
}
// SAFETY: We are in a single-threaded environment.