@@ -4,8 +4,119 @@ Provides convenience routines for escaping raw bytes.
44This was copied from `regex-automata` with a few light edits.
55*/
66
7- // These were originally defined here, but they got moved to
8- // shared since they're needed there. We re-export them here
9- // because this is really where they should live, but they're
10- // in shared because `jiff-tzdb-static` needs it.
11- pub ( crate ) use crate :: shared:: util:: escape:: { Byte , Bytes , RepeatByte } ;
7+ use super :: utf8;
8+
9+ /// Provides a convenient `Debug` implementation for a `u8`.
10+ ///
11+ /// The `Debug` impl treats the byte as an ASCII, and emits a human
12+ /// readable representation of it. If the byte isn't ASCII, then it's
13+ /// emitted as a hex escape sequence.
14+ #[ derive( Clone , Copy ) ]
15+ pub ( crate ) struct Byte ( pub u8 ) ;
16+
17+ impl core:: fmt:: Display for Byte {
18+ #[ inline( never) ]
19+ fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
20+ if self . 0 == b' ' {
21+ return write ! ( f, " " ) ;
22+ }
23+ // 10 bytes is enough for any output from ascii::escape_default.
24+ let mut bytes = [ 0u8 ; 10 ] ;
25+ let mut len = 0 ;
26+ for ( i, mut b) in core:: ascii:: escape_default ( self . 0 ) . enumerate ( ) {
27+ // capitalize \xab to \xAB
28+ if i >= 2 && b'a' <= b && b <= b'f' {
29+ b -= 32 ;
30+ }
31+ bytes[ len] = b;
32+ len += 1 ;
33+ }
34+ write ! ( f, "{}" , core:: str :: from_utf8( & bytes[ ..len] ) . unwrap( ) )
35+ }
36+ }
37+
38+ impl core:: fmt:: Debug for Byte {
39+ #[ inline( never) ]
40+ fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
41+ write ! ( f, "\" " ) ?;
42+ core:: fmt:: Display :: fmt ( self , f) ?;
43+ write ! ( f, "\" " ) ?;
44+ Ok ( ( ) )
45+ }
46+ }
47+
48+ /// Provides a convenient `Debug` implementation for `&[u8]`.
49+ ///
50+ /// This generally works best when the bytes are presumed to be mostly
51+ /// UTF-8, but will work for anything. For any bytes that aren't UTF-8,
52+ /// they are emitted as hex escape sequences.
53+ #[ derive( Clone , Copy ) ]
54+ pub ( crate ) struct Bytes < ' a > ( pub & ' a [ u8 ] ) ;
55+
56+ impl < ' a > core:: fmt:: Display for Bytes < ' a > {
57+ #[ inline( never) ]
58+ fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
59+ // This is a sad re-implementation of a similar impl found in bstr.
60+ let mut bytes = self . 0 ;
61+ while let Some ( result) = utf8:: decode ( bytes) {
62+ let ch = match result {
63+ Ok ( ch) => ch,
64+ Err ( err) => {
65+ // The decode API guarantees `errant_bytes` is non-empty.
66+ write ! ( f, r"\x{:02x}" , err. as_slice( ) [ 0 ] ) ?;
67+ bytes = & bytes[ 1 ..] ;
68+ continue ;
69+ }
70+ } ;
71+ bytes = & bytes[ ch. len_utf8 ( ) ..] ;
72+ match ch {
73+ '\0' => write ! ( f, "\\ 0" ) ?,
74+ '\x01' ..='\x7f' => {
75+ write ! ( f, "{}" , ( ch as u8 ) . escape_ascii( ) ) ?;
76+ }
77+ _ => write ! ( f, "{}" , ch. escape_debug( ) ) ?,
78+ }
79+ }
80+ Ok ( ( ) )
81+ }
82+ }
83+
84+ impl < ' a > core:: fmt:: Debug for Bytes < ' a > {
85+ #[ inline( never) ]
86+ fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
87+ write ! ( f, "\" " ) ?;
88+ core:: fmt:: Display :: fmt ( self , f) ?;
89+ write ! ( f, "\" " ) ?;
90+ Ok ( ( ) )
91+ }
92+ }
93+
94+ /// A helper for repeating a single byte utilizing `Byte`.
95+ ///
96+ /// This is limited to repeating a byte up to `u8::MAX` times in order
97+ /// to reduce its size overhead. And in practice, Jiff just doesn't
98+ /// need more than this (at time of writing, 2025-11-29).
99+ pub ( crate ) struct RepeatByte {
100+ pub ( crate ) byte : u8 ,
101+ pub ( crate ) count : u8 ,
102+ }
103+
104+ impl core:: fmt:: Display for RepeatByte {
105+ #[ inline( never) ]
106+ fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
107+ for _ in 0 ..self . count {
108+ write ! ( f, "{}" , Byte ( self . byte) ) ?;
109+ }
110+ Ok ( ( ) )
111+ }
112+ }
113+
114+ impl core:: fmt:: Debug for RepeatByte {
115+ #[ inline( never) ]
116+ fn fmt ( & self , f : & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
117+ write ! ( f, "\" " ) ?;
118+ core:: fmt:: Display :: fmt ( self , f) ?;
119+ write ! ( f, "\" " ) ?;
120+ Ok ( ( ) )
121+ }
122+ }
0 commit comments