1- use std:: borrow:: Borrow ;
1+ use std:: borrow:: { Borrow , Cow } ;
22use std:: hash:: { Hash , Hasher } ;
33use std:: ops:: Deref ;
44use std:: os:: raw:: { c_int, c_void} ;
@@ -44,13 +44,7 @@ impl String {
4444 /// ```
4545 #[ inline]
4646 pub fn to_str ( & self ) -> Result < BorrowedStr > {
47- let BorrowedBytes ( bytes, guard) = self . as_bytes ( ) ;
48- let s = str:: from_utf8 ( bytes) . map_err ( |e| Error :: FromLuaConversionError {
49- from : "string" ,
50- to : "&str" . to_string ( ) ,
51- message : Some ( e. to_string ( ) ) ,
52- } ) ?;
53- Ok ( BorrowedStr ( s, guard) )
47+ BorrowedStr :: try_from ( self )
5448 }
5549
5650 /// Converts this string to a [`StdString`].
@@ -109,19 +103,21 @@ impl String {
109103 /// ```
110104 #[ inline]
111105 pub fn as_bytes ( & self ) -> BorrowedBytes {
112- let ( bytes, guard) = unsafe { self . to_slice ( ) } ;
113- BorrowedBytes ( & bytes[ ..bytes. len ( ) - 1 ] , guard)
106+ BorrowedBytes :: from ( self )
114107 }
115108
116109 /// Get the bytes that make up this string, including the trailing nul byte.
117110 pub fn as_bytes_with_nul ( & self ) -> BorrowedBytes {
118- let ( bytes, guard) = unsafe { self . to_slice ( ) } ;
119- BorrowedBytes ( bytes, guard)
111+ let BorrowedBytes { buf, borrow, _guard } = BorrowedBytes :: from ( self ) ;
112+ // Include the trailing nul byte (it's always present but excluded by default)
113+ let buf = unsafe { slice:: from_raw_parts ( ( * buf) . as_ptr ( ) , ( * buf) . len ( ) + 1 ) } ;
114+ BorrowedBytes { buf, borrow, _guard }
120115 }
121116
117+ // Does not return the terminating nul byte
122118 unsafe fn to_slice ( & self ) -> ( & [ u8 ] , Lua ) {
123119 let lua = self . 0 . lua . upgrade ( ) ;
124- let slice = unsafe {
120+ let slice = {
125121 let rawlua = lua. lock ( ) ;
126122 let ref_thread = rawlua. ref_thread ( ) ;
127123
@@ -134,7 +130,7 @@ impl String {
134130 // string type
135131 let mut size = 0 ;
136132 let data = ffi:: lua_tolstring ( ref_thread, self . 0 . index , & mut size) ;
137- slice:: from_raw_parts ( data as * const u8 , size + 1 )
133+ slice:: from_raw_parts ( data as * const u8 , size)
138134 } ;
139135 ( slice, lua)
140136 }
@@ -238,40 +234,44 @@ impl fmt::Display for Display<'_> {
238234}
239235
240236/// A borrowed string (`&str`) that holds a strong reference to the Lua state.
241- pub struct BorrowedStr < ' a > ( & ' a str , #[ allow( unused) ] Lua ) ;
237+ pub struct BorrowedStr < ' a > {
238+ pub ( crate ) buf : * const str ,
239+ pub ( crate ) borrow : Cow < ' a , String > ,
240+ pub ( crate ) _guard : Lua ,
241+ }
242242
243243impl Deref for BorrowedStr < ' _ > {
244244 type Target = str ;
245245
246246 #[ inline( always) ]
247247 fn deref ( & self ) -> & str {
248- self . 0
248+ unsafe { & * self . buf }
249249 }
250250}
251251
252252impl Borrow < str > for BorrowedStr < ' _ > {
253253 #[ inline( always) ]
254254 fn borrow ( & self ) -> & str {
255- self . 0
255+ self . deref ( )
256256 }
257257}
258258
259259impl AsRef < str > for BorrowedStr < ' _ > {
260260 #[ inline( always) ]
261261 fn as_ref ( & self ) -> & str {
262- self . 0
262+ self . deref ( )
263263 }
264264}
265265
266266impl fmt:: Display for BorrowedStr < ' _ > {
267267 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
268- self . 0 . fmt ( f)
268+ self . as_ref ( ) . fmt ( f)
269269 }
270270}
271271
272272impl fmt:: Debug for BorrowedStr < ' _ > {
273273 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
274- self . 0 . fmt ( f)
274+ self . as_ref ( ) . fmt ( f)
275275 }
276276}
277277
@@ -280,7 +280,7 @@ where
280280 T : AsRef < str > ,
281281{
282282 fn eq ( & self , other : & T ) -> bool {
283- self . 0 == other. as_ref ( )
283+ self . as_ref ( ) == other. as_ref ( )
284284 }
285285}
286286
@@ -291,45 +291,64 @@ where
291291 T : AsRef < str > ,
292292{
293293 fn partial_cmp ( & self , other : & T ) -> Option < cmp:: Ordering > {
294- self . 0 . partial_cmp ( other. as_ref ( ) )
294+ self . as_ref ( ) . partial_cmp ( other. as_ref ( ) )
295295 }
296296}
297297
298298impl Ord for BorrowedStr < ' _ > {
299299 fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
300- self . 0 . cmp ( other. 0 )
300+ self . as_ref ( ) . cmp ( other. as_ref ( ) )
301+ }
302+ }
303+
304+ impl < ' a > TryFrom < & ' a String > for BorrowedStr < ' a > {
305+ type Error = Error ;
306+
307+ #[ inline]
308+ fn try_from ( value : & ' a String ) -> Result < Self > {
309+ let BorrowedBytes { buf, borrow, _guard } = BorrowedBytes :: from ( value) ;
310+ let buf = str:: from_utf8 ( unsafe { & * buf } ) . map_err ( |e| Error :: FromLuaConversionError {
311+ from : "string" ,
312+ to : "&str" . to_string ( ) ,
313+ message : Some ( e. to_string ( ) ) ,
314+ } ) ?;
315+ Ok ( Self { buf, borrow, _guard } )
301316 }
302317}
303318
304319/// A borrowed byte slice (`&[u8]`) that holds a strong reference to the Lua state.
305- pub struct BorrowedBytes < ' a > ( & ' a [ u8 ] , #[ allow( unused) ] Lua ) ;
320+ pub struct BorrowedBytes < ' a > {
321+ pub ( crate ) buf : * const [ u8 ] ,
322+ pub ( crate ) borrow : Cow < ' a , String > ,
323+ pub ( crate ) _guard : Lua ,
324+ }
306325
307326impl Deref for BorrowedBytes < ' _ > {
308327 type Target = [ u8 ] ;
309328
310329 #[ inline( always) ]
311330 fn deref ( & self ) -> & [ u8 ] {
312- self . 0
331+ unsafe { & * self . buf }
313332 }
314333}
315334
316335impl Borrow < [ u8 ] > for BorrowedBytes < ' _ > {
317336 #[ inline( always) ]
318337 fn borrow ( & self ) -> & [ u8 ] {
319- self . 0
338+ self . deref ( )
320339 }
321340}
322341
323342impl AsRef < [ u8 ] > for BorrowedBytes < ' _ > {
324343 #[ inline( always) ]
325344 fn as_ref ( & self ) -> & [ u8 ] {
326- self . 0
345+ self . deref ( )
327346 }
328347}
329348
330349impl fmt:: Debug for BorrowedBytes < ' _ > {
331350 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
332- self . 0 . fmt ( f)
351+ self . as_ref ( ) . fmt ( f)
333352 }
334353}
335354
@@ -338,7 +357,7 @@ where
338357 T : AsRef < [ u8 ] > ,
339358{
340359 fn eq ( & self , other : & T ) -> bool {
341- self . 0 == other. as_ref ( )
360+ self . as_ref ( ) == other. as_ref ( )
342361 }
343362}
344363
@@ -349,22 +368,31 @@ where
349368 T : AsRef < [ u8 ] > ,
350369{
351370 fn partial_cmp ( & self , other : & T ) -> Option < cmp:: Ordering > {
352- self . 0 . partial_cmp ( other. as_ref ( ) )
371+ self . as_ref ( ) . partial_cmp ( other. as_ref ( ) )
353372 }
354373}
355374
356375impl Ord for BorrowedBytes < ' _ > {
357376 fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
358- self . 0 . cmp ( other. 0 )
377+ self . as_ref ( ) . cmp ( other. as_ref ( ) )
359378 }
360379}
361380
362- impl < ' a > IntoIterator for BorrowedBytes < ' a > {
381+ impl < ' a > IntoIterator for & ' a BorrowedBytes < ' _ > {
363382 type Item = & ' a u8 ;
364383 type IntoIter = slice:: Iter < ' a , u8 > ;
365384
366385 fn into_iter ( self ) -> Self :: IntoIter {
367- self . 0 . iter ( )
386+ self . iter ( )
387+ }
388+ }
389+
390+ impl < ' a > From < & ' a String > for BorrowedBytes < ' a > {
391+ #[ inline]
392+ fn from ( value : & ' a String ) -> Self {
393+ let ( buf, _guard) = unsafe { value. to_slice ( ) } ;
394+ let borrow = Cow :: Borrowed ( value) ;
395+ Self { buf, borrow, _guard }
368396 }
369397}
370398
0 commit comments