Skip to content

Commit 4ce2e44

Browse files
Sven Lechnernagisa
authored andcommitted
feat: add name resolving library open function
The newly added method does resolve the library name passed to it by adhering to platform-specific naming schemes using Rust provided constants. Closes #62
1 parent 1b0f8c4 commit 4ce2e44

File tree

1 file changed

+139
-1
lines changed

1 file changed

+139
-1
lines changed

src/lib.rs

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@
4646
#![cfg_attr(docsrs, feature(doc_cfg))]
4747

4848

49+
use std::borrow::Cow;
50+
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
4951
use std::ffi::OsStr;
5052
use std::fmt;
51-
use std::ops;
53+
use std::ops::{self, Deref};
5254
use std::marker;
5355

5456
#[cfg(unix)]
@@ -128,6 +130,35 @@ impl Library {
128130
imp::Library::new(filename).map(From::from)
129131
}
130132

133+
fn resolve_name<'a>(name: &'a str) -> Cow<'a, str> {
134+
match (name.starts_with(DLL_PREFIX), name.ends_with(DLL_SUFFIX)) {
135+
(true, true) => Cow::Borrowed(name),
136+
(true, false) => Cow::Owned(format!("{}{}", name, DLL_SUFFIX)),
137+
(false, true) => Cow::Owned(format!("{}{}", DLL_PREFIX, name)),
138+
(false, false) => Cow::Owned(format!("{}{}{}", DLL_PREFIX, name, DLL_SUFFIX)),
139+
}
140+
}
141+
142+
/// Loads a library and does resolve it's name to match platform-specific
143+
/// naming schemes.
144+
///
145+
/// For a given library called `engine`, this method will resolve the name
146+
/// to the following:
147+
/// - `Linux`: `libengine.so`
148+
/// - `macOS`: `libengine.dylib`
149+
/// - `Windows`: `engine.dll`
150+
///
151+
/// # Note
152+
///
153+
/// This function does only work with library names and does not work when
154+
/// supplying a path to a library. The function assumes that the library is
155+
/// already present inside a path that is detectable and searchable by the
156+
/// OS during runtime.
157+
pub fn with_name_resolve<T: AsRef<str>>(libname: T) -> Result<Library, Error> {
158+
let resolved_name = Self::resolve_name(libname.as_ref());
159+
Self::new(resolved_name.deref())
160+
}
161+
131162
/// Get a pointer to function or static variable by symbol name.
132163
///
133164
/// The `symbol` may not contain any null bytes, with an exception of last byte. A null
@@ -337,3 +368,110 @@ impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
337368

338369
unsafe impl<'lib, T: Send> Send for Symbol<'lib, T> {}
339370
unsafe impl<'lib, T: Sync> Sync for Symbol<'lib, T> {}
371+
372+
#[cfg(test)]
373+
mod tests {
374+
use super::Library;
375+
376+
#[cfg(target_os = "windows")]
377+
#[test]
378+
fn test_resolve_name_none() {
379+
let name = "audioengine";
380+
let resolved = Library::resolve_name(name);
381+
assert_eq!(&resolved, "audioengine.dll");
382+
}
383+
384+
#[cfg(target_os = "linux")]
385+
#[test]
386+
fn test_resolve_name_none() {
387+
let name = "audioengine";
388+
let resolved = Library::resolve_name(name);
389+
assert_eq!(&resolved, "libaudioengine.so");
390+
}
391+
392+
#[cfg(target_os = "macos")]
393+
#[test]
394+
fn test_resolve_name_none() {
395+
let name = "audioengine";
396+
let resolved = Library::resolve_name(name);
397+
assert_eq!(&resolved, "libaudioengine.dylib");
398+
}
399+
400+
// prefix only
401+
402+
#[cfg(target_os = "windows")]
403+
#[test]
404+
fn test_resolve_name_prefix() {
405+
let name = "audioengine";
406+
let resolved = Library::resolve_name(name);
407+
assert_eq!(&resolved, "audioengine.dll");
408+
}
409+
410+
#[cfg(target_os = "linux")]
411+
#[test]
412+
fn test_resolve_name_prefix() {
413+
let name = "libaudioengine";
414+
let resolved = Library::resolve_name(name);
415+
assert_eq!(&resolved, "libaudioengine.so");
416+
}
417+
418+
#[cfg(target_os = "macos")]
419+
#[test]
420+
fn test_resolve_name_prefix() {
421+
let name = "libaudioengine";
422+
let resolved = Library::resolve_name(name);
423+
assert_eq!(&resolved, "libaudioengine.dylib");
424+
}
425+
426+
// suffix only
427+
428+
#[cfg(target_os = "windows")]
429+
#[test]
430+
fn test_resolve_name_suffix() {
431+
let name = "audioengine.dll";
432+
let resolved = Library::resolve_name(name);
433+
assert_eq!(&resolved, "audioengine.dll");
434+
}
435+
436+
#[cfg(target_os = "linux")]
437+
#[test]
438+
fn test_resolve_name_suffix() {
439+
let name = "audioengine.so";
440+
let resolved = Library::resolve_name(name);
441+
assert_eq!(&resolved, "libaudioengine.so");
442+
}
443+
444+
#[cfg(target_os = "macos")]
445+
#[test]
446+
fn test_resolve_name_suffix() {
447+
let name = "audioengine.dylib";
448+
let resolved = Library::resolve_name(name);
449+
assert_eq!(&resolved, "libaudioengine.dylib");
450+
}
451+
452+
// both
453+
454+
#[cfg(target_os = "windows")]
455+
#[test]
456+
fn test_resolve_name_prefix_and_suffix() {
457+
let name = "audioengine.dll";
458+
let resolved = Library::resolve_name(name);
459+
assert_eq!(&resolved, "audioengine.dll");
460+
}
461+
462+
#[cfg(target_os = "linux")]
463+
#[test]
464+
fn test_resolve_name_prefix_and_suffix() {
465+
let name = "libaudioengine.so";
466+
let resolved = Library::resolve_name(name);
467+
assert_eq!(&resolved, "libaudioengine.so");
468+
}
469+
470+
#[cfg(target_os = "macos")]
471+
#[test]
472+
fn test_resolve_name_prefix_and_suffix() {
473+
let name = "libaudioengine.dylib";
474+
let resolved = Library::resolve_name(name);
475+
assert_eq!(&resolved, "libaudioengine.dylib");
476+
}
477+
}

0 commit comments

Comments
 (0)