Snap for 8564071 from 62970091e982dd9972e2f3dcdee638b48bd0a820 to mainline-adbd-release

Change-Id: Icc30f076b0cf64212ddbe2bb2e38671a9257a4bd
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 69cdb18..dfc0076 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "7fbd3a34336f7839bdd6d6aaf83a9a763c4fa1e5"
-  }
-}
+    "sha1": "00c21d873aeeac16935ac85962486b41776fe976"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.github/workflows/libloading.yml b/.github/workflows/libloading.yml
index 811681d..e7e84ac 100644
--- a/.github/workflows/libloading.yml
+++ b/.github/workflows/libloading.yml
@@ -26,37 +26,28 @@
             profile: minimal
             components: clippy
             default: true
-      - name: Update
-        uses: actions-rs/cargo@v1
-        with:
-          command: update
-          args: --manifest-path=Cargo.toml
       - name: Clippy
         uses: actions-rs/cargo@v1
         with:
           command: clippy
-      - name: Build
-        uses: actions-rs/cargo@v1
-        with:
-          command: build
-          args: --manifest-path=Cargo.toml
       - name: Test
         uses: actions-rs/cargo@v1
         with:
           command: test
-          args: --manifest-path=Cargo.toml -- --nocapture
+          args: -- --nocapture
       - name: Test Release
         uses: actions-rs/cargo@v1
         with:
           command: test
-          args: --manifest-path=Cargo.toml --release -- --nocapture
+          args: --release -- --nocapture
       - name: Documentation
         uses: actions-rs/cargo@v1
         with:
-          command: doc
-          args: --manifest-path=Cargo.toml
-        env:
-          RUSTDOCFLAGS: --cfg docsrs
+          command: rustdoc
+          args: |
+            -Zunstable-options
+            --config
+            'build.rustdogflags=["--cfg", "libloading_docs", "-D", "rustdoc::broken_intra_doc_links"]'
         if: ${{ matrix.rust_toolchain == 'nightly' }}
 
   windows-gnu-test:
@@ -110,6 +101,7 @@
           - x86_64-unknown-openbsd
           - x86_64-unknown-redox
           - x86_64-fuchsia
+          - wasm32-unknown-unknown
     timeout-minutes: 20
     steps:
       - uses: actions/checkout@v2
diff --git a/Android.bp b/Android.bp
index bbae702..bdf4513 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,5 @@
-// This file is generated by cargo2android.py --run --dependencies.
+// This file is generated by cargo2android.py --config cargo2android.json.
+// Do not modify this file as changes will be overridden on upgrade.
 
 package {
     default_applicable_licenses: ["external_rust_crates_libloading_license"],
@@ -17,15 +18,19 @@
     ],
 }
 
-rust_library_host {
+rust_library {
     name: "liblibloading",
+    host_supported: true,
     crate_name: "libloading",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.7.3",
     srcs: ["src/lib.rs"],
     edition: "2015",
     rustlibs: [
         "libcfg_if",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
 }
-
-// dependent_library ["feature_list"]
-//   cfg-if-1.0.0
diff --git a/Cargo.toml b/Cargo.toml
index 396a5c2..39b41f3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,18 +3,18 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
+rust-version = "1.40.0"
 name = "libloading"
-version = "0.7.0"
+version = "0.7.3"
 authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
-description = "A safer binding to platform’s dynamic library loading utilities"
+description = "Bindings around the platform's dynamic library loading primitives with greatly improved memory safety."
 documentation = "https://docs.rs/libloading/"
 readme = "README.mkd"
 keywords = ["dlopen", "load", "shared", "dylib"]
@@ -23,7 +23,7 @@
 repository = "https://github.com/nagisa/rust_libloading/"
 [package.metadata.docs.rs]
 all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "libloading_docs"]
 [dev-dependencies.libc]
 version = "0.2"
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index d946299..35e8353 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -2,16 +2,17 @@
 name = "libloading"
 # When bumping
 # * Don’t forget to add an entry to `src/changelog.rs`
-# * If bumping a incompatible version, adjust documentation in `src/lib.rs`
-version = "0.7.0"
+# * If bumping to an incompatible version, adjust the documentation in `src/lib.rs`
+version = "0.7.3"
 authors = ["Simonas Kazlauskas <libloading@kazlauskas.me>"]
 license = "ISC"
 repository = "https://github.com/nagisa/rust_libloading/"
 documentation = "https://docs.rs/libloading/"
 readme = "README.mkd"
-description = "A safer binding to platform’s dynamic library loading utilities"
+description = "Bindings around the platform's dynamic library loading primitives with greatly improved memory safety."
 keywords = ["dlopen", "load", "shared", "dylib"]
 categories = ["api-bindings"]
+rust-version = "1.40.0"
 
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
@@ -29,4 +30,4 @@
 
 [package.metadata.docs.rs]
 all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "libloading_docs"]
diff --git a/METADATA b/METADATA
index 769af4a..0efb20d 100644
--- a/METADATA
+++ b/METADATA
@@ -1,5 +1,5 @@
 name: "libloading"
-description: "A safer binding to platform\'s dynamic library loading utilities"
+description: "Bindings around the platform\'s dynamic library loading primitives with greatly improved memory safety."
 third_party {
   url {
     type: HOMEPAGE
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/libloading/libloading-0.7.0.crate"
+    value: "https://static.crates.io/crates/libloading/libloading-0.7.3.crate"
   }
-  version: "0.7.0"
+  version: "0.7.3"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 2
-    day: 9
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/README.mkd b/README.mkd
index 8f7d342..66abb30 100644
--- a/README.mkd
+++ b/README.mkd
@@ -1,11 +1,8 @@
 # libloading
 
-Safer bindings around system dynamic library loading primitives. The most important safety
-guarantee by this library is prevention of dangling-`Symbol`s that may occur after a `Library` is
-unloaded.
+Bindings around the platform's dynamic library loading primitives with greatly improved memory safety. The most important safety guarantee of this library is the prevention of dangling `Symbol`s that may occur after a `Library` is unloaded.
 
-Using this library allows loading dynamic libraries (also known as shared libraries) as well as use
-functions and static variables these libraries contain.
+Using this library allows the loading of dynamic libraries, also known as shared libraries, as well as the use of the functions and static variables that these libraries may contain.
 
 * [Documentation][docs]
 * [Changelog][changelog]
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 58584f2..0f8796c 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,11 +1,30 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
+  "imports": [
+    {
+      "path": "external/rust/crates/ash"
+    },
+    {
+      "path": "external/rust/crates/libsqlite3-sys"
+    },
+    {
+      "path": "external/rust/crates/vulkano"
+    }
+  ],
   "presubmit": [
     {
       "name": "keystore2_test"
     },
     {
-      "name": "libsqlite3-sys_device_test_src_lib"
+      "name": "legacykeystore_test"
+    }
+  ],
+  "presubmit-rust": [
+    {
+      "name": "keystore2_test"
+    },
+    {
+      "name": "legacykeystore_test"
     }
   ]
 }
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..42b7833
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,9 @@
+{
+  "apex-available": [
+    "//apex_available:platform",
+    "com.android.virt"
+  ],
+  "dependencies": true,
+  "device": true,
+  "run": true
+}
\ No newline at end of file
diff --git a/src/changelog.rs b/src/changelog.rs
index c927551..f8b898e 100644
--- a/src/changelog.rs
+++ b/src/changelog.rs
@@ -1,6 +1,43 @@
 //! The change log.
 
