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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
// devela::mem::size::byte
//
//! Functionality related to byte sizes.
//
use crate::code::iif;
impl<T> ByteSized for T {}
/// Type size information in bytes.
///
/// This trait is automatically implemented for every `Sized` type.
// (this allows to have associated constants depending on Self)
pub trait ByteSized: Sized {
/// The alignment of this type in bytes.
const BYTE_ALIGN: usize = align_of::<Self>();
/// The size of this type in bytes.
const BYTE_SIZE: usize = size_of::<Self>();
/// The size of a pointer in bytes, for the current platform.
const PTR_BYTES: usize = size_of::<usize>();
/// The size of a pointer in bits, for the current platform.
const PTR_BITS: usize = usize::BITS as usize;
/// True if the system's architecture is little-endian.
const LITTLE_ENDIAN: bool = cfg!(target_endian = "little");
/// True if the system's architecture is big-endian.
const BIG_ENDIAN: bool = cfg!(target_endian = "big");
/// Returns the alignment of this type in bytes.
#[inline]
fn byte_align(&self) -> usize {
align_of_val(self)
}
/// Returns the size of this type in bytes.
///
/// Ignores any allocated resources in the heap.
#[inline]
fn byte_size(&self) -> usize {
size_of_val(self)
}
/// Returns the size ratio between [`PTR_BYTES`][Self#associatedconstant.PTR_BYTES]
/// and [`BYTE_SIZE`][Self#associatedconstant.BYTE_SIZE].
///
/// For example: the ratio will be (1, 1) if both sizes are the same,
/// (2, 1) if a pointer is double the byte size, and (1, 2) if a pointer is
/// half the byte size.
///
/// # Examples
/// ```
/// use devela::mem::ByteSized;
///
/// assert_eq![().ptr_size_ratio(), [1, 0]];
/// assert_eq![1_usize.ptr_size_ratio(), [1, 1]];
/// assert_eq!["slice".ptr_size_ratio(), [1, 2]];
/// assert_eq![String::from("hello").ptr_size_ratio(), [1, 3]];
///
/// #[cfg(target_pointer_width = "64")]
/// {
/// assert_eq![0_u8.ptr_size_ratio(), [8, 1]];
/// assert_eq![0_u16.ptr_size_ratio(), [4, 1]];
/// assert_eq![0_u32.ptr_size_ratio(), [2, 1]];
/// assert_eq![0_u64.ptr_size_ratio(), [1, 1]];
/// assert_eq![0_u128.ptr_size_ratio(), [1, 2]];
/// assert_eq!['c'.ptr_size_ratio(), [2, 1]];
/// assert_eq!["slice".ptr_size_ratio(), [1, 2]];
/// }
/// ```
///
/// For the `const` version see [`ptr_size_ratio`].
#[inline]
fn ptr_size_ratio(&self) -> [usize; 2] {
ptr_size_ratio(Self::BYTE_SIZE)
}
}
/// Returns the ratio of a `usize` in respect to `other_size`.
///
/// For example: the ratio will be `(1, 1)` if both sizes are equal, `(2, 1)`
/// if the pointer size is double the other size, and `(1, 2)` if is is half
/// the other byte size.
///
/// # Examples
/// ```
/// use devela::mem::ptr_size_ratio;
///
/// assert_eq![ptr_size_ratio(0), [1, 0]];
/// assert_eq![ptr_size_ratio(size_of::<usize>()), [1, 1]];
/// assert_eq![ptr_size_ratio(size_of::<&str>()), [1, 2]];
/// assert_eq![ptr_size_ratio(size_of::<String>()), [1, 3]];
///
/// #[cfg(target_pointer_width = "64")]
/// assert_eq![ptr_size_ratio(size_of::<char>()), [2,1]];
/// ```
///
/// Note that when `other_size == 0` it returns `(1, 0)` which is an invalid ratio.
///
#[inline]
#[allow(dead_code)]
pub const fn ptr_size_ratio(other_size: usize) -> [usize; 2] {
#[inline]
const fn gcd(m: usize, n: usize) -> usize {
iif![n == 0; m; gcd(n, m % n)]
}
let g = gcd(size_of::<usize>(), other_size);
[size_of::<usize>() / g, other_size / g]
}