1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-22 20:42:03 +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") .allowlist_var("mp_type_module")
// qstr // qstr
.allowlist_function("qstr_data") .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 // `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`. // 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 // 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(non_upper_case_globals)]
#![allow(dead_code)] #![allow(dead_code)]
#![allow(clippy::unnecessary_cast)] #![allow(clippy::unnecessary_cast)]
#![allow(unsafe_op_in_unsafe_fn)]
include!(concat!(env!("OUT_DIR"), "/micropython.rs")); include!(concat!(env!("OUT_DIR"), "/micropython.rs"));

View File

@ -1,13 +1,15 @@
use core::slice; use core::slice;
use crate::{ use heapless::Vec;
error::Error,
micropython::{ use super::{
ffi,
iter::IterBuf,
map::{Map, MapElem}, map::{Map, MapElem},
obj::Obj, obj::Obj,
runtime::raise_exception, runtime::{catch_exception, raise_exception},
},
}; };
use crate::error::Error;
/// Perform a call and convert errors into a raised MicroPython 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 /// 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) } 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::{ micropython::{
buffer::{hexlify_bytes, StrBuffer}, buffer::{hexlify_bytes, StrBuffer},
gc::Gc, gc::Gc,
iter::IterBuf,
list::List, list::List,
obj::Obj, obj::Obj,
util::try_or_raise, util::{iter_into_array, try_or_raise},
}, },
storage::{get_avatar_len, load_avatar}, storage::{get_avatar_len, load_avatar},
strutil::SkipPrefix, strutil::SkipPrefix,
@ -18,31 +17,6 @@ use crate::{
util::set_animation_disabled, 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 /// Maximum number of characters that can be displayed on screen at once. Used
/// for on-the-fly conversion of binary data to hexadecimal representation. /// for on-the-fly conversion of binary data to hexadecimal representation.

View File

@ -38,7 +38,7 @@ use crate::{
layout::{ layout::{
obj::{ComponentMsgObj, LayoutObj}, obj::{ComponentMsgObj, LayoutObj},
result::{CANCELLED, CONFIRMED, INFO}, 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, 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(); let mut paragraphs = ParagraphVecLong::new();
for para in IterBuf::new().try_iterate(items)? { 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 key = key.try_into_option::<StrBuffer>()?;
let value = value.try_into_option::<StrBuffer>()?; let value = value.try_into_option::<StrBuffer>()?;
let is_data: bool = is_data.try_into()?; 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)?; let mut ad = AddressDetails::new(address, case_sensitive, account, path)?;
for i in IterBuf::new().try_iterate(xpubs)? { 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)?; 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); let mut ops = OpTextLayout::new(theme::TEXT_MONO);
for item in unwrap!(IterBuf::new().try_iterate(items)) { 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() { if !ops.is_empty() {
// Each key-value pair is on its own page // Each key-value pair is on its own page
ops = ops.next_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(); let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? { 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 style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); 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(); let mut paragraphs = ParagraphVecLong::new();
for para in IterBuf::new().try_iterate(items)? { 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 style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
@ -1527,7 +1527,7 @@ extern "C" fn new_show_group_share_success(
) -> Obj { ) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?; 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; let [l0, l1, l2, l3] = lines;

View File

@ -39,7 +39,7 @@ use crate::{
layout::{ layout::{
obj::{ComponentMsgObj, LayoutObj}, obj::{ComponentMsgObj, LayoutObj},
result::{CANCELLED, CONFIRMED, INFO}, 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, 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() { if item.is_str() {
ops = ops.text_normal(item.try_into()?) ops = ops.text_normal(item.try_into()?)
} else { } 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()?; let text: StrBuffer = text.try_into()?;
if emphasis.try_into()? { if emphasis.try_into()? {
ops = ops.text_demibold(text); 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)? { 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)?; 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(); let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? { 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 key: StrBuffer = key.try_into()?;
let value: StrBuffer = value.try_into()?; let value: StrBuffer = value.try_into()?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, key).no_break()); 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(); let mut paragraphs = ParagraphVecShort::new();
for pair in IterBuf::new().try_iterate(items)? { 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_NORMAL, label).no_break());
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value)); 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(); let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? { 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 style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); 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(); let mut paragraphs = ParagraphVecLong::new();
for para in IterBuf::new().try_iterate(items)? { 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 style: &TextStyle = theme::textstyle_number(font.try_into()?);
let text: StrBuffer = text.try_into()?; let text: StrBuffer = text.try_into()?;
paragraphs.add(Paragraph::new(style, text)); 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 title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.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_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 paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_DEMIBOLD, description)]);
let obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
@ -1472,7 +1472,7 @@ extern "C" fn new_show_group_share_success(
) -> Obj { ) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let lines_iterable: Obj = kwargs.get(Qstr::MP_QSTR_lines)?; 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( let obj = LayoutObj::new(IconDialog::new_shares(
lines, lines,
@ -1493,7 +1493,7 @@ extern "C" fn new_show_remaining_shares(n_args: usize, args: *const Obj, kwargs:
let mut paragraphs = ParagraphVecLong::new(); let mut paragraphs = ParagraphVecLong::new();
for page in IterBuf::new().try_iterate(pages_iterable)? { 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 paragraphs
.add(Paragraph::new(&theme::TEXT_DEMIBOLD, title)) .add(Paragraph::new(&theme::TEXT_DEMIBOLD, title))
.add(Paragraph::new(&theme::TEXT_NORMAL, description).break_after()); .add(Paragraph::new(&theme::TEXT_NORMAL, description).break_after());