-/// Release 0.7.0 (2021-01-31)
+/// Release 0.7.3 (2022-01-15)
+///
+/// This release has no functional changes.
+///
+/// In this release the `docsrs` `cfg` has been renamed to `libloading_docs` to better reflect that
+/// this `cfg` is intended to be only used by `libloading` and only specifically for the invocation
+/// of `rustdoc` when documenting `libloading`. Setting this `cfg` in any other situation is
+/// unsupported and will not work.
+pub mod r0_7_3 {}
+
+/// Release 0.7.2 (2021-11-14)
+///
+/// Cargo.toml now specifies the MSRV bounds, which enables tooling to report an early failure when
+/// the version of the toolchain is insufficient. Refer to the [min-rust-version RFC] and its
+/// [tracking issue].
+///
+/// [min-rust-version RFC]: https://rust-lang.github.io/rfcs/2495-min-rust-version.html
+/// [tracking issue]: https://github.com/rust-lang/rust/issues/65262
+///
+/// Additionally, on platforms `libloading` has no support (today: `not(any(unix, windows))`), we
+/// will no longer attempt to implement the cross-platform `Library` and `Symbol` types. This makes
+/// `libloading` compile on targets such as `wasm32-unknown-unknown` and gives ability to the
+/// downstream consumers of this library to decide how they want to handle the absence of the
+/// library loading implementation in their code. One of such approaches could be depending on
+/// `libloading` itself optionally as such:
+///
+/// ```toml
+/// [target.'cfg(any(unix, windows))'.dependencies.libloading]
+/// version = "0.7"
+/// ```
+pub mod r0_7_2 {}
+
+/// Release 0.7.1 (2021-10-09)
+///
+/// Significantly improved the consistency and style of the documentation.
+pub mod r0_7_1 {}
+
+/// Release 0.7.0 (2021-02-06)
 ///
 /// ## Breaking changes
 ///
@@ -187,7 +224,6 @@
 /// [`Error`]: crate::Error
 pub mod r0_6_0 {}
 
-
 /// Release 0.5.2 (2019-07-07)
 ///
 /// * Added API to convert OS-specific `Library` and `Symbol` conversion to underlying resources.
@@ -218,7 +254,6 @@
 /// * `cargo test --release` now works when testing libloading.
 pub mod r0_4_3 {}
 
-
 /// Release 0.4.2 (2017-09-24)
 ///
 /// * Improved error and race-condition handling on Windows;
@@ -226,7 +261,6 @@
 /// * Added `Symbol::<Option<T>::lift_option() -> Option<Symbol<T>>` convenience method.
 pub mod r0_4_2 {}
 
-
 /// Release 0.4.1 (2017-08-29)
 ///
 /// * Solaris support
diff --git a/src/lib.rs b/src/lib.rs
index 9a531f1..6f0e4cb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,25 +1,27 @@
-//! A memory-safer wrapper around system dynamic library loading primitives.
+//! Bindings around the platform's dynamic library loading primitives with greatly improved memory safety.
 //!
-//! Using this library allows loading [dynamic libraries](struct.Library.html) (also known as
-//! shared libraries) and use functions & global variables contained within the libraries.
+//! Using this library allows the loading of [dynamic libraries](struct.Library.html), also known as
+//! shared libraries, and the use of the functions and static variables they contain.
 //!
-//! `libloading` crate exposes a cross-platform interface to load a library and utilize its
-//! contents, but little is done to paper over the differences in behaviour between different
-//! platforms. The API documentation strives to document such differences on the best-effort basis.
+//! The `libloading` crate exposes a cross-platform interface to load a library and make use of its
+//! contents, but little is done to hide the differences in behaviour between platforms.
+//! The API documentation strives to document such differences as much as possible.
 //!
-//! Platform specific APIs are also available in the [`os`](crate::os) module. These APIs are more
-//! flexible but less safe.
+//! Platform-specific APIs are also available in the [`os`](crate::os) module. These APIs are more
+//! flexible, but less safe.
 //!
-//! # Usage
+//! # Installation
 //!
-//! Add a dependency on this library to your `Cargo.toml`:
+//! Add the `libloading` library to your dependencies in `Cargo.toml`:
 //!
 //! ```toml
 //! [dependencies]
 //! libloading = "0.7"
 //! ```
 //!
-//! Then inside your code:
+//! # Usage
+//!
+//! In your code, run the following:
 //!
 //! ```no_run
 //! fn call_dynamic() -> Result<u32, Box<dyn std::error::Error>> {
@@ -31,319 +33,29 @@
 //! }
 //! ```
 //!
