@@ -5,9 +5,31 @@ use crossterm::{
55 QueueableCommand ,
66} ;
77use defmt_decoder:: { Frame , Table } ;
8+ use miette:: { bail, Context , Diagnostic , Result } ;
9+ use thiserror:: Error ;
810
911use crate :: cli:: monitor:: parser:: InputParser ;
1012
13+ #[ derive( Clone , Copy , Debug , Diagnostic , Error ) ]
14+ #[ error( "Could not set up defmt logger" ) ]
15+ pub enum DefmtError {
16+ #[ error( "No elf data available" ) ]
17+ #[ diagnostic( code( espflash:: monitor:: defmt:: no_elf) ) ]
18+ NoElf ,
19+
20+ #[ error( "No defmt data was found in the elf file" ) ]
21+ #[ diagnostic( code( espflash:: monitor:: defmt:: no_defmt) ) ]
22+ NoDefmtData ,
23+
24+ #[ error( "Failed to parse defmt data" ) ]
25+ #[ diagnostic( code( espflash:: monitor:: defmt:: parse_failed) ) ]
26+ TableParseFailed ,
27+
28+ #[ error( "Unsupported defmt encoding: {0:?}. Only rzcobs is supported." ) ]
29+ #[ diagnostic( code( espflash:: monitor:: defmt:: unsupported_encoding) ) ]
30+ UnsupportedEncoding ( defmt_decoder:: Encoding ) ,
31+ }
32+
1133#[ derive( Debug , PartialEq ) ]
1234enum FrameKind < ' a > {
1335 Defmt ( & ' a [ u8 ] ) ,
@@ -79,31 +101,38 @@ impl FrameDelimiter {
79101
80102pub struct EspDefmt {
81103 delimiter : FrameDelimiter ,
82- table : Option < Table > ,
104+ table : Table ,
83105}
84106
85107impl EspDefmt {
86- fn load_table ( elf : Option < & [ u8 ] > ) -> Option < Table > {
87- // Load symbols from the ELF file (if provided) and initialize the context.
88- Table :: parse ( elf?) . ok ( ) . flatten ( ) . and_then ( |table| {
89- let encoding = table. encoding ( ) ;
90-
91- // We only support rzcobs encoding because it is the only way to multiplex
92- // a defmt stream and an ASCII log stream over the same serial port.
93- if encoding == defmt_decoder:: Encoding :: Rzcobs {
94- Some ( table)
95- } else {
96- log:: warn!( "Unsupported defmt encoding: {:?}" , encoding) ;
97- None
98- }
99- } )
108+ /// Loads symbols from the ELF file (if provided) and initializes the context.
109+ fn load_table ( elf : Option < & [ u8 ] > ) -> Result < Table > {
110+ let Some ( elf) = elf else {
111+ bail ! ( DefmtError :: NoElf ) ;
112+ } ;
113+
114+ let table = match Table :: parse ( elf) {
115+ Ok ( Some ( table) ) => table,
116+ Ok ( None ) => bail ! ( DefmtError :: NoDefmtData ) ,
117+ Err ( e) => return Err ( DefmtError :: TableParseFailed ) . with_context ( || e) ,
118+ } ;
119+
120+ let encoding = table. encoding ( ) ;
121+
122+ // We only support rzcobs encoding because it is the only way to multiplex
123+ // a defmt stream and an ASCII log stream over the same serial port.
124+ if encoding == defmt_decoder:: Encoding :: Rzcobs {
125+ Ok ( table)
126+ } else {
127+ bail ! ( DefmtError :: UnsupportedEncoding ( encoding) )
128+ }
100129 }
101130
102- pub fn new ( elf : Option < & [ u8 ] > ) -> Self {
103- Self {
131+ pub fn new ( elf : Option < & [ u8 ] > ) -> Result < Self > {
132+ Self :: load_table ( elf ) . map ( |table| Self {
104133 delimiter : FrameDelimiter :: new ( ) ,
105- table : Self :: load_table ( elf ) ,
106- }
134+ table,
135+ } )
107136 }
108137
109138 fn handle_raw ( bytes : & [ u8 ] , out : & mut dyn Write ) {
@@ -143,12 +172,7 @@ impl EspDefmt {
143172
144173impl InputParser for EspDefmt {
145174 fn feed ( & mut self , bytes : & [ u8 ] , out : & mut dyn Write ) {
146- let Some ( table) = self . table . as_mut ( ) else {
147- Self :: handle_raw ( bytes, out) ;
148- return ;
149- } ;
150-
151- let mut decoder = table. new_stream_decoder ( ) ;
175+ let mut decoder = self . table . new_stream_decoder ( ) ;
152176
153177 self . delimiter . feed ( bytes, |frame| match frame {
154178 FrameKind :: Defmt ( frame) => {
0 commit comments