@@ -146,19 +146,24 @@ pub fn demangle(mut s: &str) -> Demangle {
146
146
}
147
147
148
148
#[ cfg( feature = "std" ) ]
149
- fn demangle_line ( line : & str , include_hash : bool ) -> std:: borrow:: Cow < str > {
150
- let mut line = std:: borrow:: Cow :: Borrowed ( line) ;
149
+ fn demangle_line (
150
+ line : & str ,
151
+ output : & mut impl std:: io:: Write ,
152
+ include_hash : bool ,
153
+ ) -> std:: io:: Result < ( ) > {
151
154
let mut head = 0 ;
152
- loop {
155
+ while head < line . len ( ) {
153
156
// Move to the next potential match
154
- head = match ( line[ head..] . find ( "_ZN" ) , line[ head..] . find ( "_R" ) ) {
157
+ let next_head = match ( line[ head..] . find ( "_ZN" ) , line[ head..] . find ( "_R" ) ) {
155
158
( Some ( idx) , None ) | ( None , Some ( idx) ) => head + idx,
156
159
( Some ( idx1) , Some ( idx2) ) => head + idx1. min ( idx2) ,
157
160
( None , None ) => {
158
- // No more matches, we can return our line .
159
- return line;
161
+ // No more matches.. .
162
+ line. len ( )
160
163
}
161
164
} ;
165
+ output. write_all ( line[ head..next_head] . as_bytes ( ) ) ?;
166
+ head = next_head;
162
167
// Find the non-matching character.
163
168
//
164
169
// If we do not find a character, then until the end of the line is the
@@ -169,29 +174,26 @@ fn demangle_line(line: &str, include_hash: bool) -> std::borrow::Cow<str> {
169
174
. unwrap_or ( line. len ( ) ) ;
170
175
171
176
let mangled = & line[ head..match_end] ;
177
+ head = head + mangled. len ( ) ;
172
178
if let Ok ( demangled) = try_demangle ( mangled) {
173
- let demangled = if include_hash {
174
- format ! ( "{}" , demangled)
179
+ if include_hash {
180
+ write ! ( output , "{}" , demangled) ? ;
175
181
} else {
176
- format ! ( "{:#}" , demangled)
177
- } ;
178
- line. to_mut ( ) . replace_range ( head..match_end, & demangled) ;
179
- // Start again after the replacement.
180
- head = head + demangled. len ( ) ;
182
+ write ! ( output, "{:#}" , demangled) ?;
183
+ }
181
184
} else {
182
- // Skip over the full symbol. We don't try to find a partial Rust symbol in the wider
183
- // matched text today.
184
- head = head + mangled. len ( ) ;
185
+ output. write_all ( mangled. as_bytes ( ) ) ?;
185
186
}
186
187
}
188
+ Ok ( ( ) )
187
189
}
188
190
189
191
/// Process a stream of data from `input` into the provided `output`, demangling any symbols found
190
192
/// within.
191
193
///
192
- /// This currently is implemented by buffering each line of input in memory, but that may be
193
- /// changed in the future. Symbols never cross line boundaries so this is just an implementation
194
- /// detail .
194
+ /// Note that the underlying implementation will perform many relatively small writes to the
195
+ /// output. If the output is expensive to write to (e.g., requires syscalls), consider using
196
+ /// `std::io::BufWriter` .
195
197
#[ cfg( feature = "std" ) ]
196
198
#[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
197
199
pub fn demangle_stream < R : std:: io:: BufRead , W : std:: io:: Write > (
@@ -206,8 +208,7 @@ pub fn demangle_stream<R: std::io::BufRead, W: std::io::Write>(
206
208
// trailing data during demangling. In the future we might directly stream to the output but at
207
209
// least right now that seems to be less efficient.
208
210
while input. read_line ( & mut buf) ? > 0 {
209
- let demangled_line = demangle_line ( & buf, include_hash) ;
210
- output. write_all ( demangled_line. as_bytes ( ) ) ?;
211
+ demangle_line ( & buf, output, include_hash) ?;
211
212
buf. clear ( ) ;
212
213
}
213
214
Ok ( ( ) )
@@ -560,11 +561,18 @@ mod tests {
560
561
) ;
561
562
}
562
563
564
+ #[ cfg( feature = "std" ) ]
565
+ fn demangle_str ( input : & str ) -> String {
566
+ let mut output = Vec :: new ( ) ;
567
+ super :: demangle_line ( input, & mut output, false ) ;
568
+ String :: from_utf8 ( output) . unwrap ( )
569
+ }
570
+
563
571
#[ test]
564
572
#[ cfg( feature = "std" ) ]
565
573
fn find_multiple ( ) {
566
574
assert_eq ! (
567
- super :: demangle_line ( "_ZN3fooE.llvm moocow _ZN3fooE.llvm" , false ) ,
575
+ demangle_str ( "_ZN3fooE.llvm moocow _ZN3fooE.llvm" ) ,
568
576
"foo.llvm moocow foo.llvm"
569
577
) ;
570
578
}
@@ -573,7 +581,7 @@ mod tests {
573
581
#[ cfg( feature = "std" ) ]
574
582
fn interleaved_new_legacy ( ) {
575
583
assert_eq ! (
576
- super :: demangle_line ( "_ZN3fooE.llvm moocow _RNvMNtNtNtNtCs8a2262Dv4r_3mio3sys4unix8selector5epollNtB2_8Selector6select _ZN3fooE.llvm" , false ) ,
584
+ demangle_str ( "_ZN3fooE.llvm moocow _RNvMNtNtNtNtCs8a2262Dv4r_3mio3sys4unix8selector5epollNtB2_8Selector6select _ZN3fooE.llvm" ) ,
577
585
"foo.llvm moocow <mio::sys::unix::selector::epoll::Selector>::select foo.llvm"
578
586
) ;
579
587
}
0 commit comments