adding SliceMeta

no-dual
Avril 4 years ago
parent c5007ad6fa
commit fd8f767077
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -159,6 +159,49 @@ where F: FnOnce(&mut [u8]) -> T
} }
} }
/// Create an accessor method. for a field in a structure.
///
/// The supported accessor types are: `ref`, `mut`, and `move`.
#[macro_export] macro_rules! accessor {
($vis:vis ref $name:ident -> $ty:ty => $internal:ident $(; $comment:literal)?) => {
$(#[doc=$comment])?
#[inline] $vis fn $name(&self) -> &$ty {
&self.$internal
}
};
($vis:vis ref $name:ident -> $ty:ty => $internal:tt $(; $comment:literal)?) => {
$(#[doc=$comment])?
#[inline] $vis fn $name(&self) -> &$ty {
&self.$internal
}
};
($vis:vis mut $name:ident -> $ty:ty => $internal:ident $(; $comment:literal)?) => {
$(#[doc=$comment])?
#[inline] $vis fn $name(&self) -> &mut $ty {
&mut self.$internal
}
};
($vis:vis mut $name:ident -> $ty:ty => $internal:tt $(; $comment:literal)?) => {
$(#[doc=$comment])?
#[inline] $vis fn $name(&self) -> &mut $ty {
&mut self.$internal
}
};
($vis:vis move $name:ident -> $ty:ty => $internal:ident $(; $comment:literal)?) => {
$(#[doc=$comment])?
#[inline] $vis fn $name(&self) -> $ty {
self.$internal
}
};
($vis:vis move $name:ident -> $ty:ty => $internal:tt $(; $comment:literal)?) => {
$(#[doc=$comment])?
#[inline] $vis fn $name(&self) -> $ty {
self.$internal
}
};
}
pub mod bytes pub mod bytes
{ {
use super::*; use super::*;
@ -170,3 +213,5 @@ pub mod bytes
} }
} }
} }
pub mod slice;