-//! The compiler will ensure that the loaded `function` will not outlive the `Library` it comes
-//! from, preventing a common class of issues.
-#![deny(
-    missing_docs,
-    clippy::all,
-    unreachable_pub,
-    unused,
-)]
-#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
-#![cfg_attr(docsrs, feature(doc_cfg))]
+//! The compiler will ensure that the loaded function will not outlive the `Library` from which it comes,
+//! preventing the most common memory-safety issues.
+#![cfg_attr(any(unix, windows), deny(missing_docs, clippy::all, unreachable_pub, unused))]
+#![cfg_attr(libloading_docs, feature(doc_cfg))]
+
+pub mod changelog;
+pub mod os;
+mod util;
+
+mod error;
+pub use self::error::Error;
+
+#[cfg(any(unix, windows, libloading_docs))]
+mod safe;
+#[cfg(any(unix, windows, libloading_docs))]
+pub use self::safe::{Library, Symbol};
 
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::ffi::{OsStr, OsString};
-use std::fmt;
-use std::ops;
-use std::marker;
-
-#[cfg(unix)]
-use self::os::unix as imp;
-#[cfg(windows)]
-use self::os::windows as imp;
-pub use self::error::Error;
-
-pub mod os;
-pub mod changelog;
-mod util;
-mod error;
-
-/// A loaded dynamic library.
-pub struct Library(imp::Library);
-
-impl Library {
-    /// Find and load a dynamic library.
-    ///
-    /// The `filename` argument may be any of:
-    ///
-    /// * A library filename;
-    /// * Absolute path to the library;
-    /// * Relative (to the current working directory) path to the library.
-    ///
-    /// # Safety
-    ///
-    /// When a library is loaded initialization routines contained within the library are executed.
-    /// For the purposes of safety, execution of these routines is conceptually the same calling an
-    /// unknown foreign function and may impose arbitrary requirements on the caller for the call
-    /// to be sound.
-    ///
-    /// Additionally, the callers of this function must also ensure that execution of the
-    /// termination routines contained within the library is safe as well. These routines may be
-    /// executed when the library is unloaded.
-    ///
-    /// # Thread-safety
-    ///
-    /// The implementation strives to be as MT-safe as sanely possible, however on certain
-    /// platforms the underlying error-handling related APIs not always MT-safe. This library
-    /// shares these limitations on those platforms. In particular, on certain UNIX targets
-    /// `dlerror` is not MT-safe, resulting in garbage error messages in certain MT-scenarios.
-    ///
-    /// Calling this function from multiple threads is not MT-safe if used in conjunction with
-    /// library filenames and the library search path is modified (`SetDllDirectory` function on
-    /// Windows, `{DY,}LD_LIBRARY_PATH` environment variable on UNIX).
-    ///
-    /// # Platform-specific behaviour
-    ///
-    /// When a plain library filename is supplied, locations where library is searched for is
-    /// platform specific and cannot be adjusted in a portable manner. See documentation for
-    /// the platform specific [`os::unix::Library::new`] and [`os::windows::Library::new`] methods
-    /// for further information on library lookup behaviour.
-    ///
-    /// If the `filename` specifies a library filename without path and with extension omitted,
-    /// `.dll` extension is implicitly added on Windows.
-    ///
-    /// # Tips
-    ///
-    /// Distributing your dynamic libraries under a filename common to all platforms (e.g.
-    /// `awesome.module`) allows to avoid code which has to account for platform’s conventional
-    /// library filenames.
-    ///
-    /// Strive to specify an absolute or at least a relative path to your library, unless
-    /// system-wide libraries are being loaded. Platform-dependent library search locations
-    /// combined with various quirks related to path-less filenames may cause flakiness in
-    /// programs.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// # use ::libloading::Library;
-    /// // Any of the following are valid.
-    /// unsafe {
-    ///     let _ = Library::new("/path/to/awesome.module").unwrap();
-    ///     let _ = Library::new("../awesome.module").unwrap();
-    ///     let _ = Library::new("libsomelib.so.1").unwrap();
-    /// }
-    /// ```
-    pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, Error> {
-        imp::Library::new(filename).map(From::from)
-    }
-
-    /// Get a pointer to function or static variable by symbol name.
-    ///
-    /// The `symbol` may not contain any null bytes, with an exception of last byte. Providing a
-    /// null terminated `symbol` may help to avoid an allocation.
-    ///
-    /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
-    /// most likely invalid.
-    ///
-    /// # Safety
-    ///
-    /// Users of this API must specify the correct type of the function or variable loaded. Using a
-    /// `Symbol` with a wrong type is undefined.
-    ///
-    /// # Platform-specific behaviour
-    ///
-    /// Implementation of thread local variables is extremely platform specific and uses of such
-    /// variables that work on e.g. Linux may have unintended behaviour on other targets.
-    ///
-    /// On POSIX implementations where the `dlerror` function is not confirmed to be MT-safe (such
-    /// as FreeBSD), this function will unconditionally return an error when the underlying `dlsym`
-    /// call returns a null pointer. There are rare situations where `dlsym` returns a genuine null
-    /// pointer without it being an error. If loading a null pointer is something you care about,
-    /// consider using the [`os::unix::Library::get_singlethreaded`] call.
-    ///
-    /// # Examples
-    ///
-    /// Given a loaded library:
-    ///
-    /// ```no_run
-    /// # use ::libloading::Library;
-    /// let lib = unsafe {
-    ///     Library::new("/path/to/awesome.module").unwrap()
-    /// };
-    /// ```
-    ///
-    /// Loading and using a function looks like this:
-    ///
-    /// ```no_run
-    /// # use ::libloading::{Library, Symbol};
-    /// # let lib = unsafe {
-    /// #     Library::new("/path/to/awesome.module").unwrap()
-    /// # };
-    /// unsafe {
-    ///     let awesome_function: Symbol<unsafe extern fn(f64) -> f64> =
-    ///         lib.get(b"awesome_function\0").unwrap();
-    ///     awesome_function(0.42);
-    /// }
-    /// ```
-    ///
-    /// A static variable may also be loaded and inspected:
-    ///
-    /// ```no_run
-    /// # use ::libloading::{Library, Symbol};
-    /// # let lib = unsafe { Library::new("/path/to/awesome.module").unwrap() };
-    /// unsafe {
-    ///     let awesome_variable: Symbol<*mut f64> = lib.get(b"awesome_variable\0").unwrap();
-    ///     **awesome_variable = 42.0;
-    /// };
-    /// ```
-    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>, Error> {
-        self.0.get(symbol).map(|from| Symbol::from_raw(from, self))
-    }
-
-    /// Unload the library.
-    ///
-    /// This method might be a no-op, depending on the flags with which the `Library` was opened,
-    /// what library was opened or other platform specifics.
-    ///
-    /// You only need to call this if you are interested in handling any errors that may arise when
-    /// library is unloaded. Otherwise the implementation of `Drop` for `Library` will close the
-    /// library and ignore the errors were they arise.
-    ///
-    /// The underlying data structures may still get leaked if an error does occur.
-    pub fn close(self) -> Result<(), Error> {
-        self.0.close()
-    }
-}
-
-impl fmt::Debug for Library {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
-impl From<imp::Library> for Library {
-    fn from(lib: imp::Library) -> Library {
-        Library(lib)
-    }
-}
-
-impl From<Library> for imp::Library {
-    fn from(lib: Library) -> imp::Library {
-        lib.0
-    }
-}
-
-unsafe impl Send for Library {}
-unsafe impl Sync for Library {}
-
-/// Symbol from a library.
-///
-/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
-/// unloaded. Primary method to create an instance of a `Symbol` is via [`Library::get`].
-///
-/// The `Deref` trait implementation allows use of `Symbol` as if it was a function or variable
-/// itself, without taking care to “extract” function or variable manually most of the time.
-///
-/// [`Library::get`]: Library::get
-pub struct Symbol<'lib, T: 'lib> {
-    inner: imp::Symbol<T>,
-    pd: marker::PhantomData<&'lib T>
-}
-
-impl<'lib, T> Symbol<'lib, T> {
-    /// Extract the wrapped `os::platform::Symbol`.
-    ///
-    /// # Safety
-    ///
-    /// Using this function relinquishes all the lifetime guarantees. It is up to programmer to
-    /// ensure the resulting `Symbol` is not used past the lifetime of the `Library` this symbol
-    /// was loaded from.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// # use ::libloading::{Library, Symbol};
-    /// unsafe {
-    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
-    ///     let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
-    ///     let symbol = symbol.into_raw();
-    /// }
-    /// ```
-    pub unsafe fn into_raw(self) -> imp::Symbol<T> {
-        self.inner
-    }
-
-    /// Wrap the `os::platform::Symbol` into this safe wrapper.
-    ///
-    /// Note that, in order to create association between the symbol and the library this symbol
-    /// came from, this function requires a reference to the library.
-    ///
-    /// # Safety
-    ///
-    /// The `library` reference must be exactly the library `sym` was loaded from.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// # use ::libloading::{Library, Symbol};
-    /// unsafe {
-    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
-    ///     let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
-    ///     let symbol = symbol.into_raw();
-    ///     let symbol = Symbol::from_raw(symbol, &lib);
-    /// }
-    /// ```
-    pub unsafe fn from_raw<L>(sym: imp::Symbol<T>, library: &'lib L) -> Symbol<'lib, T> {
-        let _ = library; // ignore here for documentation purposes.
-        Symbol {
-            inner: sym,
-            pd: marker::PhantomData
-        }
-    }
-}
-
-impl<'lib, T> Symbol<'lib, Option<T>> {
-    /// Lift Option out of the symbol.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// # use ::libloading::{Library, Symbol};
-    /// unsafe {
-    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
-    ///     let symbol: Symbol<Option<*mut u32>> = lib.get(b"symbol\0").unwrap();
-    ///     let symbol: Symbol<*mut u32> = symbol.lift_option().expect("static is not null");
-    /// }
-    /// ```
-    pub fn lift_option(self) -> Option<Symbol<'lib, T>> {
-        self.inner.lift_option().map(|is| Symbol {
-            inner: is,
-            pd: marker::PhantomData,
-        })
-    }
-}
-
-impl<'lib, T> Clone for Symbol<'lib, T> {
-    fn clone(&self) -> Symbol<'lib, T> {
-        Symbol {
-            inner: self.inner.clone(),
-            pd: marker::PhantomData
-        }
-    }
-}
-
-// FIXME: implement FnOnce for callable stuff instead.
-impl<'lib, T> ops::Deref for Symbol<'lib, T> {
-    type Target = T;
-    fn deref(&self) -> &T {
-        ops::Deref::deref(&self.inner)
-    }
-}
-
-impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
-    }
-}
-
-unsafe impl<'lib, T: Send> Send for Symbol<'lib, T> {}
-unsafe impl<'lib, T: Sync> Sync for Symbol<'lib, T> {}
 
 /// Converts a library name to a filename generally appropriate for use on the system.
 ///
