mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-18 05:28:40 +00:00
feat(core/rust): expose attrtuple to Rust
This commit is contained in:
parent
6af7b4a4b7
commit
02557ad6c0
@ -183,6 +183,7 @@ fn generate_micropython_bindings() {
|
|||||||
.allowlist_function("mp_obj_new_bytes")
|
.allowlist_function("mp_obj_new_bytes")
|
||||||
.allowlist_function("mp_obj_new_str")
|
.allowlist_function("mp_obj_new_str")
|
||||||
.allowlist_function("mp_obj_new_tuple")
|
.allowlist_function("mp_obj_new_tuple")
|
||||||
|
.allowlist_function("mp_obj_new_attrtuple")
|
||||||
.allowlist_function("mp_obj_get_int_maybe")
|
.allowlist_function("mp_obj_get_int_maybe")
|
||||||
.allowlist_function("mp_obj_is_true")
|
.allowlist_function("mp_obj_is_true")
|
||||||
.allowlist_function("mp_call_function_n_kw")
|
.allowlist_function("mp_call_function_n_kw")
|
||||||
|
@ -228,6 +228,39 @@ macro_rules! obj_module {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! attr_tuple {
|
||||||
|
(@append
|
||||||
|
fields: [$($fields:expr,)*],
|
||||||
|
values: [$($values:expr,)*],
|
||||||
|
rest: {
|
||||||
|
$field:expr => $val:expr,
|
||||||
|
$($rest:tt)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
attr_tuple! {
|
||||||
|
@append
|
||||||
|
fields: [$($fields,)* $field,],
|
||||||
|
values: [$($values,)* $val,],
|
||||||
|
rest: {$($rest)*}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(@append
|
||||||
|
fields: [$($fields:expr,)*],
|
||||||
|
values: [$($values:expr,)*],
|
||||||
|
rest: {}
|
||||||
|
) => {
|
||||||
|
$crate::micropython::util::new_attrtuple(&[$($fields,)*], &[$($values,)*])
|
||||||
|
};
|
||||||
|
// version without trailing comma
|
||||||
|
($($key:expr => $val:expr),*) => ({
|
||||||
|
attr_tuple!(@append fields: [], values: [], rest: { $($key => $val,)* })
|
||||||
|
});
|
||||||
|
// version with trailing comma
|
||||||
|
($($key:expr => $val:expr,)*) => ({
|
||||||
|
attr_tuple!(@append fields: [], values: [], rest: { $($key => $val,)* })
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Print arbitrary amounts of slices into a terminal.
|
/// Print arbitrary amounts of slices into a terminal.
|
||||||
/// Does not include a newline at the end.
|
/// Does not include a newline at the end.
|
||||||
/// Does not do anything when not in debugging mode.
|
/// Does not do anything when not in debugging mode.
|
||||||
|
@ -7,6 +7,7 @@ use super::{
|
|||||||
iter::IterBuf,
|
iter::IterBuf,
|
||||||
map::{Map, MapElem},
|
map::{Map, MapElem},
|
||||||
obj::Obj,
|
obj::Obj,
|
||||||
|
qstr::Qstr,
|
||||||
runtime::{catch_exception, raise_exception},
|
runtime::{catch_exception, raise_exception},
|
||||||
};
|
};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
@ -92,6 +93,38 @@ pub fn new_tuple(args: &[Obj]) -> Result<Obj, Error> {
|
|||||||
Ok(obj)
|
Ok(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new "attrtuple", which is essentially a namedtuple / ad-hoc object.
|
||||||
|
///
|
||||||
|
/// It is recommended to use the attr_tuple! macro instead of this function:
|
||||||
|
/// ```
|
||||||
|
/// let obj = attr_tuple! {
|
||||||
|
/// Qstr::MP_QSTR_language => header.language.try_into()?,
|
||||||
|
/// Qstr::MP_QSTR_version => util::new_tuple(&version_objs)?,
|
||||||
|
/// // ...
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn new_attrtuple(field_qstrs: &'static [Qstr], values: &[Obj]) -> Result<Obj, Error> {
|
||||||
|
if field_qstrs.len() != values.len() {
|
||||||
|
return Err(Error::TypeError);
|
||||||
|
}
|
||||||
|
// SAFETY:
|
||||||
|
// * `values` are copied into the tuple, but the `fields` array is stored as a
|
||||||
|
// pointer in the last tuple item. Hence the requirement that `fields` is
|
||||||
|
// 'static. See objattrtuple.c:79
|
||||||
|
// * we cast `field_qstrs` to the required type `qstr`, which is internally
|
||||||
|
// usize. (py/qstr.h:48). This is valid for as long as Qstr is
|
||||||
|
// repr(transparent) and the only field is a usize. Check generated qstr.rs.
|
||||||
|
// EXCEPTION: Raises if allocation fails, does not return NULL.
|
||||||
|
let obj = catch_exception(|| unsafe {
|
||||||
|
ffi::mp_obj_new_attrtuple(
|
||||||
|
field_qstrs.as_ptr() as *const _,
|
||||||
|
values.len(),
|
||||||
|
values.as_ptr(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter_into_array<T, E, const N: usize>(iterable: Obj) -> Result<[T; N], Error>
|
pub fn iter_into_array<T, E, const N: usize>(iterable: Obj) -> Result<[T; N], Error>
|
||||||
where
|
where
|
||||||
T: TryFrom<Obj, Error = E>,
|
T: TryFrom<Obj, Error = E>,
|
||||||
|
Loading…
Reference in New Issue
Block a user