zig-std 0.1.0

Bindings to Zig `std`, with optional Rust `std` features
use core::{ ptr, slice };

#[repr(C)]
pub struct ReprCSlice<T> {
	// mut ptr so T is invariant
	ptr: *mut T,
	len: usize
}

impl<T> ReprCSlice<T> {
	#[inline]
	pub fn null() -> Self {
		ReprCSlice { ptr: ptr::null_mut(), len: 0 }
	}
}

impl<T> Clone for ReprCSlice<T> {
	#[inline]
	fn clone(&self) -> Self {
		*self
	}
}

impl<T> Copy for ReprCSlice<T> {}

impl<T> From<&T> for ReprCSlice<T> {
	#[inline]
	fn from(value: &T) -> Self {
		let ptr = (&raw const *value).cast_mut();
		let len = 1;
		ReprCSlice { ptr, len }
	}
}

impl<T> From<&[T]> for ReprCSlice<T> {
	#[inline]
	fn from(value: &[T]) -> Self {
		let ptr = value.as_ptr().cast_mut();
		let len = value.len();
		ReprCSlice { ptr, len }
	}
}

impl<T> From<&mut T> for ReprCSlice<T> {
	#[inline]
	fn from(value: &mut T) -> Self {
		let ptr = &raw mut *value;
		let len = 1;
		ReprCSlice { ptr, len }
	}
}

impl<T> From<&mut [T]> for ReprCSlice<T> {
	#[inline]
	fn from(value: &mut [T]) -> Self {
		let ptr = value.as_mut_ptr();
		let len = value.len();
		ReprCSlice { ptr, len }
	}
}

impl<'h, T> From<ReprCSlice<T>> for &'h [T] {
	#[inline]
	fn from(value: ReprCSlice<T>) -> &'h [T] {
		unsafe { slice::from_raw_parts(value.ptr, value.len) }
	}
}

impl<'h, T> From<ReprCSlice<T>> for &'h mut [T] {
	#[inline]
	fn from(value: ReprCSlice<T>) -> &'h mut [T] {
		unsafe { slice::from_raw_parts_mut(value.ptr, value.len) }
	}
}

/// # Example
///
/// ```ignore
/// sys! {
///    pub fn extern_fn();
///    pub fn extern_fn_2();
///    pub fn extern_fn_247();
/// }
/// ```
macro_rules! sys {
	{ @inside_module $($tt:tt)* } => {
		use super::*;
		unsafe extern "C" {
			$($tt)*
		}
	};

	{ $($tt:tt)* } => {
		cfg_select! {
			feature = "unstable-sys" => {
				#[cfg_attr(
					docsrs,
					doc(cfg(feature = "unstable-sys"))
				)]
				#[allow(
					dead_code,
					unused_imports,
					reason = "macro generated code"
				)]
				pub mod sys {
					$crate::util::sys! { @inside_module $($tt)* }
				}
			}
			_ => {
				#[allow(
					dead_code,
					unused_imports,
					reason = "macro generated code"
				)]
				mod sys {
					$crate::util::sys! { @inside_module $($tt)* }
				}
			}
		}
	};
}
pub(crate) use sys;

// size/align assertions
const _: () = {
	assert!(size_of::<ReprCSlice<u8>>() == 2 * size_of::<usize>());
	assert!(align_of::<ReprCSlice<u8>>() == align_of::<usize>());
	assert!(size_of::<ReprCSlice<u128>>() == 2 * size_of::<usize>());
	assert!(align_of::<ReprCSlice<u128>>() == align_of::<usize>());
};