-/// The function will prepend prefixes (such as `lib`) and suffixes (such as `.so`) to the library
+/// This function will prepend prefixes (such as `lib`) and suffixes (such as `.so`) to the library
 /// `name` to construct the filename.
 ///
 /// # Examples
diff --git a/src/os/mod.rs b/src/os/mod.rs
index c03ebc1..710353f 100644
--- a/src/os/mod.rs
+++ b/src/os/mod.rs
@@ -1,6 +1,6 @@
-//! Unsafe but flexible platform specific bindings to dynamic library loading facilities.
+//! Unsafe but flexible platform-specific bindings to dynamic library loading facilities.
 //!
-//! These modules expose more extensive, powerful, less principled bindings to the dynamic
+//! These modules expose more extensive and powerful bindings to the dynamic
 //! library loading facilities. Use of these bindings come at the cost of less (in most cases,
 //! none at all) safety guarantees, which are provided by the top-level bindings.
 //!
@@ -17,11 +17,11 @@
 //! ```
 
 /// UNIX implementation of dynamic library loading.
-#[cfg(any(unix, docsrs))]
-#[cfg_attr(docsrs, doc(cfg(unix)))]
+#[cfg(any(unix, libloading_docs))]
+#[cfg_attr(libloading_docs, doc(cfg(unix)))]
 pub mod unix;
 
 /// Windows implementation of dynamic library loading.
-#[cfg(any(windows, docsrs))]
-#[cfg_attr(docsrs, doc(cfg(windows)))]
+#[cfg(any(windows, libloading_docs))]
+#[cfg_attr(libloading_docs, doc(cfg(windows)))]
 pub mod windows;
diff --git a/src/os/unix/consts.rs b/src/os/unix/consts.rs
index 2c18f95..dbe4df9 100644
--- a/src/os/unix/consts.rs
+++ b/src/os/unix/consts.rs
@@ -7,7 +7,7 @@
 /// Specifying `RTLD_LAZY` should improve performance on implementations supporting dynamic
 /// symbol binding since a process might not reference all of the symbols in an executable
 /// object file. And, for systems supporting dynamic symbol resolution for normal process
-/// execution, this behavior mimics the normal handling of process execution.
+/// execution, this behaviour mimics the normal handling of process execution.
 ///
 /// Conflicts with [`RTLD_NOW`].
 ///
@@ -18,7 +18,7 @@
 ///
 /// All necessary relocations shall be performed when the executable object file is first
 /// loaded. This may waste some processing if relocations are performed for symbols
-/// that are never referenced. This behavior may be useful for applications that need to
+/// that are never referenced. This behaviour may be useful for applications that need to
 /// know that all symbols referenced during execution will be available before
 /// [`Library::open`] returns.
 ///
@@ -43,7 +43,7 @@
 /// any other executable object file. This mode of operation is most appropriate for e.g. plugins.
 pub const RTLD_LOCAL: c_int = posix::RTLD_LOCAL;
 
-#[cfg(all(docsrs, not(unix)))]
+#[cfg(all(libloading_docs, not(unix)))]
 mod posix {
     use super::c_int;
     pub(super) const RTLD_LAZY: c_int = !0;
@@ -52,7 +52,7 @@
     pub(super) const RTLD_LOCAL: c_int = !0;
 }
 
