1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 23:48:12 +00:00

feat(core): introduce uformat!, use uDebug in favor of Debug

now that we have ufmt, this is just much nicer
This commit is contained in:
matejcik 2024-04-09 12:58:07 +02:00 committed by matejcik
parent b406fc22f3
commit 8134490e2e
12 changed files with 142 additions and 89 deletions

View File

@ -1,7 +1,21 @@
use ufmt;
mod unix_ffi {
const STDOUT_FILENO: cty::c_int = 1;
extern "C" {
pub fn write(fd: cty::c_int, buf: *const u8, count: cty::size_t) -> cty::ssize_t;
}
pub fn print(to_log: &str) {
unsafe {
write(STDOUT_FILENO, to_log.as_ptr(), to_log.len() as cty::size_t);
}
}
}
#[cfg(feature = "micropython")]
use crate::micropython;
use crate::micropython::print::print;
#[cfg(not(feature = "micropython"))]
pub use unix_ffi::print;
pub struct DebugConsole;
@ -9,25 +23,7 @@ impl ufmt::uWrite for DebugConsole {
type Error = core::convert::Infallible;
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
#[cfg(feature = "micropython")]
micropython::print::print(s);
// TODO: add alternative if micropython is not available
print(s);
Ok(())
}
}
#[macro_export]
macro_rules! dbg_println {
($($args:tt)*) => {
ufmt::uwriteln!($crate::debug::DebugConsole, $($args)*).ok();
};
}
#[macro_export]
macro_rules! dbg_print {
($($args:tt)*) => {
ufmt::uwrite!($crate::debug::DebugConsole, $($args)*).ok();
};
}

View File

@ -0,0 +1,57 @@
macro_rules! unwrap {
($e:expr, $msg:expr) => {{
use $crate::trezorhal::fatal_error::UnwrapOrFatalError;
$e.unwrap_or_fatal_error($msg, file!(), line!())
}};
($expr:expr) => {
unwrap!($expr, "unwrap failed")
};
}
macro_rules! ensure {
($what:expr, $error:expr) => {
if !($what) {
$crate::trezorhal::fatal_error::__fatal_error($error, file!(), line!());
}
};
}
macro_rules! fatal_error {
($msg:expr) => {{
$crate::trezorhal::fatal_error::__fatal_error($msg, file!(), line!());
}};
}
// from https://docs.rs/ufmt/latest/ufmt/
// like `std::format!` it returns a `heapless::String` but uses `uwrite!`
// instead of `write!`
macro_rules! uformat {
// IMPORTANT use `tt` fragments instead of `expr` fragments (i.e. `$($exprs:expr),*`)
(@$type:ty, $($tt:tt)*) => {{
let mut s = <$type>::new();
unwrap!(ufmt::uwrite!(&mut s, $($tt)*));
s
}};
(len:$len:expr, $($tt:tt)*) => {
uformat!(@heapless::String::<$len>, $($tt)*)
};
($($tt:tt)*) => {
uformat!(@crate::strutil::ShortString, $($tt)*)
};
}
#[allow(unused_macros)] // Should be used only for debugging purposes
macro_rules! dbg_print {
($($args:tt)*) => {
#[cfg(feature = "debug")]
ufmt::uwrite!($crate::debug::DebugConsole, $($args)*).ok();
}
}
#[allow(unused_macros)] // Should be used only for debugging purposes
macro_rules! dbg_println {
($($args:tt)*) => {
#[cfg(feature = "debug")]
ufmt::uwriteln!($crate::debug::DebugConsole, $($args)*).ok();
}
}

View File

