11use std:: {
2+ borrow:: Cow ,
23 fmt:: { self , Display } ,
34 iter:: Peekable ,
45} ;
@@ -31,7 +32,7 @@ impl<'a> Display for Alternative<'a> {
3132
3233 write_join_with ( f, "" , & self . body , |iter| {
3334 let next = iter. next ( ) ?;
34- let Some ( next) = as_character ( next) else { return Some ( next. to_string ( ) ) } ;
35+ let Some ( next) = as_character ( next) else { return Some ( Cow :: Owned ( next. to_string ( ) ) ) } ;
3536
3637 let peek = iter. peek ( ) . and_then ( |it| as_character ( it) ) ;
3738 let ( result, eat) = character_to_string ( next, peek) ;
@@ -106,10 +107,12 @@ impl<'a> Display for Quantifier<'a> {
106107 ( 1 , None ) => write ! ( f, "+" ) ?,
107108 ( 0 , Some ( 1 ) ) => write ! ( f, "?" ) ?,
108109 ( min, Some ( max) ) if min == max => write ! ( f, "{{{min}}}" , ) ?,
109- ( min, max) => {
110- let max = max. map_or_else ( String :: default, |it| it. to_string ( ) ) ;
110+ ( min, Some ( max) ) => {
111111 write ! ( f, "{{{min},{max}}}" , ) ?;
112112 }
113+ ( min, None ) => {
114+ write ! ( f, "{{{min},}}" , ) ?;
115+ }
113116 }
114117
115118 if !self . greedy {
@@ -194,7 +197,9 @@ impl<'a> Display for CharacterClass<'a> {
194197
195198 write_join_with ( f, sep, & self . body , |iter| {
196199 let next = iter. next ( ) ?;
197- let Some ( next) = as_character ( next) else { return Some ( next. to_string ( ) ) } ;
200+ let Some ( next) = as_character ( next) else {
201+ return Some ( Cow :: Owned ( next. to_string ( ) ) ) ;
202+ } ;
198203
199204 let peek = iter. peek ( ) . and_then ( |it| as_character ( it) ) ;
200205 let ( result, eat) = character_to_string ( next, peek) ;
@@ -304,76 +309,62 @@ impl<'a> Display for NamedReference<'a> {
304309fn character_to_string (
305310 this : & Character ,
306311 peek : Option < & Character > ,
307- ) -> ( /* result */ String , /* true of peek should be consumed */ bool ) {
312+ ) -> ( /* result */ Cow < ' static , str > , /* true of peek should be consumed */ bool ) {
308313 let cp = this. value ;
309314
310315 if matches ! ( this. kind, CharacterKind :: Symbol | CharacterKind :: UnicodeEscape ) {
311316 // Trail only
312317 if is_trail_surrogate ( cp) {
313- return ( format ! ( r"\u{cp:X}" ) , false ) ;
318+ return ( Cow :: Owned ( format ! ( r"\u{cp:X}" ) ) , false ) ;
314319 }
315320
316321 if is_lead_surrogate ( cp) {
317322 if let Some ( peek) = peek. filter ( |peek| is_trail_surrogate ( peek. value ) ) {
318323 // Lead+Trail
319324 let cp = combine_surrogate_pair ( cp, peek. value ) ;
320325 let ch = char:: from_u32 ( cp) . expect ( "Invalid surrogate pair `Character`!" ) ;
321- return ( format ! ( "{ch}" ) , true ) ;
326+ return ( Cow :: Owned ( format ! ( "{ch}" ) ) , true ) ;
322327 }
323328
324329 // Lead only
325- return ( format ! ( r"\u{cp:X}" ) , false ) ;
330+ return ( Cow :: Owned ( format ! ( r"\u{cp:X}" ) ) , false ) ;
326331 }
327332 }
328333
329334 let ch = char:: from_u32 ( cp) . expect ( "Invalid `Character`!" ) ;
330335 let result = match this. kind {
331336 // Not a surrogate, like BMP, or all units in unicode mode
332- CharacterKind :: Symbol => format ! ( "{ch}" ) ,
337+ CharacterKind :: Symbol => Cow :: Owned ( ch . to_string ( ) ) ,
333338 CharacterKind :: ControlLetter => match ch {
334- '\n' => r"\cJ" . to_string ( ) ,
335- '\r' => r"\cM" . to_string ( ) ,
336- '\t' => r"\cI" . to_string ( ) ,
337- _ => format ! ( r"\c{ch}" ) ,
339+ '\n' => Cow :: Borrowed ( r"\cJ" ) ,
340+ '\r' => Cow :: Borrowed ( r"\cM" ) ,
341+ '\t' => Cow :: Borrowed ( r"\cI" ) ,
342+ _ => Cow :: Owned ( format ! ( r"\c{ch}" ) ) ,
338343 } ,
339- CharacterKind :: Identifier => {
340- format ! ( r"\{ch}" )
341- }
344+ CharacterKind :: Identifier => Cow :: Owned ( format ! ( r"\{ch}" ) ) ,
342345 CharacterKind :: SingleEscape => match ch {
343- '\n' => String :: from ( r"\n" ) ,
344- '\r' => String :: from ( r"\r" ) ,
345- '\t' => String :: from ( r"\t" ) ,
346- '\u{b}' => String :: from ( r"\v" ) ,
347- '\u{c}' => String :: from ( r"\f" ) ,
348- '\u{8}' => String :: from ( r"\b" ) ,
349- '\u{2D}' => String :: from ( r"\-" ) ,
350- _ => format ! ( r"\{ch}" ) ,
346+ '\n' => Cow :: Borrowed ( r"\n" ) ,
347+ '\r' => Cow :: Borrowed ( r"\r" ) ,
348+ '\t' => Cow :: Borrowed ( r"\t" ) ,
349+ '\u{b}' => Cow :: Borrowed ( r"\v" ) ,
350+ '\u{c}' => Cow :: Borrowed ( r"\f" ) ,
351+ '\u{8}' => Cow :: Borrowed ( r"\b" ) ,
352+ '\u{2D}' => Cow :: Borrowed ( r"\-" ) ,
353+ _ => Cow :: Owned ( format ! ( r"\{ch}" ) ) ,
351354 } ,
352- CharacterKind :: Null => String :: from ( r"\0" ) ,
355+ CharacterKind :: Null => Cow :: Borrowed ( r"\0" ) ,
353356 CharacterKind :: UnicodeEscape => {
354357 let hex = & format ! ( "{cp:04X}" ) ;
355358 if hex. len ( ) <= 4 {
356- format ! ( r"\u{hex}" )
359+ Cow :: Owned ( format ! ( r"\u{hex}" ) )
357360 } else {
358- format ! ( r"\u{{{hex}}}" )
361+ Cow :: Owned ( format ! ( r"\u{{{hex}}}" ) )
359362 }
360363 }
361- CharacterKind :: HexadecimalEscape => {
362- let hex = & format ! ( "{cp:02X}" ) ;
363- format ! ( r"\x{hex}" )
364- }
365- CharacterKind :: Octal1 => {
366- let octal = format ! ( "{cp:o}" ) ;
367- format ! ( r"\{octal}" )
368- }
369- CharacterKind :: Octal2 => {
370- let octal = format ! ( "{cp:02o}" ) ;
371- format ! ( r"\{octal}" )
372- }
373- CharacterKind :: Octal3 => {
374- let octal = format ! ( "{cp:03o}" ) ;
375- format ! ( r"\{octal}" )
376- }
364+ CharacterKind :: HexadecimalEscape => Cow :: Owned ( format ! ( r"\x{cp:02X}" ) ) ,
365+ CharacterKind :: Octal1 => Cow :: Owned ( format ! ( r"\{cp:o}" ) ) ,
366+ CharacterKind :: Octal2 => Cow :: Owned ( format ! ( r"\{cp:02o}" ) ) ,
367+ CharacterKind :: Octal3 => Cow :: Owned ( format ! ( r"\{cp:03o}" ) ) ,
377368 } ;
378369
379370 ( result, false )
@@ -390,12 +381,18 @@ where
390381 write_join_with ( f, sep, items, |iter| iter. next ( ) . map ( |it| it. to_string ( ) ) )
391382}
392383
393- fn write_join_with < S , I , E , F > ( f : & mut fmt:: Formatter < ' _ > , sep : S , items : I , next : F ) -> fmt:: Result
384+ fn write_join_with < S , I , E , F , D > (
385+ f : & mut fmt:: Formatter < ' _ > ,
386+ sep : S ,
387+ items : I ,
388+ next : F ,
389+ ) -> fmt:: Result
394390where
395391 S : AsRef < str > ,
396392 E : Display ,
397393 I : IntoIterator < Item = E > ,
398- F : Fn ( & mut Peekable < I :: IntoIter > ) -> Option < String > ,
394+ F : Fn ( & mut Peekable < I :: IntoIter > ) -> Option < D > ,
395+ D : fmt:: Display ,
399396{
400397 let sep = sep. as_ref ( ) ;
401398 let iter = & mut items. into_iter ( ) . peekable ( ) ;
0 commit comments