-#[cfg(any(not(docsrs), unix))]
+#[cfg(any(not(libloading_docs), unix))]
 mod posix {
     extern crate cfg_if;
     use self::cfg_if::cfg_if;
diff --git a/src/os/unix/mod.rs b/src/os/unix/mod.rs
index 45e8230..fd0777e 100644
--- a/src/os/unix/mod.rs
+++ b/src/os/unix/mod.rs
@@ -1,19 +1,18 @@
 // A hack for docs.rs to build documentation that has both windows and linux documentation in the
 // same rustdoc build visible.
-#[cfg(all(docsrs, not(unix)))]
-mod unix_imports {
-}
-#[cfg(any(not(docsrs), unix))]
+#[cfg(all(libloading_docs, not(unix)))]
+mod unix_imports {}
+#[cfg(any(not(libloading_docs), unix))]
 mod unix_imports {
     pub(super) use std::os::unix::ffi::OsStrExt;
 }
 
-use self::unix_imports::*;
-use util::{ensure_compatible_types, cstr_cow_from_bytes};
-use std::ffi::{CStr, OsStr};
-use std::{fmt, marker, mem, ptr};
-use std::os::raw;
 pub use self::consts::*;
+use self::unix_imports::*;
+use std::ffi::{CStr, OsStr};
+use std::os::raw;
+use std::{fmt, marker, mem, ptr};
+use util::{cstr_cow_from_bytes, ensure_compatible_types};
 
 mod consts;
 
@@ -109,8 +108,8 @@
     ///
     /// # Safety
     ///
-    /// When a library is loaded initialization routines contained within the library are executed.
-    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// When a library is loaded, initialisation routines contained within the library are executed.
+    /// For the purposes of safety, the execution of these routines is conceptually the same calling an
     /// unknown foreign function and may impose arbitrary requirements on the caller for the call
     /// to be sound.
     ///
@@ -127,12 +126,12 @@
     /// [`Library::get`] calls of the returned `Library` will look for symbols in following
     /// locations in order:
     ///
-    /// 1. Original program image;
+    /// 1. The original program image;
     /// 2. Any executable object files (e.g. shared libraries) loaded at program startup;
-    /// 3. Executable object files loaded at runtime (e.g. via other `Library::new` calls or via
-    ///    calls to the `dlopen` function)
+    /// 3. Any executable object files loaded at runtime (e.g. via other `Library::new` calls or via
+    ///    calls to the `dlopen` function).
     ///
-    /// Note that behaviour of `Library` loaded with this method is different from
+    /// Note that the behaviour of a `Library` loaded with this method is different from that of
     /// Libraries loaded with [`os::windows::Library::this`].
     ///
     /// This is equivalent to <code>[Library::open](None, [RTLD_LAZY] | [RTLD_LOCAL])</code>.
@@ -142,22 +141,22 @@
     pub fn this() -> Library {
         unsafe {
             // SAFE: this does not load any new shared library images, no danger in it executing
-            // initializer routines.
+            // initialiser routines.
             Library::open(None::<&OsStr>, RTLD_LAZY | RTLD_LOCAL).expect("this should never fail")
         }
     }
 
     /// Find and load an executable object file (shared library).
     ///
-    /// See documentation for [`Library::this`] for further description of behaviour
+    /// See documentation for [`Library::this`] for further description of the behaviour
     /// when the `filename` is `None`. Otherwise see [`Library::new`].
     ///
     /// Corresponds to `dlopen(filename, flags)`.
     ///
     /// # Safety
     ///
-    /// When a library is loaded initialization routines contained within the library are executed.
-    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// When a library is loaded, initialisation routines contained within the library are executed.
+    /// For the purposes of safety, the execution of these routines is conceptually the same calling an
     /// unknown foreign function and may impose arbitrary requirements on the caller for the call
     /// to be sound.
     ///
@@ -217,9 +216,9 @@
 
     }
 
-    /// Get a pointer to function or static variable by symbol name.
+    /// Get a pointer to a function or static variable by symbol name.
     ///
-    /// The `symbol` may not contain any null bytes, with an exception of last byte. Providing a
+    /// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
     /// null terminated `symbol` may help to avoid an allocation.
     ///
     /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
@@ -265,7 +264,7 @@
 
     /// Get a pointer to function or static variable by symbol name.
     ///
-    /// The `symbol` may not contain any null bytes, with an exception of last byte. Providing a
+    /// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
     /// null terminated `symbol` may help to avoid an allocation.
     ///
     /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
@@ -273,16 +272,15 @@
     ///
     /// # Safety
     ///
-    /// Users of this API must specify the correct type of the function or variable loaded. Using a
-    /// `Symbol` with a wrong type is undefined.
+    /// Users of this API must specify the correct type of the function or variable loaded.
     ///
     /// It is up to the user of this library to ensure that no other calls to an MT-unsafe
-    /// implementation of `dlerror` occur during execution of this function. Failing that, the
+    /// implementation of `dlerror` occur during the execution of this function. Failing that, the
     /// behaviour of this function is not defined.
     ///
     /// # Platform-specific behaviour
     ///
-    /// Implementation of thread local variables is extremely platform specific and uses of such
+    /// The implementation of thread-local variables is extremely platform specific and uses of such
     /// variables that work on e.g. Linux may have unintended behaviour on other targets.
     #[inline(always)]
     pub unsafe fn get_singlethreaded<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
@@ -357,15 +355,15 @@
 
 /// Symbol from a library.
 ///
