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, _lua } = 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, _lua }
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,45 @@ 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+ // `buf` points to a readonly memory managed by Lua
239+ pub ( crate ) buf : & ' a str ,
240+ pub ( crate ) borrow : Cow < ' a , String > ,
241+ pub ( crate ) _lua : Lua ,
242+ }
242243
243244impl Deref for BorrowedStr < ' _ > {
244245 type Target = str ;
245246
246247 #[ inline( always) ]
247248 fn deref ( & self ) -> & str {
248- self . 0
249+ self . buf
249250 }
250251}
251252
252253impl Borrow < str > for BorrowedStr < ' _ > {
253254 #[ inline( always) ]
254255 fn borrow ( & self ) -> & str {
255- self . 0
256+ self . buf
256257 }
257258}
258259
259260impl AsRef < str > for BorrowedStr < ' _ > {
260261 #[ inline( always) ]
261262 fn as_ref ( & self ) -> & str {
262- self . 0
263+ self . buf
263264 }
264265}
265266
266267impl fmt:: Display for BorrowedStr < ' _ > {
267268 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
268- self . 0 . fmt ( f)
269+ self . buf . fmt ( f)
269270 }
270271}
271272
272273impl fmt:: Debug for BorrowedStr < ' _ > {
273274 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
274- self . 0 . fmt ( f)
275+ self . buf . fmt ( f)
275276 }
276277}
277278
@@ -280,7 +281,7 @@ where
280281 T : AsRef < str > ,
281282{
282283 fn eq ( & self , other : & T ) -> bool {
283- self . 0 == other. as_ref ( )
284+ self . buf == other. as_ref ( )
284285 }
285286}
286287
@@ -291,45 +292,65 @@ where
291292 T : AsRef < str > ,
292293{
293294 fn partial_cmp ( & self , other : & T ) -> Option < cmp:: Ordering > {
294- self . 0 . partial_cmp ( other. as_ref ( ) )
295+ self . buf . partial_cmp ( other. as_ref ( ) )
295296 }
296297}
297298
298299impl Ord for BorrowedStr < ' _ > {
299300 fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
300- self . 0 . cmp ( other. 0 )
301+ self . buf . cmp ( other. buf )
302+ }
303+ }
304+
305+ impl < ' a > TryFrom < & ' a String > for BorrowedStr < ' a > {
306+ type Error = Error ;
307+
308+ #[ inline]
309+ fn try_from ( value : & ' a String ) -> Result < Self > {
310+ let BorrowedBytes { buf, borrow, _lua } = BorrowedBytes :: from ( value) ;
311+ let buf = str:: from_utf8 ( buf) . map_err ( |e| Error :: FromLuaConversionError {
312+ from : "string" ,
313+ to : "&str" . to_string ( ) ,
314+ message : Some ( e. to_string ( ) ) ,
315+ } ) ?;
316+ Ok ( Self { buf, borrow, _lua } )
301317 }
302318}
303319
304320/// A borrowed byte slice (`&[u8]`) that holds a strong reference to the Lua state.
305- pub struct BorrowedBytes < ' a > ( & ' a [ u8 ] , #[ allow( unused) ] Lua ) ;
321+ pub struct BorrowedBytes < ' a > {
322+ // `buf` points to a readonly memory managed by Lua
323+ pub ( crate ) buf : & ' a [ u8 ] ,
324+ pub ( crate ) borrow : Cow < ' a , String > ,
325+ pub ( crate ) _lua : Lua ,
326+ }
306327
307328impl Deref for BorrowedBytes < ' _ > {
308329 type Target = [ u8 ] ;
309330
310331 #[ inline( always) ]
311332 fn deref ( & self ) -> & [ u8 ] {
312- self . 0
333+ self . buf
313334 }
314335}
315336
316337impl Borrow < [ u8 ] > for BorrowedBytes < ' _ > {
317338 #[ inline( always) ]
318339 fn borrow ( & self ) -> & [ u8 ] {
319- self . 0
340+ self . buf
320341 }
321342}
322343
323344impl AsRef < [ u8 ] > for BorrowedBytes < ' _ > {
324345 #[ inline( always) ]
325346 fn as_ref ( & self ) -> & [ u8 ] {
326- self . 0
347+ self . buf
327348 }
328349}
329350
330351impl fmt:: Debug for BorrowedBytes < ' _ > {
331352 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
332- self . 0 . fmt ( f)
353+ self . buf . fmt ( f)
333354 }
334355}
335356
@@ -338,7 +359,7 @@ where
338359 T : AsRef < [ u8 ] > ,
339360{
340361 fn eq ( & self , other : & T ) -> bool {
341- self . 0 == other. as_ref ( )
362+ self . buf == other. as_ref ( )
342363 }
343364}
344365
@@ -349,22 +370,31 @@ where
349370 T : AsRef < [ u8 ] > ,
350371{
351372 fn partial_cmp ( & self , other : & T ) -> Option < cmp:: Ordering > {
352- self . 0 . partial_cmp ( other. as_ref ( ) )
373+ self . buf . partial_cmp ( other. as_ref ( ) )
353374 }
354375}
355376
356377impl Ord for BorrowedBytes < ' _ > {
357378 fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
358- self . 0 . cmp ( other. 0 )
379+ self . buf . cmp ( other. buf )
359380 }
360381}
361382
362- impl < ' a > IntoIterator for BorrowedBytes < ' a > {
383+ impl < ' a > IntoIterator for & ' a BorrowedBytes < ' _ > {
363384 type Item = & ' a u8 ;
364385 type IntoIter = slice:: Iter < ' a , u8 > ;
365386
366387 fn into_iter ( self ) -> Self :: IntoIter {
367- self . 0 . iter ( )
388+ self . iter ( )
389+ }
390+ }
391+
392+ impl < ' a > From < & ' a String > for BorrowedBytes < ' a > {
393+ #[ inline]
394+ fn from ( value : & ' a String ) -> Self {
395+ let ( buf, _lua) = unsafe { value. to_slice ( ) } ;
396+ let borrow = Cow :: Borrowed ( value) ;
397+ Self { buf, borrow, _lua }
368398 }
369399}
370400
0 commit comments