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:
parent
3b88116bba
commit
8bf5a72843
@ -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
|
||||||
|
@ -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"));
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
Loading…
Reference in New Issue
Block a user