-/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
-/// `Symbol` does not outlive `Library` it comes from.
+/// A major difference compared to the cross-platform `Symbol` is that this does not ensure that the
+/// `Symbol` does not outlive the `Library` it comes from.
 pub struct Symbol<T> {
     pointer: *mut raw::c_void,
     pd: marker::PhantomData<T>
 }
 
 impl<T> Symbol<T> {
-    /// Convert the loaded Symbol into a raw pointer.
+    /// Convert the loaded `Symbol` into a raw pointer.
     pub fn into_raw(self) -> *mut raw::c_void {
         let pointer = self.pointer;
         mem::forget(self);
diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs
index 7e28527..eadeb69 100644
--- a/src/os/windows/mod.rs
+++ b/src/os/windows/mod.rs
@@ -1,6 +1,6 @@
 // A hack for docs.rs to build documentation that has both windows and linux documentation in the
 // same rustdoc build visible.
-#[cfg(all(docsrs, not(windows)))]
+#[cfg(all(libloading_docs, not(windows)))]
 mod windows_imports {
     pub(super) enum WORD {}
     pub(super) struct DWORD;
@@ -23,7 +23,7 @@
         pub(crate) const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = DWORD;
     }
 }
-#[cfg(any(not(docsrs), windows))]
+#[cfg(any(not(libloading_docs), windows))]
 mod windows_imports {
     extern crate winapi;
     pub(super) use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
@@ -55,23 +55,23 @@
 use std::ffi::{OsStr, OsString};
 use std::{fmt, io, marker, mem, ptr};
 
-/// A platform-specific counterpart of the cross-platform [`Library`](crate::Library).
+/// The platform-specific counterpart of the cross-platform [`Library`](crate::Library).
 pub struct Library(HMODULE);
 
 unsafe impl Send for Library {}
 // Now, this is sort-of-tricky. MSDN documentation does not really make any claims as to safety of
 // the Win32 APIs. Sadly, whomever I asked, even current and former Microsoft employees, couldn’t
-// say for sure, whether the Win32 APIs used to implement `Library` are thread-safe or not.
+// say for sure whether the Win32 APIs used to implement `Library` are thread-safe or not.
 //
 // My investigation ended up with a question about thread-safety properties of the API involved
 // being sent to an internal (to MS) general question mailing-list. The conclusion of the mail is
 // as such:
 //
-// * Nobody inside MS (at least out of all the people who have seen the question) knows for
+// * Nobody inside MS (at least out of all of the people who have seen the question) knows for
 //   sure either;
 // * However, the general consensus between MS developers is that one can rely on the API being
 //   thread-safe. In case it is not thread-safe it should be considered a bug on the Windows
-//   part. (NB: bugs filled at https://connect.microsoft.com/ against Windows Server)
+//   part. (NB: bugs filed at https://connect.microsoft.com/ against Windows Server)
 unsafe impl Sync for Library {}
 
 impl Library {
@@ -79,11 +79,11 @@
     ///
     /// If the `filename` specifies a full path, the function only searches that path for the
     /// module. Otherwise, if the `filename` specifies a relative path or a module name without a
-    /// path, the function uses a windows-specific search strategy to find the module; for more
+    /// path, the function uses a Windows-specific search strategy to find the module. For more
     /// information, see the [Remarks on MSDN][msdn].
     ///
-    /// If the `filename` specifies a library filename without path and with extension omitted,
-    /// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
+    /// If the `filename` specifies a library filename without a path and with the extension omitted,
+    /// the `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
     /// trailing `.` to the `filename`.
     ///
     /// This is equivalent to <code>[Library::load_with_flags](filename, 0)</code>.
@@ -92,8 +92,8 @@
     ///
     /// # Safety
     ///
-    /// When a library is loaded initialization routines contained within the library are executed.
-    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// When a library is loaded, initialisation routines contained within the library are executed.
+    /// For the purposes of safety, the execution of these routines is conceptually the same calling an
     /// unknown foreign function and may impose arbitrary requirements on the caller for the call
     /// to be sound.
     ///
@@ -107,7 +107,7 @@
 
     /// Get the `Library` representing the original program executable.
     ///
-    /// Note that behaviour of `Library` loaded with this method is different from
+    /// Note that the behaviour of the `Library` loaded with this method is different from
     /// Libraries loaded with [`os::unix::Library::this`]. For more information refer to [MSDN].
     ///
     /// Corresponds to `GetModuleHandleExW(0, NULL, _)`.
@@ -131,15 +131,15 @@
     /// Get a module that is already loaded by the program.
     ///
     /// This function returns a `Library` corresponding to a module with the given name that is
-    /// already mapped into the address space of the process. If the module isn't found an error is
+    /// already mapped into the address space of the process. If the module isn't found, an error is
     /// returned.
     ///
     /// If the `filename` does not include a full path and there are multiple different loaded
     /// modules corresponding to the `filename`, it is impossible to predict which module handle
     /// will be returned. For more information refer to [MSDN].
     ///
-    /// If the `filename` specifies a library filename without path and with extension omitted,
-    /// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
+    /// If the `filename` specifies a library filename without a path and with the extension omitted,
+    /// the `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
     /// trailing `.` to the `filename`.
     ///
     /// This is equivalent to `GetModuleHandleExW(0, filename, _)`.
@@ -169,7 +169,7 @@
 
     /// Find and load a module, additionally adjusting behaviour with flags.
     ///
-    /// See [`Library::new`] for documentation on handling of the `filename` argument. See the
+    /// See [`Library::new`] for documentation on the handling of the `filename` argument. See the
     /// [flag table on MSDN][flags] for information on applicable values for the `flags` argument.
     ///
     /// Corresponds to `LoadLibraryExW(filename, reserved: NULL, flags)`.
@@ -178,8 +178,8 @@
     ///
     /// # Safety
     ///
-    /// When a library is loaded initialization routines contained within the library are executed.
-    /// For the purposes of safety, execution of these routines is conceptually the same calling an
+    /// When a library is loaded, initialisation routines contained within the library are executed.
+    /// For the purposes of safety, the execution of these routines is conceptually the same calling an
     /// unknown foreign function and may impose arbitrary requirements on the caller for the call
     /// to be sound.
     ///
@@ -206,9 +206,9 @@
         ret
     }
 
-    /// Get a pointer to function or static variable by symbol name.
+    /// Get a pointer to a function or static variable by symbol name.
     ///
-    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
+    /// The `symbol` may not contain any null bytes, with the exception of the last byte. A null
     /// terminated `symbol` may avoid a string allocation in some cases.
     ///
     /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
@@ -216,8 +216,7 @@
     ///
     /// # Safety
     ///
-    /// Users of this API must specify the correct type of the function or variable loaded. Using a
-    /// `Symbol` with a wrong type is undefined.
+    /// Users of this API must specify the correct type of the function or variable loaded.
     pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
         ensure_compatible_types::<T, FARPROC>()?;
         let symbol = cstr_cow_from_bytes(symbol)?;
@@ -234,12 +233,11 @@
         }).map_err(|e| e.unwrap_or(crate::Error::GetProcAddressUnknown))
     }
 
-    /// Get a pointer to function or static variable by ordinal number.
+    /// Get a pointer to a function or static variable by ordinal number.
     ///
     /// # Safety
     ///
-    /// Users of this API must specify the correct type of the function or variable loaded. Using a
-    /// `Symbol` with a wrong type is undefined.
+    /// Users of this API must specify the correct type of the function or variable loaded.
     pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error> {
         ensure_compatible_types::<T, FARPROC>()?;
         with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
@@ -267,8 +265,8 @@
     ///
     /// # Safety
     ///
-    /// The handle shall be a result of a successful call of `LoadLibraryA`, `LoadLibraryW`,
-    /// `LoadLibraryExW`, `LoadLibraryExA` or a handle previously returned by the
+    /// The handle must be the result of a successful call of `LoadLibraryA`, `LoadLibraryW`,
+    /// `LoadLibraryExW`, or `LoadLibraryExA`, or a handle previously returned by the
     /// `Library::into_raw` call.
     pub unsafe fn from_raw(handle: HMODULE) -> Library {
         Library(handle)
@@ -290,7 +288,7 @@
         }).map_err(|e| e.unwrap_or(crate::Error::FreeLibraryUnknown));
         // While the library is not free'd yet in case of an error, there is no reason to try
         // dropping it again, because all that will do is try calling `FreeLibrary` again. only
-        // this time it would ignore the return result, which we already seen failing…
+        // this time it would ignore the return result, which we already seen failing...
         std::mem::forget(self);
         result
     }
@@ -323,17 +321,17 @@
     }
 }
 
-/// Symbol from a library.
+/// A symbol from a library.
 ///
