@@ -21,7 +21,7 @@ use crossterm::{
21
21
terminal:: { disable_raw_mode, enable_raw_mode} ,
22
22
QueueableCommand ,
23
23
} ;
24
- use defmt_decoder:: { DecodeError , Frame , Table } ;
24
+ use defmt_decoder:: { Frame , StreamDecoder , Table } ;
25
25
use lazy_static:: lazy_static;
26
26
use log:: error;
27
27
use miette:: { IntoDiagnostic , Result } ;
@@ -78,127 +78,47 @@ enum FrameKind<'a> {
78
78
Raw ( & ' a [ u8 ] ) ,
79
79
}
80
80
81
- struct FrameDelimiter {
81
+ struct FrameDelimiter < ' a > {
82
82
buffer : Vec < u8 > ,
83
- table : Option < Table > ,
84
- started : bool ,
83
+ decoder : Option < Box < dyn StreamDecoder + ' a > > ,
84
+ in_frame : bool ,
85
85
}
86
86
87
- impl FrameDelimiter {
87
+ const FRAME_START : & [ u8 ] = & [ 0xFF , 0x00 ] ;
88
+ const FRAME_END : & [ u8 ] = & [ 0xFC , 0x00 ] ;
89
+
90
+ fn search ( haystack : & [ u8 ] , look_for_end : bool ) -> Option < ( & [ u8 ] , usize ) > {
91
+ let needle = if look_for_end { FRAME_END } else { FRAME_START } ;
92
+ haystack
93
+ . windows ( needle. len ( ) )
94
+ . position ( |window| window == FRAME_START || window == FRAME_END )
95
+ . map ( |pos| ( & haystack[ pos..] [ ..2 ] , pos) )
96
+ }
97
+
98
+ impl FrameDelimiter < ' _ > {
88
99
pub fn feed ( & mut self , buffer : & [ u8 ] , mut process : impl FnMut ( FrameKind < ' _ > ) ) {
89
- let Some ( table) = self . table . as_mut ( ) else {
100
+ let Some ( table) = self . decoder . as_mut ( ) else {
90
101
process ( FrameKind :: Raw ( buffer) ) ;
91
102
return ;
92
103
} ;
93
104
94
- let mut buffer = buffer;
95
- let mut retry = false ;
96
- while !buffer. is_empty ( ) || retry {
97
- retry = false ;
98
- // try to break buffer into 0-bounded frames
99
- let end_of_frame = buffer. iter ( ) . position ( |& x| x == 0 ) ;
100
- let Some ( pos) = end_of_frame else {
101
- // we either have a frame open already, or we are in serial output mode
102
- // either case, we consume everything so we can break out of the loop
103
-
104
- self . buffer . extend_from_slice ( buffer) ;
105
- return ;
106
- } ;
107
-
108
- let consumed = pos + 1 ; // also take the trailing 0 byte
109
- let ( frame_bytes, rest) = buffer. split_at ( consumed) ;
110
- buffer = rest;
111
-
112
- // Print bootloader output as is
113
- if !self . started {
114
- self . started = true ;
115
- self . buffer . extend_from_slice ( frame_bytes) ;
116
- process ( FrameKind :: Raw ( & self . buffer ) ) ;
117
- self . buffer . clear ( ) ;
118
- continue ;
119
- }
105
+ self . buffer . extend_from_slice ( buffer) ;
120
106
121
- let frame_bytes = if !self . buffer . is_empty ( ) {
122
- self . buffer . extend_from_slice ( frame_bytes) ;
123
- self . buffer . as_slice ( )
107
+ while let Some ( ( delimiter, pos) ) = search ( & self . buffer , self . in_frame ) {
108
+ let frame = & self . buffer [ ..pos] ;
109
+ if delimiter == FRAME_START {
110
+ process ( FrameKind :: Raw ( frame) ) ;
124
111
} else {
125
- frame_bytes
126
- } ;
127
-
128
- // we have a complete frame, try to decode it
129
- let mut decoder = table. new_stream_decoder ( ) ;
130
- decoder. received ( frame_bytes) ;
131
-
132
- match decoder. decode ( ) {
133
- Ok ( frame) => process ( FrameKind :: Defmt ( frame) ) ,
134
-
135
- Err ( DecodeError :: UnexpectedEof ) => unreachable ! ( ) ,
136
- Err ( DecodeError :: Malformed ) => try_parse_mixed ( & mut process, table, frame_bytes) ,
137
- }
138
-
139
- // We ended on a 0 byte, and we have processed everything one way or another.
140
- self . buffer . clear ( ) ;
141
- }
142
- }
143
- }
144
-
145
- fn try_parse_mixed ( process : & mut impl FnMut ( FrameKind < ' _ > ) , table : & Table , frame_bytes : & [ u8 ] ) {
146
- // We have a frame that mixes regular serial output and a defmt frame in the end.
147
- // We walk backwards and try to decode the frame that starts at our moving index.
148
- // If deconding is successful, we move backwards some more.
149
- // We stop when we don't find more starting points.
150
-
151
- // This is a weird and probably not very fast heuristic, that assumes ASCII
152
- // strings will rarely contain valid defmt frames and that a defmt frame will rarely be valid
153
- // ASCII.
154
-
155
- let mut frame_start = frame_bytes. len ( ) ;
156
- let mut candidate_frame_start = frame_start - 2 ;
157
-
158
- let is_valid_frame = |frame_bytes| {
159
- let mut decoder = table. new_stream_decoder ( ) ;
160
- decoder. received ( frame_bytes) ;
161
- match decoder. decode ( ) {
162
- Ok ( frame) => frame. display_message ( ) . to_string ( ) . len ( ) > frame_bytes. len ( ) ,
163
- Err ( _) => false ,
164
- }
165
- } ;
166
-
167
- let assume_text = |frame_bytes : & [ u8 ] | {
168
- frame_bytes
169
- . iter ( )
170
- . any ( |b| * b > 0x20 || [ b'\n' , b'\r' , b'\t' ] . contains ( b) )
171
- } ;
172
-
173
- let mut first_valid = true ;
174
-
175
- // We're checking as far back as there can be a valid Rzcobs run, which is
176
- // 134 data bytes and a 0xFF.
177
- while candidate_frame_start >= frame_start. saturating_sub ( 135 ) {
178
- if is_valid_frame ( & frame_bytes[ candidate_frame_start..] ) {
179
- // Assume a frame can't be valid ASCII.
180
- if first_valid || !assume_text ( & frame_bytes[ candidate_frame_start..frame_start] ) {
181
- frame_start = candidate_frame_start;
182
- first_valid = false ;
112
+ table. received ( frame) ;
113
+ if let Ok ( frame) = table. decode ( ) {
114
+ process ( FrameKind :: Defmt ( frame) ) ;
115
+ } else {
116
+ log:: warn!( "Failed to decode defmt frame" ) ;
117
+ log:: debug!( "Frame contents: {:02X?}" , frame) ;
118
+ }
183
119
}
120
+ self . buffer . drain ( ..pos + delimiter. len ( ) ) ;
184
121
}
185
-
186
- if candidate_frame_start == 0 {
187
- break ;
188
- }
189
-
190
- candidate_frame_start -= 1 ;
191
- }
192
-
193
- let ( raw, frame) = frame_bytes. split_at ( frame_start) ;
194
- if !raw. is_empty ( ) {
195
- process ( FrameKind :: Raw ( raw) ) ;
196
- }
197
-
198
- let mut decoder = table. new_stream_decoder ( ) ;
199
- decoder. received ( frame) ;
200
- if let Ok ( frame) = decoder. decode ( ) {
201
- process ( FrameKind :: Defmt ( frame) ) ;
202
122
}
203
123
}
204
124
@@ -258,8 +178,10 @@ pub fn monitor(
258
178
259
179
let mut delimiter = FrameDelimiter {
260
180
buffer : Vec :: new ( ) ,
261
- table : defmt_encoding. map ( |( table, _) | table) ,
262
- started : false ,
181
+ decoder : defmt_encoding
182
+ . as_ref ( )
183
+ . map ( |( table, _) | table. new_stream_decoder ( ) ) ,
184
+ in_frame : false ,
263
185
} ;
264
186
265
187
loop {
0 commit comments