use super::*;
const_assert! {
::core::mem::size_of::<::libc::uintptr_t>()
==
::core::mem::size_of::<::libc::size_t>()
}
const _: () = { macro_rules! impl_CTypes {
() => (
impl_CTypes! { @pointers }
impl_CTypes! { @zsts }
impl_CTypes! { @floats
unsafe
f32 => "float",
unsafe
f64 => "double",
}
impl_CTypes! { @integers
unsafe
u8 => "uint8",
unsafe
u16 => "uint16",
unsafe
u32 => "uint32",
unsafe
u64 => "uint64",
unsafe
usize => "size",
unsafe
i8 => "int8",
unsafe
i16 => "int16",
unsafe
i32 => "int32",
unsafe
i64 => "int64",
unsafe
isize => "ssize",
}
#[cfg(docs)] impl_CTypes! { @fns (A1) } #[cfg(not(docs))]
impl_CTypes! { @fns
(A9, A8, A7, A6, A5, A4, A3, A2, A1)
}
#[cfg(docs)] impl_CTypes! { @arrays 1 2 } #[cfg(not(docs))]
impl_CTypes! { @arrays
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
26 27 28 29 30 31 32 40 48 50 60 64 70 75 80 90 96 100 125 128 192
200 250 256 300 400 500 512 600 700 750 800 900 1000 1024
}
);
(
@arrays
$($N:tt)*
) => ($(
unsafe
impl<Item : CType> CType
for [Item; $N]
{ __cfg_headers__! {
fn c_short_name_fmt (fmt: &'_ mut fmt::Formatter<'_>)
-> fmt::Result
{
write!(fmt,
concat!("{}_", stringify!($N), "_array"),
Item::c_short_name(),
)
}
fn c_define_self (definer: &'_ mut dyn Definer)
-> io::Result<()>
{
let short_name = &Self::c_short_name().to_string();
definer.define_once(
short_name,
&mut |definer| {
Item::c_define_self(definer)?;
write!(definer.out(),
"typedef struct {{ {}; }} {}_t;\n\n",
Item::c_var(concat!(
"idx[", stringify!($N), "]",
)),
short_name,
)
}
)
}
fn c_var_fmt (
fmt: &'_ mut fmt::Formatter<'_>,
var_name: &'_ str,
) -> fmt::Result
{
write!(fmt,
"{}_t{sep}{}",
Self::c_short_name(),
var_name,
sep = if var_name.is_empty() { "" } else { " " },
)
}
} type OPAQUE_KIND = OpaqueKind::Concrete; }
unsafe
impl<Item : ReprC> ReprC
for [Item; $N]
{
type CLayout = [Item::CLayout; $N];
#[inline]
fn is_valid (it: &'_ Self::CLayout)
-> bool
{
it.iter().all(Item::is_valid)
}
}
)*);
(@fns
(
$(
$An:ident $(,
$Ai:ident)* $(,)?
)?
)
) => (
$(
impl_CTypes! {
@fns
($($Ai ,)*)
}
)?
unsafe
impl<
Ret : CType, $(
$An : CType, $(
$Ai : CType,
)*)?> CType
for Option<unsafe extern "C" fn ($($An, $($Ai ,)*)?) -> Ret>
{ __cfg_headers__! {
fn c_short_name_fmt (fmt: &'_ mut fmt::Formatter<'_>)
-> fmt::Result
{
Ret::c_short_name_fmt(fmt)?; $(
write!(fmt, "_{}", $An::c_short_name())?; $(
write!(fmt, "_{}", $Ai::c_short_name())?; )*)?
fmt.write_str("_fptr")
}
fn c_define_self (definer: &'_ mut dyn Definer)
-> io::Result<()>
{
Ret::c_define_self(definer)?; $(
$An::c_define_self(definer)?; $(
$Ai::c_define_self(definer)?; )*)?
Ok(())
}
fn c_var_fmt (
fmt: &'_ mut fmt::Formatter<'_>,
var_name: &'_ str,
) -> fmt::Result
{
write!(fmt, "{} ", Ret::c_var(""))?;
write!(fmt, "(*{})(", var_name)?;
let _empty = true; $(
let _empty = false;
write!(fmt, "{}", $An::c_var(""))?; $(
write!(fmt, ", {}", $Ai::c_var(""))?; )*)?
if _empty {
fmt.write_str("void")?;
}
fmt.write_str(")")
}
} type OPAQUE_KIND = OpaqueKind::Concrete; }
unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> ReprC
for Option<unsafe extern "C" fn ($($An, $($Ai ,)*)?) -> Ret>
{
type CLayout = Option<
unsafe extern "C"
fn ($($An::CLayout, $($Ai::CLayout ,)*)?) -> Ret::CLayout
>;
#[inline]
fn is_valid (_: &'_ Self::CLayout)
-> bool
{
true
}
}
unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> ReprC
for Option< extern "C" fn ($($An, $($Ai ,)*)?) -> Ret>
{
type CLayout = Option<
unsafe extern "C"
fn ($($An::CLayout, $($Ai::CLayout ,)*)?) -> Ret::CLayout
>;
#[inline]
fn is_valid (_: &'_ Self::CLayout)
-> bool
{
true
}
}
unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> ReprC
for unsafe extern "C" fn ($($An, $($Ai ,)*)?) -> Ret
{
type CLayout = Option<
unsafe extern "C"
fn ($($An::CLayout, $($Ai::CLayout ,)*)?) -> Ret::CLayout
>;
#[inline]
fn is_valid (c_layout: &'_ Self::CLayout)
-> bool
{
c_layout.is_some()
}
}
unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> ReprC
for extern "C" fn ($($An, $($Ai ,)*)?) -> Ret
{
type CLayout = Option<
unsafe extern "C"
fn ($($An::CLayout, $($Ai::CLayout ,)*)?) -> Ret::CLayout
>;
#[inline]
fn is_valid (c_layout: &'_ Self::CLayout)
-> bool
{
c_layout.is_some()
}
}
unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> crate::layout::__HasNiche__
for fn ($($An, $($Ai ,)*)?) -> Ret
where
Self : ReprC,
{
#[inline]
fn is_niche (_: &'_ Self::CLayout)
-> bool
{
unreachable!()
}
}
unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> crate::layout::__HasNiche__
for unsafe fn ($($An, $($Ai ,)*)?) -> Ret
where
Self : ReprC,
{
#[inline]
fn is_niche (_: &'_ Self::CLayout)
-> bool
{
unreachable!()
}
}
);
(@integers
$(
$unsafe:tt
$RustInt:ident => $CInt:literal,
)*
) => ($(
$unsafe
impl CType
for $RustInt
{ __cfg_headers__! {
fn c_short_name_fmt (fmt: &'_ mut fmt::Formatter<'_>)
-> fmt::Result
{
fmt.write_str($CInt)
}
fn c_define_self (definer: &'_ mut dyn Definer)
-> io::Result<()>
{
definer.define_once(
"__int_headers__",
&mut |definer| write!(definer.out(),
concat!(
"\n",
"#include <stddef.h>\n",
"#include <stdint.h>\n",
"\n",
),
),
)
}
fn c_var_fmt (
fmt: &'_ mut fmt::Formatter<'_>,
var_name: &'_ str,
) -> fmt::Result
{
write!(fmt,
concat!($CInt, "_t{sep}{}"),
var_name,
sep = if var_name.is_empty() { "" } else { " " },
)
}
} type OPAQUE_KIND = OpaqueKind::Concrete; }
from_CType_impl_ReprC! { $RustInt }
)*);
(@floats
$(
$unsafe:tt
$fN:ident => $Cty:literal,
)*
) => ($(
$unsafe
impl CType
for $fN
{ __cfg_headers__! {
fn c_short_name_fmt (fmt: &'_ mut fmt::Formatter<'_>)
-> fmt::Result
{
fmt.write_str($Cty)
}
fn c_var_fmt (
fmt: &'_ mut fmt::Formatter<'_>,
var_name: &'_ str,
) -> fmt::Result
{
write!(fmt,
concat!($Cty, "{sep}{}"),
var_name,
sep = if var_name.is_empty() { "" } else { " " },
)
}
} type OPAQUE_KIND = OpaqueKind::Concrete; }
from_CType_impl_ReprC! { $fN }
)*);
(
@pointers
) => (
unsafe
impl<T : CType> CType
for *const T
{ __cfg_headers__! {
fn c_short_name_fmt (fmt: &'_ mut fmt::Formatter<'_>)
-> fmt::Result
{
write!(fmt, "{}_const_ptr", T::c_short_name())
}
fn c_define_self (definer: &'_ mut dyn Definer)
-> io::Result<()>
{
T::c_define_self(definer)
}
fn c_var_fmt (
fmt: &'_ mut fmt::Formatter<'_>,
var_name: &'_ str,
) -> fmt::Result
{
write!(fmt,
"{} const *{sep}{}",
T::c_var(""),
var_name,
sep = if var_name.is_empty() { "" } else { " " },
)
}
} type OPAQUE_KIND = OpaqueKind::Concrete; }
unsafe
impl<T : ReprC> ReprC
for *const T
{
type CLayout = *const T::CLayout;
#[inline]
fn is_valid (_: &'_ Self::CLayout)
-> bool
{
true
}
}
unsafe
impl<T : CType> CType
for *mut T
{ __cfg_headers__! {
fn c_short_name_fmt (fmt: &'_ mut fmt::Formatter<'_>)
-> fmt::Result
{
write!(fmt, "{}_ptr", T::c_short_name())
}
fn c_define_self (definer: &'_ mut dyn Definer)
-> io::Result<()>
{
T::c_define_self(definer)
}
fn c_var_fmt (
fmt: &'_ mut fmt::Formatter<'_>,
var_name: &'_ str,
) -> fmt::Result
{
write!(fmt,
"{} *{sep}{}",
T::c_var(""),
var_name,
sep = if var_name.is_empty() { "" } else { " " },
)
}
} type OPAQUE_KIND = OpaqueKind::Concrete; }
unsafe
impl<T : ReprC> ReprC
for *mut T
{
type CLayout = *mut T::CLayout;
#[inline]
fn is_valid (_: &'_ Self::CLayout)
-> bool
{
true
}
}
);
(
@zsts
) => (
unsafe
impl ReprC
for ()
{
type CLayout = CVoid;
#[inline]
fn is_valid (_: &'_ CVoid)
-> bool
{
panic!("It is a logic error to try and get a ZST from C");
}
}
unsafe
impl<T : ?Sized> ReprC
for PhantomData<T>
{
type CLayout = CVoid;
#[inline]
fn is_valid (_: &'_ CVoid)
-> bool
{
panic!("It is a logic error to try and get a ZST from C");
}
}
);
} impl_CTypes! {} };
macro_rules! impl_ReprC_for {(
$unsafe:tt {
$(
$(@for [$($generics:tt)+])? $T:ty
=> |ref $it:tt : $Layout:ty| $expr:expr
),* $(,)?
}
) => (
$(
$unsafe
impl $(<$($generics)+>)? ReprC
for $T
{
type CLayout = $Layout;
#[inline]
fn is_valid (it: &'_ $Layout)
-> bool
{
let $it = it;
if $expr {
true
} else {
#[cfg(feature = "log")]
::log::error!(
"{:#x?} is not a _valid_ bit pattern for the type `{}`",
unsafe {
::core::slice::from_raw_parts(
<*const _>::cast::<u8>(it),
::core::mem::size_of_val(it),
)
},
::core::any::type_name::<Self>(),
);
false
}
}
}
)*
)}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq)]
#[allow(missing_debug_implementations)]
pub
struct Bool(u8);
unsafe
impl CType
for Bool
{
__cfg_headers__! {
fn c_short_name_fmt (fmt: &'_ mut fmt::Formatter<'_>)
-> fmt::Result
{
fmt.write_str("bool")
}
fn c_define_self (definer: &'_ mut dyn Definer)
-> io::Result<()>
{
definer.define_once(
"bool",
&mut |definer| {
definer.out().write_all(
b"\n#include <stdbool.h>\n\n"
)
},
)
}
fn c_var_fmt (
fmt: &'_ mut fmt::Formatter<'_>,
var_name: &'_ str,
) -> fmt::Result
{
write!(fmt,
"bool{sep}{}",
var_name,
sep = if var_name.is_empty() { "" } else { " " },
)
}
}
type OPAQUE_KIND = OpaqueKind::Concrete;
}
impl_ReprC_for! { unsafe {
bool
=> |ref byte: Bool| (byte.0 & !0b1) == 0
,
@for[T : ReprC]
ptr::NonNull<T>
=> |ref it: *mut T::CLayout| {
it.is_null().not() &&
(*it as usize) % ::core::mem::align_of::<T>() == 0
}
,
@for[T : ReprC]
ptr::NonNullRef<T>
=> |ref it: *const T::CLayout| {
it.is_null().not() &&
(*it as usize) % ::core::mem::align_of::<T>() == 0
}
,
@for[T : ReprC]
ptr::NonNullMut<T>
=> |ref it: *mut T::CLayout| {
it.is_null().not() &&
(*it as usize) % ::core::mem::align_of::<T>() == 0
}
,
@for[T : ReprC]
ptr::NonNullOwned<T>
=> |ref it: *mut T::CLayout| {
it.is_null().not() &&
(*it as usize) % ::core::mem::align_of::<T>() == 0
}
,
@for['a, T : 'a + ReprC]
&'a T
=> |ref it: *const T::CLayout| {
it.is_null().not() &&
(*it as usize) % ::core::mem::align_of::<T>() == 0
}
,
@for['a, T : 'a + ReprC]
&'a mut T
=> |ref it: *mut T::CLayout| {
it.is_null().not() &&
(*it as usize) % ::core::mem::align_of::<T>() == 0
}
,
}}
#[cfg(feature = "out-refs")]
impl_ReprC_for! { unsafe {
@for['out, T : 'out + Sized + ReprC]
Out<'out, T>
=> |ref it: *mut T::CLayout| {
(*it as usize) % ::core::mem::align_of::<T>() == 0
},
}}