-/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
-/// `Symbol` does not outlive `Library` it comes from.
+/// A major difference compared to the cross-platform `Symbol` is that this does not ensure that the
+/// `Symbol` does not outlive the `Library` that it comes from.
 pub struct Symbol<T> {
     pointer: FARPROC,
     pd: marker::PhantomData<T>
 }
 
 impl<T> Symbol<T> {
-    /// Convert the loaded Symbol into a handle.
+    /// Convert the loaded `Symbol` into a handle.
     pub fn into_raw(self) -> FARPROC {
         let pointer = self.pointer;
         mem::forget(self);
@@ -452,7 +450,7 @@
 
 /// Map the file into the process’ virtual address space as an image file.
 ///
-/// The loader does not load the static imports or perform the other usual initialization steps.
+/// The loader does not load the static imports or perform the other usual initialisation steps.
 /// Use this flag when you want to load a DLL only to extract messages or resources from it.
 ///
 /// Unless the application depends on the file having the in-memory layout of an image, this value
@@ -462,7 +460,7 @@
 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
 pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = consts::LOAD_LIBRARY_AS_IMAGE_RESOURCE;
 
-/// Search application's installation directory for the DLL and its dependencies.
+/// Search the application's installation directory for the DLL and its dependencies.
 ///
 /// Directories in the standard search path are not searched. This value cannot be combined with
 /// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
@@ -509,11 +507,11 @@
 /// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
 pub const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_USER_DIRS;
 
-/// If `filename specifies an absolute path, the system uses the alternate file search strategy
+/// If `filename` specifies an absolute path, the system uses the alternate file search strategy
 /// discussed in the [Remarks section] to find associated executable modules that the specified
 /// module causes to be loaded.
 ///
-/// If this value is used and `filename` specifies a relative path, the behavior is undefined.
+/// If this value is used and `filename` specifies a relative path, the behaviour is undefined.
 ///
 /// If this value is not used, or if `filename` does not specify a path, the system uses the
 /// standard search strategy discussed in the [Remarks section] to find associated executable
diff --git a/src/safe.rs b/src/safe.rs
new file mode 100644
index 0000000..49be0cf
--- /dev/null
+++ b/src/safe.rs
@@ -0,0 +1,299 @@
+use super::Error;
+#[cfg(libloading_docs)]
+use super::os::unix as imp; // the implementation used here doesn't matter particularly much...
+#[cfg(all(not(libloading_docs), unix))]
+use super::os::unix as imp;
+#[cfg(all(not(libloading_docs), windows))]
+use super::os::windows as imp;
+use std::ffi::OsStr;
+use std::fmt;
+use std::marker;
+use std::ops;
+
+/// A loaded dynamic library.
+#[cfg_attr(libloading_docs, doc(cfg(any(unix, windows))))]
+pub struct Library(imp::Library);
+
+impl Library {
+    /// Find and load a dynamic library.
+    ///
+    /// The `filename` argument may be either:
+    ///
+    /// * A library filename;
+    /// * The absolute path to the library;
+    /// * A relative (to the current working directory) path to the library.
+    ///
+    /// # Safety
+    ///
+    /// When a library is loaded, initialisation routines contained within it are executed.
+    /// For the purposes of safety, the execution of these routines is conceptually the same calling an
+    /// unknown foreign function and may impose arbitrary requirements on the caller for the call
+    /// to be sound.
+    ///
+    /// Additionally, the callers of this function must also ensure that execution of the
+    /// termination routines contained within the library is safe as well. These routines may be
+    /// executed when the library is unloaded.
+    ///
+    /// # Thread-safety
+    ///
+    /// The implementation strives to be as MT-safe as sanely possible, however on certain
+    /// platforms the underlying error-handling related APIs not always MT-safe. This library
+    /// shares these limitations on those platforms. In particular, on certain UNIX targets
+    /// `dlerror` is not MT-safe, resulting in garbage error messages in certain MT-scenarios.
+    ///
+    /// Calling this function from multiple threads is not MT-safe if used in conjunction with
+    /// library filenames and the library search path is modified (`SetDllDirectory` function on
+    /// Windows, `{DY,}LD_LIBRARY_PATH` environment variable on UNIX).
+    ///
+    /// # Platform-specific behaviour
+    ///
+    /// When a plain library filename is supplied, the locations in which the library is searched are
+    /// platform specific and cannot be adjusted in a portable manner. See the documentation for
+    /// the platform specific [`os::unix::Library::new`] and [`os::windows::Library::new`] methods
+    /// for further information on library lookup behaviour.
+    ///
+    /// If the `filename` specifies a library filename without a path and with the extension omitted,
+    /// the `.dll` extension is implicitly added on Windows.
+    ///
+    /// [`os::unix::Library::new`]: crate::os::unix::Library::new
+    /// [`os::windows::Library::new`]: crate::os::windows::Library::new
+    ///
+    /// # Tips
+    ///
+    /// Distributing your dynamic libraries under a filename common to all platforms (e.g.
+    /// `awesome.module`) allows you to avoid code which has to account for platform’s conventional
+    /// library filenames.
+    ///
+    /// Strive to specify an absolute or at least a relative path to your library, unless
+    /// system-wide libraries are being loaded. Platform-dependent library search locations
+    /// combined with various quirks related to path-less filenames may cause flakiness in
+    /// programs.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// # use ::libloading::Library;
+    /// // Any of the following are valid.
+    /// unsafe {
+    ///     let _ = Library::new("/path/to/awesome.module").unwrap();
+    ///     let _ = Library::new("../awesome.module").unwrap();
+    ///     let _ = Library::new("libsomelib.so.1").unwrap();
+    /// }
+    /// ```
+    pub unsafe fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, Error> {
+        imp::Library::new(filename).map(From::from)
+    }
+
+    /// Get a pointer to a function or static variable by symbol name.
+    ///
+    /// The `symbol` may not contain any null bytes, with the exception of the last byte. Providing a
+    /// null-terminated `symbol` may help to avoid an allocation.
+    ///
+    /// The symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
+    /// most likely invalid.
+    ///
+    /// # Safety
+    ///
+    /// Users of this API must specify the correct type of the function or variable loaded.
+    ///
+    /// # Platform-specific behaviour
+    ///
+    /// The implementation of thread-local variables is extremely platform specific and uses of such
+    /// variables that work on e.g. Linux may have unintended behaviour on other targets.
+    ///
+    /// On POSIX implementations where the `dlerror` function is not confirmed to be MT-safe (such
+    /// as FreeBSD), this function will unconditionally return an error when the underlying `dlsym`
+    /// call returns a null pointer. There are rare situations where `dlsym` returns a genuine null
+    /// pointer without it being an error. If loading a null pointer is something you care about,
+    /// consider using the [`os::unix::Library::get_singlethreaded`] call.
+    ///
+    /// [`os::unix::Library::get_singlethreaded`]: crate::os::unix::Library::get_singlethreaded
+    ///
+    /// # Examples
+    ///
+    /// Given a loaded library:
+    ///
+    /// ```no_run
+    /// # use ::libloading::Library;
+    /// let lib = unsafe {
+    ///     Library::new("/path/to/awesome.module").unwrap()
+    /// };
+    /// ```
+    ///
+    /// Loading and using a function looks like this:
+    ///
+    /// ```no_run
+    /// # use ::libloading::{Library, Symbol};
+    /// # let lib = unsafe {
+    /// #     Library::new("/path/to/awesome.module").unwrap()
+    /// # };
+    /// unsafe {
+    ///     let awesome_function: Symbol<unsafe extern fn(f64) -> f64> =
+    ///         lib.get(b"awesome_function\0").unwrap();
+    ///     awesome_function(0.42);
+    /// }
+    /// ```
+    ///
+    /// A static variable may also be loaded and inspected:
+    ///
+    /// ```no_run
+    /// # use ::libloading::{Library, Symbol};
+    /// # let lib = unsafe { Library::new("/path/to/awesome.module").unwrap() };
+    /// unsafe {
+    ///     let awesome_variable: Symbol<*mut f64> = lib.get(b"awesome_variable\0").unwrap();
+    ///     **awesome_variable = 42.0;
+    /// };
+    /// ```
+    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>, Error> {
+        self.0.get(symbol).map(|from| Symbol::from_raw(from, self))
+    }
+
+    /// Unload the library.
+    ///
+    /// This method might be a no-op, depending on the flags with which the `Library` was opened,
+    /// what library was opened or other platform specifics.
+    ///
+    /// You only need to call this if you are interested in handling any errors that may arise when
+    /// library is unloaded. Otherwise the implementation of `Drop` for `Library` will close the
+    /// library and ignore the errors were they arise.
+    ///
+    /// The underlying data structures may still get leaked if an error does occur.
+    pub fn close(self) -> Result<(), Error> {
+        self.0.close()
+    }
+}
+
+impl fmt::Debug for Library {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl From<imp::Library> for Library {
+    fn from(lib: imp::Library) -> Library {
+        Library(lib)
+    }
+}
+
+impl From<Library> for imp::Library {
+    fn from(lib: Library) -> imp::Library {
+        lib.0
+    }
+}
+
+unsafe impl Send for Library {}
+unsafe impl Sync for Library {}
+
+/// Symbol from a library.
+///
+/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
+/// unloaded. The primary method to create an instance of a `Symbol` is via [`Library::get`].
+///
+/// The `Deref` trait implementation allows the use of `Symbol` as if it was a function or variable
+/// itself, without taking care to “extract” the function or variable manually most of the time.
+///
+/// [`Library::get`]: Library::get
+#[cfg_attr(libloading_docs, doc(cfg(any(unix, windows))))]
+pub struct Symbol<'lib, T: 'lib> {
+    inner: imp::Symbol<T>,
+    pd: marker::PhantomData<&'lib T>,
+}
+
+impl<'lib, T> Symbol<'lib, T> {
+    /// Extract the wrapped `os::platform::Symbol`.
+    ///
+    /// # Safety
+    ///
+    /// Using this function relinquishes all the lifetime guarantees. It is up to the developer to
+    /// ensure the resulting `Symbol` is not used past the lifetime of the `Library` this symbol
+    /// was loaded from.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// # use ::libloading::{Library, Symbol};
+    /// unsafe {
+    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
+    ///     let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
+    ///     let symbol = symbol.into_raw();
+    /// }
+    /// ```
+    pub unsafe fn into_raw(self) -> imp::Symbol<T> {
+        self.inner
+    }
+
+    /// Wrap the `os::platform::Symbol` into this safe wrapper.
+    ///
+    /// Note that, in order to create association between the symbol and the library this symbol
+    /// came from, this function requires a reference to the library.
+    ///
+    /// # Safety
+    ///
+    /// The `library` reference must be exactly the library `sym` was loaded from.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// # use ::libloading::{Library, Symbol};
+    /// unsafe {
+    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
+    ///     let symbol: Symbol<*mut u32> = lib.get(b"symbol\0").unwrap();
+    ///     let symbol = symbol.into_raw();
+    ///     let symbol = Symbol::from_raw(symbol, &lib);
+    /// }
+    /// ```
+    pub unsafe fn from_raw<L>(sym: imp::Symbol<T>, library: &'lib L) -> Symbol<'lib, T> {
+        let _ = library; // ignore here for documentation purposes.
+        Symbol {
+            inner: sym,
+            pd: marker::PhantomData,
+        }
+    }
+}
+
+impl<'lib, T> Symbol<'lib, Option<T>> {
+    /// Lift Option out of the symbol.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// # use ::libloading::{Library, Symbol};
+    /// unsafe {
+    ///     let lib = Library::new("/path/to/awesome.module").unwrap();
+    ///     let symbol: Symbol<Option<*mut u32>> = lib.get(b"symbol\0").unwrap();
+    ///     let symbol: Symbol<*mut u32> = symbol.lift_option().expect("static is not null");
+    /// }
+    /// ```
+    pub fn lift_option(self) -> Option<Symbol<'lib, T>> {
+        self.inner.lift_option().map(|is| Symbol {
+            inner: is,
+            pd: marker::PhantomData,
+        })
+    }
+}
+
+impl<'lib, T> Clone for Symbol<'lib, T> {
+    fn clone(&self) -> Symbol<'lib, T> {
+        Symbol {
+            inner: self.inner.clone(),
+            pd: marker::PhantomData,
+        }
+    }
+}
+
+// FIXME: implement FnOnce for callable stuff instead.
+impl<'lib, T> ops::Deref for Symbol<'lib, T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        ops::Deref::deref(&self.inner)
+    }
+}
+
+impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+unsafe impl<'lib, T: Send> Send for Symbol<'lib, T> {}
+unsafe impl<'lib, T: Sync> Sync for Symbol<'lib, T> {}
diff --git a/src/util.rs b/src/util.rs
index 880b689..599e6c2 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,10 +1,10 @@
-use std::ffi::{CStr, CString};
 use std::borrow::Cow;