@ -20,7 +20,7 @@ use super::ffi;
/// The `off` field represents offset from the `ptr` and allows us to do
/// substring slices while keeping the head pointer as required by GC.
#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Copy, Clone)]
pub struct StrBuffer {
ptr: *const u8,
len: u16,
@ -165,6 +165,19 @@ impl From<&'static str> for StrBuffer {
}
}
#[cfg(feature = "debug")]
impl ufmt::uDebug for StrBuffer {
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
where
W: ufmt::uWrite + ?Sized,
{
f.write_str("StrBuffer(")?;
f.write_str(self.as_ref())?;
f.write_str(")")?;
Ok(())
}
}
fn get_buffer_info(obj: Obj, flags: u32) -> Result<ffi::mp_buffer_info_t, Error> {
let mut bufinfo = ffi::mp_buffer_info_t {
buf: ptr::null_mut(),

View File

@ -250,41 +250,3 @@ pub(crate) use obj_fn_var;
pub(crate) use obj_map;
pub(crate) use obj_module;
pub(crate) use obj_type;
// from https://docs.rs/ufmt/latest/ufmt/
// like `std::format!` it returns a `std::String` but uses `uwrite!` instead of
// `write!`
macro_rules! uformat {
// IMPORTANT use `tt` fragments instead of `expr` fragments (i.e. `$($exprs:expr),*`)
($len:expr, $($tt:tt)*) => {{
let mut s = heapless::String::<$len>::new();
match ufmt::uwrite!(&mut s, $($tt)*) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}};
}
/// Print arbitrary amounts of slices into a terminal.
/// Does not include a newline at the end.
/// Does not do anything when not in debugging mode.
#[allow(unused_macros)] // Should be used only for debugging purposes
macro_rules! print {
($($string:expr),+) => {
#[cfg(feature = "debug")]
{
$(crate::micropython::print::print($string);)+
}
}
}
/// Print arbitrary amounts of slices into a terminal.
/// Includes a newline at the end.
/// Does not do anything when not in debugging mode.
#[allow(unused_macros)] // Should be used only for debugging purposes
macro_rules! println {
($($string:expr),+) => {
// Just delegating to print! and adding a newline
print!($($string),+, "\n");
}
}

View File

@ -195,3 +195,43 @@ impl<'a, 'b> PartialEq<TString<'a>> for TString<'b> {
}
impl Eq for TString<'_> {}
impl ufmt::uDisplay for TString<'_> {
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
where
W: ufmt::uWrite + ?Sized,
{
self.map(|s| f.write_str(s))
}
}
#[cfg(feature = "debug")]
impl ufmt::uDebug for TString<'_> {
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
where
W: ufmt::uWrite + ?Sized,
{
match self {
#[cfg(feature = "micropython")]
TString::Allocated(buf) => {
f.write_str("Allocated(")?;
buf.fmt(f)?;
f.write_str(")")?;
}
#[cfg(feature = "translations")]
TString::Translation { tr, offset } => {
f.write_str("Translation(")?;
tr.fmt(f)?;
f.write_str(", ")?;
offset.fmt(f)?;
f.write_str(")")?;
}
TString::Str(s) => {
f.write_str("Str(")?;
f.write_str(s)?;
f.write_str(")")?;
}
}
Ok(())
}
}

View File

@ -6,7 +6,8 @@
#[cfg(feature = "micropython")]
use crate::micropython::qstr::Qstr;
#[derive(Debug, Copy, Clone, FromPrimitive, PartialEq, Eq)]
#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum TranslatedString {

View File

@ -35,7 +35,8 @@ en_data = json.loads(en_file.read_text())["translations"]
#[cfg(feature = "micropython")]
use crate::micropython::qstr::Qstr;
#[derive(Debug, Copy, Clone, FromPrimitive, PartialEq, Eq)]
#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum TranslatedString {

View File

@ -10,9 +10,6 @@ use crate::ui::{
ui_features::{ModelUI, UIFeaturesCommon},
};
#[cfg(feature = "debug")]
use crate::dbg_println;
fn shutdown() -> ! {
unsafe { ffi::trezor_shutdown() }
}
@ -73,27 +70,3 @@ impl<T, E> UnwrapOrFatalError<T> for Result<T, E> {
}
}
}
macro_rules! unwrap {
($e:expr, $msg:expr) => {{
use crate::trezorhal::fatal_error::UnwrapOrFatalError;
$e.unwrap_or_fatal_error($msg, file!(), line!())
}};
($expr:expr) => {
unwrap!($expr, "unwrap failed")
};
}
macro_rules! ensure {
($what:expr, $error:expr) => {
if !($what) {
crate::trezorhal::fatal_error::__fatal_error($error, file!(), line!());
}
};
}
macro_rules! fatal_error {
($msg:expr) => {{
crate::trezorhal::fatal_error::__fatal_error($msg, file!(), line!());
}};
}

View File

@ -469,6 +469,7 @@ where
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum AttachType {
Initial,
#[cfg(feature = "touch")]
@ -476,6 +477,7 @@ pub enum AttachType {
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum Event {
#[cfg(feature = "button")]
Button(ButtonEvent),
@ -499,6 +501,7 @@ pub enum Event {
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub struct TimerToken(u32);
impl TimerToken {

View File

@ -6,6 +6,7 @@ use crate::ui::{
};
#[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum SwipeDirection {
Up,
Down,

View File

@ -5,12 +5,14 @@ use core::convert::TryInto;
use crate::ui::component::SwipeDirection;
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum PhysicalButton {
Left,
Right,
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum ButtonEvent {
/// Button pressed down.
/// ▼ * | * ▼
@ -39,6 +41,7 @@ impl ButtonEvent {
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum TouchEvent {
/// A person has started touching the screen at given absolute coordinates.
/// `TouchMove` will usually follow, and `TouchEnd` should finish the
@ -64,6 +67,7 @@ impl TouchEvent {
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum USBEvent {
/// USB host has connected/disconnected.
Connected(bool),
@ -71,6 +75,7 @@ pub enum USBEvent {
#[cfg(feature = "touch")]
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub enum SwipeEvent {
Move(SwipeDirection, i16),
End(SwipeDirection),

View File

@ -154,6 +154,7 @@ impl Lerp for Offset {
/// A point in 2D space defined by the the `x` and `y` coordinate. Relative
/// coordinates, vectors, and offsets are represented by the `Offset` type.
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
pub struct Point {
pub x: i16,
pub y: i16,