diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index e7fd1f9bc..af4d35d5e 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -81,6 +81,8 @@ fn generate_micropython_bindings() { .allowlist_var("mp_type_fun_builtin_1") .allowlist_var("mp_type_fun_builtin_2") .allowlist_var("mp_type_fun_builtin_3") + .allowlist_type("mp_obj_fun_builtin_var_t") + .allowlist_var("mp_type_fun_builtin_var") // gc .allowlist_function("gc_alloc") // iter diff --git a/core/embed/rust/src/micropython/func.rs b/core/embed/rust/src/micropython/func.rs index b1d573c29..6c6a267b9 100644 --- a/core/embed/rust/src/micropython/func.rs +++ b/core/embed/rust/src/micropython/func.rs @@ -16,3 +16,21 @@ impl Func { // SAFETY: We are in a single-threaded environment. unsafe impl Sync for Func {} + +pub type FuncVar = ffi::mp_obj_fun_builtin_var_t; + +impl FuncVar { + /// Convert variable argument "static const" function to a MicroPython + /// object. + pub const fn as_obj(&'static self) -> Obj { + // SAFETY: + // - We are an object struct with a base and a type. + // - 'static lifetime holds us in place. + // - MicroPython is smart enough not to mutate `mp_obj_fun_builtin_var_t` + // objects. + unsafe { Obj::from_ptr(self as *const _ as *mut _) } + } +} + +// SAFETY: We are in a single-threaded environment. +unsafe impl Sync for FuncVar {} diff --git a/core/embed/rust/src/micropython/macros.rs b/core/embed/rust/src/micropython/macros.rs index e60526f7a..c782ff3c2 100644 --- a/core/embed/rust/src/micropython/macros.rs +++ b/core/embed/rust/src/micropython/macros.rs @@ -46,6 +46,40 @@ macro_rules! obj_fn_3 { }}; } +macro_rules! obj_fn_var { + ($min:expr, $max:expr, $f:expr) => {{ + #[allow(unused_unsafe)] + unsafe { + use $crate::micropython::ffi; + + ffi::mp_obj_fun_builtin_var_t { + base: ffi::mp_obj_base_t { + type_: &ffi::mp_type_fun_builtin_var, + }, + sig: ($min << 17u32) | ($max << 1u32) | 0, // min, max, takes_kw + fun: ffi::_mp_obj_fun_builtin_var_t__bindgen_ty_1 { var: Some($f) }, + } + } + }}; +} + +macro_rules! obj_fn_kw { + ($min:expr, $f:expr) => {{ + #[allow(unused_unsafe)] + unsafe { + use $crate::micropython::ffi; + + ffi::mp_obj_fun_builtin_var_t { + base: ffi::mp_obj_base_t { + type_: &ffi::mp_type_fun_builtin_var, + }, + sig: ($min << 17u32) | (0xffff << 1u32) | 1, // min, max, takes_kw + fun: ffi::_mp_obj_fun_builtin_var_t__bindgen_ty_1 { kw: Some($f) }, + } + } + }}; +} + /// Construct fixed static const `Map` from `key` => `val` pairs. macro_rules! obj_map { ($($key:expr => $val:expr),*) => ({