+use std::ffi::{CStr, CString};
 use std::os::raw;
 
 use crate::Error;
 
-/// Checks for last byte and avoids allocating if it is zero.
+/// Checks for the last byte and avoids allocating if it is zero.
 ///
 /// Non-last null bytes still result in an error.
 pub(crate) fn cstr_cow_from_bytes(slice: &[u8]) -> Result<Cow<'_, CStr>, Error> {
@@ -13,11 +13,14 @@
         // Slice out of 0 elements
         None => unsafe { Cow::Borrowed(CStr::from_ptr(&ZERO)) },
         // Slice with trailing 0
-        Some(&0) => Cow::Borrowed(CStr::from_bytes_with_nul(slice)
-            .map_err(|source| Error::CreateCStringWithTrailing { source })?),
+        Some(&0) => Cow::Borrowed(
+            CStr::from_bytes_with_nul(slice)
+                .map_err(|source| Error::CreateCStringWithTrailing { source })?,
+        ),
         // Slice with no trailing 0
-        Some(_) => Cow::Owned(CString::new(slice)
-            .map_err(|source| Error::CreateCString { source })?),
+        Some(_) => {
+            Cow::Owned(CString::new(slice).map_err(|source| Error::CreateCString { source })?)
+        }
     })
 }
 
diff --git a/tests/constants.rs b/tests/constants.rs
index ad910c4..6ae5a84 100644
--- a/tests/constants.rs
+++ b/tests/constants.rs
@@ -1,5 +1,5 @@
-extern crate libloading;
 extern crate libc;
+extern crate libloading;
 extern crate static_assertions;
 
 #[cfg(all(test, unix))]
diff --git a/tests/functions.rs b/tests/functions.rs
index eef41e6..795f0cf 100644
--- a/tests/functions.rs
+++ b/tests/functions.rs
@@ -148,7 +148,7 @@
 }
 
 #[test]
-// Something about i686-pc-windows-gnu, makes dll initialization code call abort when it is loaded
+// Something about i686-pc-windows-gnu, makes dll initialisation code call abort when it is loaded
 // and unloaded many times. So far it seems like an issue with mingw, not libloading, so ignoring
 // the target. Especially since it is very unlikely to be fixed given the state of support its
 // support.
@@ -193,7 +193,7 @@
     use libloading::os::windows::Library;
     make_helpers();
     unsafe {
-        // SAFE: well-known library without initializers is loaded.
+        // SAFE: well-known library without initialisers is loaded.
         let _lib = Library::new(LIBPATH).unwrap();
         let this = Library::this().expect("this library");
         // SAFE: functions are never called.