use std::{
convert::Infallible,
mem,
path::{Path, PathBuf},
sync::atomic,
};
#[allow(unused_imports)]
use core_extensions::SelfOps;
use libloading::{Library as LibLoadingLibrary, Symbol as LLSymbol};
use crate::{
abi_stability::stable_abi_trait::StableAbi,
globals::{self, Globals},
marker_type::ErasedPrefix,
prefix_type::{PrefixRef, PrefixRefTrait},
sabi_types::{LateStaticRef, NulStr, VersionNumber, VersionStrings},
std_types::{RResult, RStr},
type_layout::TypeLayout,
};
pub mod c_abi_testing;
pub mod development_utils;
mod errors;
mod lib_header;
#[cfg(test)]
mod library_tests;
mod raw_library;
mod root_mod_trait;
#[doc(no_inline)]
pub use self::c_abi_testing::{CAbiTestingFns, C_ABI_TESTING_FNS};
pub use self::{
errors::{IntoRootModuleResult, LibraryError, RootModuleError},
lib_header::{AbiHeader, AbiHeaderRef, LibHeader},
raw_library::RawLibrary,
root_mod_trait::{
abi_header_from_path, abi_header_from_raw_library, lib_header_from_path,
lib_header_from_raw_library, RootModule, RootModuleConsts,
},
};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum LibrarySuffix {
NoSuffix,
Suffix,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum LibraryPath<'a> {
FullPath(&'a Path),
Directory(&'a Path),
}
pub enum CheckTypeLayout {
Yes,
No,
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, StableAbi)]
pub enum IsLayoutChecked {
Yes(&'static TypeLayout),
No,
}
impl IsLayoutChecked {
pub const fn into_option(self) -> Option<&'static TypeLayout> {
match self {
IsLayoutChecked::Yes(x) => Some(x),
IsLayoutChecked::No => None,
}
}
}
pub type RootModuleResult = RResult<PrefixRef<ErasedPrefix>, RootModuleError>;
#[doc(hidden)]
pub struct RootModuleStatics<M> {
root_mod: LateStaticRef<M>,
raw_lib: LateStaticRef<&'static RawLibrary>,
}
impl<M> RootModuleStatics<M> {
#[doc(hidden)]
#[inline]
pub const unsafe fn __private_new() -> Self {
Self {
root_mod: LateStaticRef::new(),
raw_lib: LateStaticRef::new(),
}
}
}
#[cfg_attr(
doctest,
doc = r###"
```rust
struct Foo;
impl Foo {
abi_stable::declare_root_module_statics!{Foo}
}
```
```rust
struct Foo;
impl Foo {
abi_stable::declare_root_module_statics!{(Foo)}
}
```
```compile_fail
struct Foo;
impl Foo {
abi_stable::declare_root_module_statics!{Self}
}
```
```compile_fail
struct Foo;
impl Foo {
abi_stable::declare_root_module_statics!{(Self)}
}
```
```compile_fail
struct Foo;
impl Foo {
abi_stable::declare_root_module_statics!{((Self))}
}
```
"###
)]
#[macro_export]
macro_rules! declare_root_module_statics {
( ( $($stuff:tt)* ) ) => (
$crate::declare_root_module_statics!{$($stuff)*}
);
( Self ) => (
compile_error!{"Don't use `Self`, write the full type name"}
);
( $this:ty ) => (
#[inline]
fn root_module_statics()->&'static $crate::library::RootModuleStatics<$this>{
static _ROOT_MOD_STATICS:$crate::library::RootModuleStatics<$this>= unsafe{
$crate::library::RootModuleStatics::__private_new()
};
&_ROOT_MOD_STATICS
}
);
}
abi_stable_derive::__const_mangled_root_module_loader_name! {}
pub const ROOT_MODULE_LOADER_NAME: &str = PRIV_MANGLED_ROOT_MODULE_LOADER_NAME;
pub const ROOT_MODULE_LOADER_NAME_WITH_NUL: &str = PRIV_MANGLED_ROOT_MODULE_LOADER_NAME_NUL;
pub const ROOT_MODULE_LOADER_NAME_NULSTR: NulStr<'_> =
NulStr::from_str(PRIV_MANGLED_ROOT_MODULE_LOADER_NAME_NUL);
#[doc(hidden)]
pub fn __call_root_module_loader<T>(function: fn() -> T) -> RootModuleResult
where
T: IntoRootModuleResult,
{
type TheResult = Result<PrefixRef<ErasedPrefix>, RootModuleError>;
let res = ::std::panic::catch_unwind(|| -> TheResult {
let ret: T::Module = function().into_root_module_result()?;
let _ = <T::Module as RootModule>::load_module_with(|| Ok::<_, Infallible>(ret));
unsafe { ret.to_prefix_ref().cast::<ErasedPrefix>().piped(Ok) }
});
let flattened: TheResult = res.unwrap_or(Err(RootModuleError::Unwound));
RootModuleResult::from(flattened)
}