@@ -16,6 +16,11 @@ pub(crate) struct PortalId(IdInner);
1616#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
1717struct IdInner ( Option < NonZeroU32 > ) ;
1818
19+ pub ( crate ) struct DisplayId {
20+ prefix : & ' static str ,
21+ id : NonZeroU32 ,
22+ }
23+
1924impl StatementId {
2025 #[ allow( dead_code) ]
2126 pub const UNNAMED : Self = Self ( IdInner :: UNNAMED ) ;
@@ -34,17 +39,23 @@ impl StatementId {
3439 pub fn name_len ( & self ) -> Saturating < usize > {
3540 self . 0 . name_len ( Self :: NAME_PREFIX )
3641 }
42+
43+ /// Get a type to format this statement ID with [`Display`].
44+ ///
45+ /// Returns `None` if this is the unnamed statement.
46+ #[ inline( always) ]
47+ pub fn display ( & self ) -> Option < DisplayId > {
48+ self . 0 . display ( Self :: NAME_PREFIX )
49+ }
3750
38- // There's no common trait implemented by `Formatter` and `Vec<u8>` for this purpose;
39- // we're deliberately avoiding the formatting machinery because it's known to be slow.
40- pub fn write_name < E > ( & self , write : impl FnMut ( & str ) -> Result < ( ) , E > ) -> Result < ( ) , E > {
41- self . 0 . write_name ( Self :: NAME_PREFIX , write)
51+ pub fn put_name_with_nul ( & self , buf : & mut Vec < u8 > ) {
52+ self . 0 . put_name_with_nul ( Self :: NAME_PREFIX , buf)
4253 }
4354}
4455
45- impl Display for StatementId {
56+ impl Display for DisplayId {
4657 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
47- self . write_name ( |s| f . write_str ( s ) )
58+ write ! ( f , "{}{}" , self . prefix , self . id )
4859 }
4960}
5061
@@ -67,13 +78,13 @@ impl PortalId {
6778 Self ( self . 0 . next ( ) )
6879 }
6980
70- /// Calculate the number of bytes that will be written by [`Self::write_name ()`].
81+ /// Calculate the number of bytes that will be written by [`Self::put_name_with_nul ()`].
7182 pub fn name_len ( & self ) -> Saturating < usize > {
7283 self . 0 . name_len ( Self :: NAME_PREFIX )
7384 }
7485
75- pub fn write_name < E > ( & self , write : impl FnMut ( & str ) -> Result < ( ) , E > ) -> Result < ( ) , E > {
76- self . 0 . write_name ( Self :: NAME_PREFIX , write )
86+ pub fn put_name_with_nul ( & self , buf : & mut Vec < u8 > ) {
87+ self . 0 . put_name_with_nul ( Self :: NAME_PREFIX , buf )
7788 }
7889}
7990
@@ -92,7 +103,15 @@ impl IdInner {
92103 . map ( |id| id. checked_add ( 1 ) . unwrap_or ( NonZeroU32 :: MIN ) ) ,
93104 )
94105 }
95-
106+
107+ #[ inline( always) ]
108+ fn display ( & self , prefix : & ' static str ) -> Option < DisplayId > {
109+ self . 0 . map ( |id| DisplayId {
110+ prefix,
111+ id
112+ } )
113+ }
114+
96115 #[ inline( always) ]
97116 fn name_len ( & self , name_prefix : & str ) -> Saturating < usize > {
98117 let mut len = Saturating ( 0 ) ;
@@ -113,18 +132,32 @@ impl IdInner {
113132 }
114133
115134 #[ inline( always) ]
116- fn write_name < E > (
135+ fn put_name_with_nul (
117136 & self ,
118137 name_prefix : & str ,
119- mut write : impl FnMut ( & str ) -> Result < ( ) , E > ,
120- ) -> Result < ( ) , E > {
138+ buf : & mut Vec < u8 > ,
139+ ) {
121140 if let Some ( id) = self . 0 {
122- write ( name_prefix) ? ;
123- write ( itoa:: Buffer :: new ( ) . format ( id. get ( ) ) ) ? ;
141+ buf . extend_from_slice ( name_prefix. as_bytes ( ) ) ;
142+ buf . extend_from_slice ( itoa:: Buffer :: new ( ) . format ( id. get ( ) ) . as_bytes ( ) ) ;
124143 }
125144
126- write ( "\0 " ) ?;
127-
128- Ok ( ( ) )
145+ buf. push ( 0 ) ;
129146 }
130147}
148+
149+ #[ test]
150+ fn statement_id_display_matches_encoding ( ) {
151+ const EXPECTED_STR : & str = "sqlx_s_1234567890" ;
152+ const EXPECTED_BYTES : & [ u8 ] = b"sqlx_s_1234567890\0 " ;
153+
154+ let mut bytes = Vec :: new ( ) ;
155+
156+ StatementId :: TEST_VAL . put_name_with_nul ( & mut bytes) ;
157+
158+ assert_eq ! ( bytes, EXPECTED_BYTES ) ;
159+
160+ let str = StatementId :: TEST_VAL . display ( ) . unwrap ( ) . to_string ( ) ;
161+
162+ assert_eq ! ( str , EXPECTED_STR ) ;
163+ }
0 commit comments