1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-18 05:28:40 +00:00

refactor(core/rust): move iter_into_array to micropython::utils

This commit is contained in:
matejcik 2024-01-17 15:40:19 +01:00 committed by Jiří Musil
parent 3b88116bba
commit 8bf5a72843
6 changed files with 61 additions and 51 deletions

View File

@ -241,6 +241,8 @@ fn generate_micropython_bindings() {
.allowlist_var("mp_type_module")
// qstr
.allowlist_function("qstr_data")
// tuple
.allowlist_type("mp_obj_tuple_t")
// `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

@ -2,5 +2,6 @@
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
#![allow(clippy::unnecessary_cast)]
#![allow(unsafe_op_in_unsafe_fn)]
include!(concat!(env!("OUT_DIR"), "/micropython.rs"));

View File

@ -1,13 +1,15 @@
use core::slice;
use crate::{
error::Error,
micropython::{
map::{Map, MapElem},
obj::Obj,
runtime::raise_exception,
},
use heapless::Vec;
use super::{
ffi,
iter::IterBuf,
map::{Map, MapElem},
obj::Obj,
runtime::{catch_exception, raise_exception},
};
use crate::error::Error;
/// Perform a call and convert errors into a raised MicroPython exception.
/// Should only called when returning from Rust to C. See `raise_exception` for
@ -82,3 +84,34 @@ pub unsafe fn try_with_args_and_kwargs_inline(
};
unsafe { try_or_raise(block) }
}
pub fn new_tuple(args: &[Obj]) -> Result<Obj, Error> {
// SAFETY: Safe.
// EXCEPTION: Raises if allocation fails, does not return NULL.
let obj = catch_exception(|| unsafe { ffi::mp_obj_new_tuple(args.len(), args.as_ptr()) })?;
Ok(obj)
}
pub fn iter_into_array<T, E, const N: usize>(iterable: Obj) -> Result<[T; N], Error>
where
T: TryFrom<Obj, Error = E>,
Error: From<E>,
{
let vec: Vec<T, N> = iter_into_vec(iterable)?;
// Returns error if array.len() != N
vec.into_array()
.map_err(|_| value_error!("Invalid iterable length"))
}
pub fn iter_into_vec<T, E, const N: usize>(iterable: Obj) -> Result<Vec<T, N>, Error>
where
T: TryFrom<Obj, Error = E>,
Error: From<E>,
{
let mut vec = Vec::<T, N>::new();
for item in IterBuf::new().try_iterate(iterable)? {
vec.push(item.try_into()?)
.map_err(|_| value_error!("Invalid iterable length"))?;
}
Ok(vec)
}

View File

@ -3,10 +3,9 @@ use crate::{
micropython::{
buffer::{hexlify_bytes, StrBuffer},
gc::Gc,
iter::IterBuf,
list::List,
obj::Obj,
util::try_or_raise,
util::{iter_into_array, try_or_raise},
},
storage::{get_avatar_len, load_avatar},
strutil::SkipPrefix,
@ -18,31 +17,6 @@ use crate::{
util::set_animation_disabled,
},
};
use heapless::Vec;
pub fn iter_into_array<T, E, const N: usize>(iterable: Obj) -> Result<[T; N], Error>
where
T: TryFrom<Obj, Error = E>,
Error: From<E>,
{
let vec: Vec<T, N> = iter_into_vec(iterable)?;
// Returns error if array.len() != N
vec.into_array()
.map_err(|_| value_error!("Invalid iterable length"))
}
pub fn iter_into_vec<T, E, const N: usize>(iterable: Obj) -> Result<Vec<T, N>, Error>
where
T: TryFrom<Obj, Error = E>,
Error: From<E>,
{
let mut vec = Vec::<T, N>::new();
for item in IterBuf::new().try_iterate(iterable)? {
vec.push(item.try_into()?)
.map_err(|_| value_error!("Invalid iterable length"))?;
}
Ok(vec)
}
/// Maximum number of characters that can be displayed on screen at once. Used
/// for on-the-fly conversion of binary data to hexadecimal representation.

View File

@ -38,7 +38,7 @@ use crate::{
layout::{
obj::{ComponentMsgObj, LayoutObj},
result::{CANCELLED, CONFIRMED, INFO},
util::{iter_into_array, iter_into_vec, upy_disable_animation, ConfirmBlob},
util::{upy_disable_animation, ConfirmBlob},
},
model_tr::component::check_homescreen_format,
},
@ -380,7 +380,7 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
let mut paragraphs = ParagraphVecLong::new();
for para in IterBuf::new().try_iterate(items)? {
let [key, value, is_data]: [Obj; 3] = iter_into_array(para)?;
let [key, value, is_data]: [Obj; 3] = util::iter_into_array(para)?;
let key = key.try_into_option::<StrBuffer>()?;
let value = value.try_into_option::<StrBuffer>()?;
let is_data: bool = is_data.try_into()?;
@ -506,7 +506,7 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
let mut ad = AddressDetails::new(address, case_sensitive, account, path)?;
for i in IterBuf::new().try_iterate(xpubs)? {
let [xtitle, text]: [StrBuffer; 2] = iter_into_array(i)?;
let [xtitle, text]: [StrBuffer; 2] = util::iter_into_array(i)?;
ad.add_xpub(xtitle, text)?;
}
@ -796,7 +796,7 @@ extern "C" fn new_altcoin_tx_summary(n_args: usize, args: *const Obj, kwargs: *m
let mut ops = OpTextLayout::new(theme::TEXT_MONO);
for item in unwrap!(IterBuf::new().try_iterate(items)) {
let [key, value]: [Obj; 2] = unwrap!(iter_into_array(item));
let [key, value]: [Obj; 2] = unwrap!(util::iter_into_array(item));
if !ops.is_empty() {
// Each key-value pair is on its own page
ops = ops.next_page();
@ -1247,7 +1247,7 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = iter_into_array(para)?;
let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text));
@ -1278,7 +1278,7 @@ extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map
let mut paragraphs = ParagraphVecLong::new();
for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = iter_into_array(para)?;
let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text));
@ -1527,7 +1527,7 @@ extern "C" fn new_show_group_share_success(
) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?;
let lines: [StrBuffer; 4] = iter_into_array(lines_iterable)?;
let lines: [StrBuffer; 4] = util::iter_into_array(lines_iterable)?;
let [l0, l1, l2, l3] = lines;

View File

@ -39,7 +39,7 @@ use crate::{
layout::{
obj::{ComponentMsgObj, LayoutObj},
result::{CANCELLED, CONFIRMED, INFO},
util::{iter_into_array, upy_disable_animation, ConfirmBlob, PropsList},
util::{upy_disable_animation, ConfirmBlob, PropsList},
},
model_tt::component::check_homescreen_format,
},
@ -430,7 +430,7 @@ extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *m
if item.is_str() {
ops = ops.text_normal(item.try_into()?)
} else {
let [emphasis, text]: [Obj; 2] = iter_into_array(item)?;
let [emphasis, text]: [Obj; 2] = util::iter_into_array(item)?;
let text: StrBuffer = text.try_into()?;
if emphasis.try_into()? {
ops = ops.text_demibold(text);
@ -721,7 +721,7 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
)?;
for i in IterBuf::new().try_iterate(xpubs)? {
let [xtitle, text]: [StrBuffer; 2] = iter_into_array(i)?;
let [xtitle, text]: [StrBuffer; 2] = util::iter_into_array(i)?;
ad.add_xpub(xtitle, text)?;
}
@ -741,7 +741,7 @@ extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs:
let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? {
let [key, value]: [Obj; 2] = iter_into_array(para)?;
let [key, value]: [Obj; 2] = util::iter_into_array(para)?;
let key: StrBuffer = key.try_into()?;
let value: StrBuffer = value.try_into()?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, key).no_break());
@ -806,7 +806,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
let mut paragraphs = ParagraphVecShort::new();
for pair in IterBuf::new().try_iterate(items)? {
let [label, value]: [StrBuffer; 2] = iter_into_array(pair)?;
let [label, value]: [StrBuffer; 2] = util::iter_into_array(pair)?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, label).no_break());
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value));
}
@ -1165,7 +1165,7 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = iter_into_array(para)?;
let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text));
@ -1195,7 +1195,7 @@ extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map
let mut paragraphs = ParagraphVecLong::new();
for para in IterBuf::new().try_iterate(items)? {
let [font, text]: [Obj; 2] = iter_into_array(para)?;
let [font, text]: [Obj; 2] = util::iter_into_array(para)?;
let style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text));
@ -1290,7 +1290,7 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map)
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let words_iterable: Obj = kwargs.get(Qstr::MP_QSTR_words)?;
let words: [StrBuffer; 3] = iter_into_array(words_iterable)?;
let words: [StrBuffer; 3] = util::iter_into_array(words_iterable)?;
let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_DEMIBOLD, description)]);
let obj = LayoutObj::new(Frame::left_aligned(
@ -1472,7 +1472,7 @@ extern "C" fn new_show_group_share_success(
) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?;
let lines: [StrBuffer; 4] = iter_into_array(lines_iterable)?;
let lines: [StrBuffer; 4] = util::iter_into_array(lines_iterable)?;
let obj = LayoutObj::new(IconDialog::new_shares(
lines,
@ -1493,7 +1493,7 @@ extern "C" fn new_show_remaining_shares(n_args: usize, args: *const Obj, kwargs:
let mut paragraphs = ParagraphVecLong::new();
for page in IterBuf::new().try_iterate(pages_iterable)? {
let [title, description]: [StrBuffer; 2] = iter_into_array(page)?;
let [title, description]: [StrBuffer; 2] = util::iter_into_array(page)?;
paragraphs
.add(Paragraph::new(&theme::TEXT_DEMIBOLD, title))
.add(Paragraph::new(&theme::TEXT_NORMAL, description).break_after());