@ -0,0 +1,182 @@
//! Slice tools
use super::*;
use std::marker::PhantomData;
use std::{slice, ptr, mem};
/// For an untyped `SliceMeta<T>`, this is the default `T`.
///
/// `SliceMeta<AnySlice>` is slice metadata that can **unsafely** coerce to slice metadata for any other type.
/// And any `SliceMeta<T>` can **safely** coerce to `SliceMeta<AnySlice>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)]
pub enum AnySlice { }
/// Metadata of a slice `[T]`.
///
/// # Usage
/// This may or may not point to a valid slice. The address may or may not be null.
/// It is intended for comparing pointer-identity of slice fat pointers.
///
/// # Layout
/// This type has a `repr(C)` memory layout of 2 `size_t`s and is safe for FFI use.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Default)]
#[repr(C)]
pub struct SliceMeta<T = AnySlice>
{
/// The address of the first element of the slice
/// # Notes
/// This can be `0` if the `SliceMeta` is initialised to `Default`, but a null-pointing `SliceMeta` is never safe to construct a real slice out of. The address may also be dangling, if the slice is 0 sized.
pub address: usize,
/// The length of the slice.
pub length: usize,
_slice: PhantomData<[T]>,
}
impl SliceMeta<AnySlice>
{
/// Create a new `SliceMeta` representing this slice of any type.
pub fn from_slice_any<T>(slice: &[T]) -> Self
{
Self::new(slice.as_ptr() as usize, slice.len())
}
/// Is this instance referring to the data and length of this slice (regardless of type)?
pub fn is_slice_any<T>(&self, other: &[T]) -> bool
{
*self == Self::from_slice_any(other)
}
}
impl<T> SliceMeta<T>
{
#[inline(always)] fn assert_not_null(&self)
{
#[inline(never)] fn panic_null()
{
panic!("Address cannot be null");
}
if self.address == 0 {
panic_null();
}
}
/// Remove the type information from this instance.
#[inline(always)] pub const fn as_any(&self) -> SliceMeta<AnySlice>
{
SliceMeta {
address: self.address,
length: self.length,
_slice: PhantomData,
}
}
/// Is this slice metadata instance pointing to a null address? (i.e. undefined/empty).
#[inline(always)] pub const fn is_null(self) -> bool{
self.address == 0
}
/// The size in bytes of the slice pointed to at `address`.
#[inline] pub const fn length_bytes(self) -> usize
{
mem::size_of::<T>() * self.length
}
/// Is this instance referring to the data and length of this slice?
pub fn is_slice(&self, other: &[T]) -> bool
{
self.as_any() == Self::from_slice(other).as_any()
}
/// Create a new `SliceMeta` representing this slice.
#[inline] pub fn from_slice(slice: &[T]) -> Self
{
Self::new(slice.as_ptr() as usize, slice.len())
}
/// Create a new `SliceMeta` with these parameters.
#[inline] pub const fn new(address: usize, length: usize) -> Self
{
Self {
address,
length,
_slice: PhantomData,
}
}
/// Returns `address` as a raw pointer.
///
/// The pointer will be null if `address` is 0.
#[inline(always)] pub const fn as_ptr(self) -> *const T
{
self.address as *const T
}
/// Returns `address` as a mutable raw pointer.
///
/// The pointer will be null if `address` is 0.
#[inline(always)] pub const fn as_mut_ptr(self) -> *mut T
{
self.address as *mut T
}
/// Create a raw slice from the metadata.
///
/// # Panics
/// If `address` is 0.
#[inline] pub fn as_raw_slice(self) -> *const [T]
{
self.assert_not_null();
ptr::slice_from_raw_parts(self.address as *const T, self.length)
}
/// Create a mutable raw slice from the metadata.
///
/// # Panics
/// If `address` is 0.
#[inline] pub fn as_raw_slice_mut(self) -> *mut [T]
{
self.assert_not_null();
ptr::slice_from_raw_parts_mut(self.address as *mut T, self.length)
}
/// Create a slice from the metadata.
///
/// This operation is unsafe.
/// # Safety
/// * `address` must be properly aligned and point to a valid `length` number of elements of `T`. If `length` is 0, the pointer can be dangling, but it cannot be null.
/// * Rust's slice requirements must be met using this metadata as a real slice.
/// * The lifetime chosen for the returned slice must be valid for the data pointed to by `address`.
///
/// # Panics
/// If `address` is 0.
#[inline] pub unsafe fn as_slice<'a>(self) -> &'a [T]
{
self.assert_not_null();
slice::from_raw_parts(self.address as *const T, self.length)
}
/// Create a mutable slice from the metadata.
///
/// This operation is unsafe.
/// # Safety
/// * `address` must be properly aligned and point to a valid `length` number of elements of `T`. If `length` is 0, the pointer can be dangling, but it cannot be null.
/// * Rust's slice requirements must be met using this metadata as a real slice.
/// * The lifetime chosen for the returned slice must be valid for the data pointed to by `address`.
///
/// # Panics
/// If `address` is 0.
#[inline] pub unsafe fn as_slice_mut<'a>(self) -> &'a mut [T]
{
self.assert_not_null();
slice::from_raw_parts_mut(self.address as *mut T, self.length)
}
//accessor!(pub move address -> usize => 0; "The address of the first element of the slice\n\n# Notes\nThis can be `0` if the `SliceMeta` is initialised to `Default`, but a null-pointing `SliceMeta` is never safe to construct a real slice out of. The address may also be dangling, if the slice is 0 sized.");
}

@ -20,7 +20,7 @@ mod stream;
pub use stream::{ pub use stream::{
AsyncStream, AsyncStream,
EncryptedStream, // EncryptedStream,
WriteHalf, WriteHalf,
ReadHalf, ReadHalf,
}; };

Loading…
Cancel
Save