@@ -8,11 +8,13 @@ mod unix_imports {
88}
99
1010pub use self :: consts:: * ;
11+ use crate :: error:: Error ;
12+ use crate :: util:: ensure_compatible_types;
1113use self :: unix_imports:: * ;
12- use std:: ffi:: { CStr , OsStr } ;
14+ use std:: borrow:: Cow ;
15+ use std:: ffi:: { CStr , CString , OsStr } ;
1316use std:: os:: raw;
1417use std:: { fmt, marker, mem, ptr} ;
15- use util:: { cstr_cow_from_bytes, ensure_compatible_types} ;
1618
1719mod consts;
1820
@@ -181,6 +183,25 @@ impl Library {
181183 where
182184 P : AsRef < OsStr > ,
183185 {
186+ /// Checks for the last byte and avoids allocating if it is zero.
187+ ///
188+ /// Non-last null bytes still result in an error.
189+ fn cstr_cow_from_bytes ( slice : & [ u8 ] ) -> Result < Cow < ' _ , CStr > , Error > {
190+ Ok ( match slice. last ( ) {
191+ // Slice out of 0 elements
192+ None => Cow :: Borrowed ( c"" ) ,
193+ // Slice with trailing 0
194+ Some ( & 0 ) => Cow :: Borrowed (
195+ CStr :: from_bytes_with_nul ( slice)
196+ . map_err ( |source| Error :: CreateCStringWithTrailing { source } ) ?,
197+ ) ,
198+ // Slice with no trailing 0
199+ Some ( _) => {
200+ Cow :: Owned ( CString :: new ( slice) . map_err ( |source| Error :: CreateCString { source } ) ?)
201+ }
202+ } )
203+ }
204+
184205 let filename = match filename {
185206 None => None ,
186207 Some ( ref f) => Some ( cstr_cow_from_bytes ( f. as_ref ( ) . as_bytes ( ) ) ?) ,
@@ -207,12 +228,12 @@ impl Library {
207228 . map_err ( |e| e. unwrap_or ( crate :: Error :: DlOpenUnknown ) )
208229 }
209230
210- unsafe fn get_impl < T , F > ( & self , symbol : & [ u8 ] , on_null : F ) -> Result < Symbol < T > , crate :: Error >
231+ unsafe fn get_impl < T , F > ( & self , symbol : & CStr , on_null : F ) -> Result < Symbol < T > , crate :: Error >
211232 where
212233 F : FnOnce ( ) -> Result < Symbol < T > , crate :: Error > ,
213234 {
214235 ensure_compatible_types :: < T , * mut raw:: c_void > ( ) ?;
215- let symbol = cstr_cow_from_bytes ( symbol ) ? ;
236+
216237 // `dlsym` may return nullptr in two cases: when a symbol genuinely points to a null
217238 // pointer or the symbol cannot be found. In order to detect this case a double dlerror
218239 // pattern must be used, which is, sadly, a little bit racy.
@@ -243,9 +264,6 @@ impl Library {
243264
244265 /// Get a pointer to a function or static variable by symbol name.
245266 ///
246- /// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
247- /// null terminated `symbol` may help to avoid an allocation.
248- ///
249267 /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
250268 /// most likely invalid.
251269 ///
@@ -265,8 +283,7 @@ impl Library {
265283 /// pointer without it being an error. If loading a null pointer is something you care about,
266284 /// consider using the [`Library::get_singlethreaded`] call.
267285 #[ inline( always) ]
268- pub unsafe fn get < T > ( & self , symbol : & [ u8 ] ) -> Result < Symbol < T > , crate :: Error > {
269- extern crate cfg_if;
286+ pub unsafe fn get < T > ( & self , symbol : & CStr ) -> Result < Symbol < T > , crate :: Error > {
270287 cfg_if:: cfg_if! {
271288 // These targets are known to have MT-safe `dlerror`.
272289 if #[ cfg( any(
@@ -289,9 +306,6 @@ impl Library {
289306
290307 /// Get a pointer to function or static variable by symbol name.
291308 ///
292- /// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
293- /// null terminated `symbol` may help to avoid an allocation.
294- ///
295309 /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
296310 /// most likely invalid.
297311 ///
@@ -308,7 +322,7 @@ impl Library {
308322 /// The implementation of thread-local variables is extremely platform specific and uses of such
309323 /// variables that work on e.g. Linux may have unintended behaviour on other targets.
310324 #[ inline( always) ]
311- pub unsafe fn get_singlethreaded < T > ( & self , symbol : & [ u8 ] ) -> Result < Symbol < T > , crate :: Error > {
325+ pub unsafe fn get_singlethreaded < T > ( & self , symbol : & CStr ) -> Result < Symbol < T > , crate :: Error > {
312326 self . get_impl ( symbol, || {
313327 Ok ( Symbol {
314328 pointer : ptr:: null_mut ( ) ,
0 commit comments