mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-07 07:12:34 +00:00
rust: add new trace methods
This commit is contained in:
parent
9f6e4b8c79
commit
b06cfb32d0
@ -1,3 +1,5 @@
|
||||
use heapless::String;
|
||||
|
||||
/// Visitor passed into `Trace` types.
|
||||
pub trait Tracer {
|
||||
fn int(&mut self, i: i64);
|
||||
@ -6,12 +8,25 @@ pub trait Tracer {
|
||||
fn symbol(&mut self, name: &str);
|
||||
fn open(&mut self, name: &str);
|
||||
fn field(&mut self, name: &str, value: &dyn Trace);
|
||||
fn title(&mut self, title: &str);
|
||||
fn button(&mut self, button: &str);
|
||||
fn content_flag(&mut self);
|
||||
fn kw_pair(&mut self, key: &str, value: &dyn Trace);
|
||||
fn close(&mut self);
|
||||
}
|
||||
|
||||
// Identifiers for tagging various parts of the Trace
|
||||
// message - so that things like title or the main screen
|
||||
// content can be read in debug mode by micropython.
|
||||
pub const TITLE_TAG: &str = " **TITLE** ";
|
||||
pub const BTN_TAG: &str = " **BTN** ";
|
||||
pub const CONTENT_TAG: &str = " **CONTENT** ";
|
||||
// For when the button is not used
|
||||
pub const EMPTY_BTN: &str = "---";
|
||||
|
||||
/// Value that can describe own structure and data using the `Tracer` interface.
|
||||
pub trait Trace {
|
||||
fn trace(&self, d: &mut dyn Tracer);
|
||||
fn trace(&self, t: &mut dyn Tracer);
|
||||
}
|
||||
|
||||
impl Trace for &[u8] {
|
||||
@ -26,6 +41,12 @@ impl<const N: usize> Trace for &[u8; N] {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Trace for String<N> {
|
||||
fn trace(&self, t: &mut dyn Tracer) {
|
||||
t.string(&self[..])
|
||||
}
|
||||
}
|
||||
|
||||
impl Trace for &str {
|
||||
fn trace(&self, t: &mut dyn Tracer) {
|
||||
t.string(self);
|
||||
@ -68,24 +89,54 @@ mod tests {
|
||||
}
|
||||
|
||||
fn symbol(&mut self, name: &str) {
|
||||
self.extend(name.as_bytes())
|
||||
self.string("<");
|
||||
self.string(name);
|
||||
self.string(">");
|
||||
}
|
||||
|
||||
fn open(&mut self, name: &str) {
|
||||
self.extend(b"<");
|
||||
self.extend(name.as_bytes());
|
||||
self.extend(b" ");
|
||||
self.string("<");
|
||||
self.string(name);
|
||||
self.string(" ");
|
||||
}
|
||||
|
||||
fn field(&mut self, name: &str, value: &dyn Trace) {
|
||||
self.extend(name.as_bytes());
|
||||
self.extend(b":");
|
||||
self.string(name);
|
||||
self.string(":");
|
||||
value.trace(self);
|
||||
self.extend(b" ");
|
||||
self.string(" ");
|
||||
}
|
||||
|
||||
/// Mark the string as a title/header.
|
||||
fn title(&mut self, title: &str) {
|
||||
self.string(TITLE_TAG);
|
||||
self.string(title);
|
||||
self.string(TITLE_TAG);
|
||||
}
|
||||
|
||||
/// Mark the string as a button content.
|
||||
fn button(&mut self, button: &str) {
|
||||
self.string(BTN_TAG);
|
||||
self.string(button);
|
||||
self.string(BTN_TAG);
|
||||
}
|
||||
|
||||
// Mark the following as content visible on the screen,
|
||||
// until it is called next time.
|
||||
fn content_flag(&mut self) {
|
||||
self.string(CONTENT_TAG);
|
||||
}
|
||||
|
||||
/// Key-value pair for easy parsing
|
||||
fn kw_pair(&mut self, key: &str, value: &dyn Trace) {
|
||||
self.string(key);
|
||||
self.string("::");
|
||||
value.trace(self);
|
||||
self.string(","); // mostly for human readability
|
||||
}
|
||||
|
||||
fn close(&mut self) {
|
||||
self.extend(b">")
|
||||
self.string(">")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,7 @@ pub mod trace {
|
||||
impl<T: ParagraphSource> crate::trace::Trace for Paragraphs<T> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("Paragraphs");
|
||||
t.content_flag();
|
||||
Self::foreach_visible(
|
||||
&self.source,
|
||||
&self.visible,
|
||||
@ -248,6 +249,7 @@ pub mod trace {
|
||||
t.string("\n");
|
||||
},
|
||||
);
|
||||
t.content_flag();
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
@ -231,30 +231,51 @@ impl LayoutObj {
|
||||
}
|
||||
|
||||
fn symbol(&mut self, name: &str) {
|
||||
self.0
|
||||
.call_with_n_args(&[
|
||||
"<".try_into().unwrap(),
|
||||
name.try_into().unwrap(),
|
||||
">".try_into().unwrap(),
|
||||
])
|
||||
.unwrap();
|
||||
self.string("<");
|
||||
self.string(name);
|
||||
self.string(">");
|
||||
}
|
||||
|
||||
fn open(&mut self, name: &str) {
|
||||
self.0
|
||||
.call_with_n_args(&["<".try_into().unwrap(), name.try_into().unwrap()])
|
||||
.unwrap();
|
||||
self.string("<");
|
||||
self.string(name);
|
||||
self.string(" ");
|
||||
}
|
||||
|
||||
fn field(&mut self, name: &str, value: &dyn Trace) {
|
||||
self.0
|
||||
.call_with_n_args(&[name.try_into().unwrap(), ": ".try_into().unwrap()])
|
||||
.unwrap();
|
||||
self.string(name);
|
||||
self.string(":");
|
||||
value.trace(self);
|
||||
self.string(" ");
|
||||
}
|
||||
|
||||
/// Mark the string as a title/header.
|
||||
fn title(&mut self, title: &str) {
|
||||
self.string(crate::trace::TITLE_TAG);
|
||||
self.string(title);
|
||||
self.string(crate::trace::TITLE_TAG);
|
||||
}
|
||||
|
||||
/// Mark the string as a button content.
|
||||
fn button(&mut self, button: &str) {
|
||||
self.string(crate::trace::BTN_TAG);
|
||||
self.string(button);
|
||||
self.string(crate::trace::BTN_TAG);
|
||||
}
|
||||
|
||||
fn content_flag(&mut self) {
|
||||
self.string(crate::trace::CONTENT_TAG);
|
||||
}
|
||||
|
||||
fn kw_pair(&mut self, key: &str, value: &dyn Trace) {
|
||||
self.string(key);
|
||||
self.string("::");
|
||||
value.trace(self);
|
||||
self.string(","); // mostly for human readability
|
||||
}
|
||||
|
||||
fn close(&mut self) {
|
||||
self.0.call_with_n_args(&[">".try_into().unwrap()]).unwrap();
|
||||
self.string(">")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,9 +190,9 @@ where
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("Frame");
|
||||
t.field("title", &self.title);
|
||||
t.title(self.title.inner().text().as_ref());
|
||||
if let Some(s) = &self.subtitle {
|
||||
t.field("subtitle", s);
|
||||
t.title(s.inner().text().as_ref());
|
||||
}
|
||||
if let Some(b) = &self.button {
|
||||
t.field("button", b);
|
||||
@ -283,7 +283,7 @@ where
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("NotificationFrame");
|
||||
t.field("title", &self.title);
|
||||
t.title(self.title.as_ref());
|
||||
t.field("content", &self.content);
|
||||
t.close();
|
||||
}
|
||||
|
@ -193,6 +193,7 @@ pub enum MnemonicInputMsg {
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<T, U> crate::trace::Trace for MnemonicKeyboard<T, U> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
// TODO: could differentiate between BIP39 and SLIP39
|
||||
t.open("MnemonicKeyboard");
|
||||
t.close();
|
||||
}
|
||||
|
@ -378,6 +378,7 @@ impl Component for Input {
|
||||
impl crate::trace::Trace for PassphraseKeyboard {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("PassphraseKeyboard");
|
||||
t.kw_pair("textbox", &self.input.inner().textbox.content());
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
@ -469,6 +469,17 @@ where
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("PinKeyboard");
|
||||
// So that debuglink knows the locations of the buttons
|
||||
let mut digits_order: String<10> = String::new();
|
||||
for btn in self.digit_btns.iter() {
|
||||
let btn_content = btn.inner().content();
|
||||
if let ButtonContent::Text(text) = btn_content {
|
||||
unwrap!(digits_order.push_str(text));
|
||||
}
|
||||
}
|
||||
t.kw_pair("digits_order", &digits_order);
|
||||
// TODO: textbox does not get updated when the pin is changed
|
||||
t.kw_pair("textbox", &self.textbox.inner().pin());
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
@ -312,8 +312,8 @@ where
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("SwipePage");
|
||||
t.field("active_page", &self.scrollbar.active_page);
|
||||
t.field("page_count", &self.scrollbar.page_count);
|
||||
t.kw_pair("active_page", &self.scrollbar.active_page);
|
||||
t.kw_pair("page_count", &self.scrollbar.page_count);
|
||||
t.field("content", &self.content);
|
||||
t.field("controls", &self.controls);
|
||||
t.close();
|
||||
@ -561,7 +561,7 @@ mod tests {
|
||||
page.place(SCREEN);
|
||||
|
||||
let expected =
|
||||
"<SwipePage active_page:0 page_count:1 content:<Paragraphs > controls:<Empty > >";
|
||||
"<SwipePage active_page::0,page_count::1,content:<Paragraphs **CONTENT** **CONTENT** > buttons:<Empty > >";
|
||||
|
||||
assert_eq!(trace(&page), expected);
|
||||
swipe_up(&mut page);
|
||||
@ -588,7 +588,7 @@ mod tests {
|
||||
);
|
||||
page.place(SCREEN);
|
||||
|
||||
let expected = "<SwipePage active_page:0 page_count:1 content:<Paragraphs This is the first\nparagraph and it should\nfit on the screen\nentirely.\nSecond, bold, paragraph\nshould also fit on the\nscreen whole I think.\n> controls:<Empty > >";
|
||||
let expected = "<SwipePage active_page:0,page_count:1,content:<Paragraphs **CONTENT** This is the first\nparagraph and it should\nfit on the screen\nentirely.\nSecond, bold, paragraph\nshould also fit on the\nscreen whole I think.\n **CONTENT** > controls:<Empty > >";
|
||||
|
||||
assert_eq!(trace(&page), expected);
|
||||
swipe_up(&mut page);
|
||||
@ -611,8 +611,8 @@ mod tests {
|
||||
);
|
||||
page.place(SCREEN);
|
||||
|
||||
let expected1 = "<SwipePage active_page:0 page_count:2 content:<Paragraphs This is somewhat long\nparagraph that goes on\nand on and on and on and\non and will definitely not\nfit on just a single\nscreen. You have to\nswipe a bit to see all the\ntext it contains I guess....\n> controls:<FixedHeightBar inner:<Button text:NO > > >";
|
||||
let expected2 = "<SwipePage active_page:1 page_count:2 content:<Paragraphs There's just so much\nletters in it.\n> controls:<FixedHeightBar inner:<Button text:NO > > >";
|
||||
let expected1 = "<SwipePage active_page:0 page_count:2 content:<Paragraphs **CONTENT** This is somewhat long\nparagraph that goes on\nand on and on and on and\non and will definitely not\nfit on just a single\nscreen. You have to\nswipe a bit to see all the\ntext it contains I guess....\n **CONTENT** > controls:<FixedHeightBar inner:<Button text:NO > > >";
|
||||
let expected2 = "<SwipePage active_page:1 page_count:2 content:<Paragraphs **CONTENT** There's just so much\nletters in it.\n **CONTENT** > controls:<FixedHeightBar inner:<Button text:NO > > >";
|
||||
|
||||
assert_eq!(trace(&page), expected1);
|
||||
swipe_down(&mut page);
|
||||
@ -647,9 +647,9 @@ mod tests {
|
||||
);
|
||||
page.place(SCREEN);
|
||||
|
||||
let expected1 = "<SwipePage active_page:0 page_count:3 content:<Paragraphs This paragraph is using a\nbold font. It doesn't need\nto be all that long.\nAnd this one is u\nsing MONO. Monosp\nace is nice for n\numbers, they...\n> controls:<FixedHeightBar inner:<Button text:IDK > > >";
|
||||
let expected2 = "<SwipePage active_page:1 page_count:3 content:<Paragraphs ...have the same\nwidth and can be\nscanned quickly.\nEven if they span\nseveral pages or\nsomething.\nLet's add another one...\n> controls:<FixedHeightBar inner:<Button text:IDK > > >";
|
||||
let expected3 = "<SwipePage active_page:2 page_count:3 content:<Paragraphs for a good measure. This\none should overflow all\nthe way to the third page\nwith a bit of luck.\n> controls:<FixedHeightBar inner:<Button text:IDK > > >";
|
||||
let expected1 = "<SwipePage active_page:0 page_count:3 content:<Paragraphs **CONTENT** This paragraph is using a\nbold font. It doesn't need\nto be all that long.\nAnd this one is u\nsing MONO. Monosp\nace is nice for n\numbers, they...\n **CONTENT** > controls:<FixedHeightBar inner:<Button text:IDK > > >";
|
||||
let expected2 = "<SwipePage active_page:1 page_count:3 content:<Paragraphs **CONTENT** ...have the same\nwidth and can be\nscanned quickly.\nEven if they span\nseveral pages or\nsomething.\nLet's add another one...\n **CONTENT** > controls:<FixedHeightBar inner:<Button text:IDK > > >";
|
||||
let expected3 = "<SwipePage active_page:2 page_count:3 content:<Paragraphs **CONTENT** for a good measure. This\none should overflow all\nthe way to the third page\nwith a bit of luck.\n **CONTENT** > controls:<FixedHeightBar inner:<Button text:IDK > > >";
|
||||
|
||||
assert_eq!(trace(&page), expected1);
|
||||
swipe_down(&mut page);
|
||||
@ -681,9 +681,9 @@ mod tests {
|
||||
);
|
||||
page.place(SCREEN);
|
||||
|
||||
let expected1 = "<SwipePage active_page:0 page_count:3 content:<Paragraphs Short one.\n> controls:<FixedHeightBar inner:<Empty > > >";
|
||||
let expected2 = "<SwipePage active_page:1 page_count:3 content:<Paragraphs Short two.\n> controls:<FixedHeightBar inner:<Empty > > >";
|
||||
let expected3 = "<SwipePage active_page:2 page_count:3 content:<Paragraphs Short three.\n> controls:<FixedHeightBar inner:<Empty > > >";
|
||||
let expected1 = "<SwipePage active_page:0,page_count:3,content:<Paragraphs **CONTENT** Short one.\n **CONTENT** > controls:<FixedHeightBar inner:<Empty > > >";
|
||||
let expected2 = "<SwipePage active_page:1,page_count:3,content:<Paragraphs **CONTENT** Short two.\n **CONTENT** > controls:<FixedHeightBar inner:<Empty > > >";
|
||||
let expected3 = "<SwipePage active_page:2,page_count:3,content:<Paragraphs **CONTENT** Short three.\n **CONTENT** > controls:<FixedHeightBar inner:<Empty > > >";
|
||||
|
||||
assert_eq!(trace(&page), expected1);
|
||||
swipe_up(&mut page);
|
||||
|
Loading…
Reference in New Issue
Block a user