1111
1212//! Adapters for alternative string formats.
1313
14- use core:: str:: FromStr ;
14+ use core:: { convert :: TryInto as _ , str:: FromStr } ;
1515
1616use crate :: {
17- std:: { borrow:: Borrow , fmt, ptr , str} ,
17+ std:: { borrow:: Borrow , fmt, str} ,
1818 Error , Uuid , Variant ,
1919} ;
2020
@@ -67,25 +67,105 @@ impl fmt::UpperHex for Uuid {
6767
6868/// Format a [`Uuid`] as a hyphenated string, like
6969/// `67e55044-10b1-426f-9247-bb680e5fe0c8`.
70- #[ derive( Clone , Copy , Debug , Default , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
70+ #[ derive(
71+ Clone ,
72+ Copy ,
73+ Debug ,
74+ Default ,
75+ Eq ,
76+ Hash ,
77+ Ord ,
78+ PartialEq ,
79+ PartialOrd ,
80+ ) ]
81+ #[ cfg_attr(
82+ all( uuid_unstable, feature = "zerocopy" ) ,
83+ derive(
84+ zerocopy:: IntoBytes ,
85+ zerocopy:: FromBytes ,
86+ zerocopy:: KnownLayout ,
87+ zerocopy:: Immutable ,
88+ zerocopy:: Unaligned
89+ )
90+ ) ]
7191#[ repr( transparent) ]
7292pub struct Hyphenated ( Uuid ) ;
7393
7494/// Format a [`Uuid`] as a simple string, like
7595/// `67e5504410b1426f9247bb680e5fe0c8`.
76- #[ derive( Clone , Copy , Debug , Default , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
96+ #[ derive(
97+ Clone ,
98+ Copy ,
99+ Debug ,
100+ Default ,
101+ Eq ,
102+ Hash ,
103+ Ord ,
104+ PartialEq ,
105+ PartialOrd ,
106+ ) ]
107+ #[ cfg_attr(
108+ all( uuid_unstable, feature = "zerocopy" ) ,
109+ derive(
110+ zerocopy:: IntoBytes ,
111+ zerocopy:: FromBytes ,
112+ zerocopy:: KnownLayout ,
113+ zerocopy:: Immutable ,
114+ zerocopy:: Unaligned
115+ )
116+ ) ]
77117#[ repr( transparent) ]
78118pub struct Simple ( Uuid ) ;
79119
80120/// Format a [`Uuid`] as a URN string, like
81121/// `urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8`.
82- #[ derive( Clone , Copy , Debug , Default , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
122+ #[ derive(
123+ Clone ,
124+ Copy ,
125+ Debug ,
126+ Default ,
127+ Eq ,
128+ Hash ,
129+ Ord ,
130+ PartialEq ,
131+ PartialOrd ,
132+ ) ]
133+ #[ cfg_attr(
134+ all( uuid_unstable, feature = "zerocopy" ) ,
135+ derive(
136+ zerocopy:: IntoBytes ,
137+ zerocopy:: FromBytes ,
138+ zerocopy:: KnownLayout ,
139+ zerocopy:: Immutable ,
140+ zerocopy:: Unaligned
141+ )
142+ ) ]
83143#[ repr( transparent) ]
84144pub struct Urn ( Uuid ) ;
85145
86146/// Format a [`Uuid`] as a braced hyphenated string, like
87147/// `{67e55044-10b1-426f-9247-bb680e5fe0c8}`.
88- #[ derive( Clone , Copy , Debug , Default , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
148+ #[ derive(
149+ Clone ,
150+ Copy ,
151+ Debug ,
152+ Default ,
153+ Eq ,
154+ Hash ,
155+ Ord ,
156+ PartialEq ,
157+ PartialOrd ,
158+ ) ]
159+ #[ cfg_attr(
160+ all( uuid_unstable, feature = "zerocopy" ) ,
161+ derive(
162+ zerocopy:: IntoBytes ,
163+ zerocopy:: FromBytes ,
164+ zerocopy:: KnownLayout ,
165+ zerocopy:: Immutable ,
166+ zerocopy:: Unaligned
167+ )
168+ ) ]
89169#[ repr( transparent) ]
90170pub struct Braced ( Uuid ) ;
91171
@@ -99,8 +179,7 @@ impl Uuid {
99179 /// Get a borrowed [`Hyphenated`] formatter.
100180 #[ inline]
101181 pub fn as_hyphenated ( & self ) -> & Hyphenated {
102- // SAFETY: `Uuid` and `Hyphenated` have the same ABI
103- unsafe { & * ( self as * const Uuid as * const Hyphenated ) }
182+ unsafe_transmute_ref ! ( self )
104183 }
105184
106185 /// Get a [`Simple`] formatter.
@@ -112,8 +191,7 @@ impl Uuid {
112191 /// Get a borrowed [`Simple`] formatter.
113192 #[ inline]
114193 pub fn as_simple ( & self ) -> & Simple {
115- // SAFETY: `Uuid` and `Simple` have the same ABI
116- unsafe { & * ( self as * const Uuid as * const Simple ) }
194+ unsafe_transmute_ref ! ( self )
117195 }
118196
119197 /// Get a [`Urn`] formatter.
@@ -125,8 +203,7 @@ impl Uuid {
125203 /// Get a borrowed [`Urn`] formatter.
126204 #[ inline]
127205 pub fn as_urn ( & self ) -> & Urn {
128- // SAFETY: `Uuid` and `Urn` have the same ABI
129- unsafe { & * ( self as * const Uuid as * const Urn ) }
206+ unsafe_transmute_ref ! ( self )
130207 }
131208
132209 /// Get a [`Braced`] formatter.
@@ -138,8 +215,7 @@ impl Uuid {
138215 /// Get a borrowed [`Braced`] formatter.
139216 #[ inline]
140217 pub fn as_braced ( & self ) -> & Braced {
141- // SAFETY: `Uuid` and `Braced` have the same ABI
142- unsafe { & * ( self as * const Uuid as * const Braced ) }
218+ unsafe_transmute_ref ! ( self )
143219 }
144220}
145221
@@ -194,58 +270,62 @@ const fn format_hyphenated(src: &[u8; 16], upper: bool) -> [u8; 36] {
194270#[ inline]
195271fn encode_simple < ' b > ( src : & [ u8 ; 16 ] , buffer : & ' b mut [ u8 ] , upper : bool ) -> & ' b mut str {
196272 let buf = & mut buffer[ ..Simple :: LENGTH ] ;
197- let dst = buf. as_mut_ptr ( ) ;
273+ let buf: & mut [ u8 ; Simple :: LENGTH ] = buf. try_into ( ) . unwrap ( ) ;
274+ * buf = format_simple ( src, upper) ;
198275
199- // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
200276 // SAFETY: The encoded buffer is ASCII encoded
201- unsafe {
202- ptr:: write ( dst. cast ( ) , format_simple ( src, upper) ) ;
203- str:: from_utf8_unchecked_mut ( buf)
204- }
277+ unsafe { str:: from_utf8_unchecked_mut ( buf) }
205278}
206279
207280#[ inline]
208281fn encode_hyphenated < ' b > ( src : & [ u8 ; 16 ] , buffer : & ' b mut [ u8 ] , upper : bool ) -> & ' b mut str {
209282 let buf = & mut buffer[ ..Hyphenated :: LENGTH ] ;
210- let dst = buf. as_mut_ptr ( ) ;
283+ let buf: & mut [ u8 ; Hyphenated :: LENGTH ] = buf. try_into ( ) . unwrap ( ) ;
284+ * buf = format_hyphenated ( src, upper) ;
211285
212- // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
213286 // SAFETY: The encoded buffer is ASCII encoded
214- unsafe {
215- ptr:: write ( dst. cast ( ) , format_hyphenated ( src, upper) ) ;
216- str:: from_utf8_unchecked_mut ( buf)
217- }
287+ unsafe { str:: from_utf8_unchecked_mut ( buf) }
218288}
219289
220290#[ inline]
221291fn encode_braced < ' b > ( src : & [ u8 ; 16 ] , buffer : & ' b mut [ u8 ] , upper : bool ) -> & ' b mut str {
222- let buf = & mut buffer[ ..Braced :: LENGTH ] ;
223- buf[ 0 ] = b'{' ;
224- buf[ Braced :: LENGTH - 1 ] = b'}' ;
292+ let buf = & mut buffer[ ..Hyphenated :: LENGTH + 2 ] ;
293+ let buf: & mut [ u8 ; Hyphenated :: LENGTH + 2 ] = buf. try_into ( ) . unwrap ( ) ;
294+
295+ #[ cfg_attr(
296+ all( uuid_unstable, feature = "zerocopy" ) ,
297+ derive( zerocopy:: IntoBytes )
298+ ) ]
299+ #[ repr( C ) ]
300+ struct Braced {
301+ open_curly : u8 ,
302+ hyphenated : [ u8 ; Hyphenated :: LENGTH ] ,
303+ close_curly : u8 ,
304+ }
225305
226- // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
227- // SAFETY: The encoded buffer is ASCII encoded
228- unsafe {
229- let dst = buf. as_mut_ptr ( ) . add ( 1 ) ;
306+ let braced = Braced {
307+ open_curly : b'{' ,
308+ hyphenated : format_hyphenated ( src, upper) ,
309+ close_curly : b'}' ,
310+ } ;
230311
231- ptr:: write ( dst. cast ( ) , format_hyphenated ( src, upper) ) ;
232- str:: from_utf8_unchecked_mut ( buf)
233- }
312+ * buf = unsafe_transmute ! ( braced) ;
313+
314+ // SAFETY: The encoded buffer is ASCII encoded
315+ unsafe { str:: from_utf8_unchecked_mut ( buf) }
234316}
235317
236318#[ inline]
237319fn encode_urn < ' b > ( src : & [ u8 ; 16 ] , buffer : & ' b mut [ u8 ] , upper : bool ) -> & ' b mut str {
238320 let buf = & mut buffer[ ..Urn :: LENGTH ] ;
239321 buf[ ..9 ] . copy_from_slice ( b"urn:uuid:" ) ;
240322
241- // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
242- // SAFETY: The encoded buffer is ASCII encoded
243- unsafe {
244- let dst = buf. as_mut_ptr ( ) . add ( 9 ) ;
323+ let dst = & mut buf[ 9 ..( 9 + Hyphenated :: LENGTH ) ] ;
324+ let dst: & mut [ u8 ; Hyphenated :: LENGTH ] = dst. try_into ( ) . unwrap ( ) ;
325+ * dst = format_hyphenated ( src, upper) ;
245326
246- ptr:: write ( dst. cast ( ) , format_hyphenated ( src, upper) ) ;
247- str:: from_utf8_unchecked_mut ( buf)
248- }
327+ // SAFETY: The encoded buffer is ASCII encoded
328+ unsafe { str:: from_utf8_unchecked_mut ( buf) }
249329}
250330
251331impl Hyphenated {
0 commit comments