#![deny(missing_docs)]
#![no_std]
use core::mem;
use core::ops;
macro_rules! impl_byte_size {
( $name:ident , $byte_size:expr ) => {
impl ByteSize for $name {
const BYTE_SIZE: Bytes = Bytes($byte_size);
}
}
}
macro_rules! impl_from_bytes {
( $name:ident ) => {
impl From<$name> for Bytes {
#[inline]
fn from(x: $name) -> Bytes {
Bytes(x.0 * $name::BYTE_SIZE.0)
}
}
}
}
macro_rules! impl_ops {
( $name:ident ) => {
impl<T: Into<Bytes>> RoundUpTo<$name> for T {
fn round_up_to(self) -> $name {
let bytes: Bytes = self.into();
$name(round_up_to(bytes.0, $name::BYTE_SIZE.0))
}
}
impl<T: Into<Self>> ops::Add<T> for $name {
type Output = Self;
#[inline]
fn add(self, rhs: T) -> Self {
$name(self.0 + rhs.into().0)
}
}
impl<T: Into<Self>> ops::Sub<T> for $name {
type Output = Self;
#[inline]
fn sub(self, rhs: T) -> Self {
$name(self.0 - rhs.into().0)
}
}
impl<T: Into<Self>> ops::Mul<T> for $name {
type Output = Self;
#[inline]
fn mul(self, rhs: T) -> Self {
$name(self.0 * rhs.into().0)
}
}
impl<T: Into<Self>> ops::Div<T> for $name {
type Output = Self;
#[inline]
fn div(self, rhs: T) -> Self {
$name(self.0 / rhs.into().0)
}
}
}
}
macro_rules! define_newtype {
(
$( #[$attr:meta] )*
newtype $name:ident = $t:ty;
) => {
$( #[$attr] )*
pub struct $name(pub $t);
}
}
macro_rules! define_unit {
(
$( #[$attr:meta] )*
newtype $name:ident is bytes = $byte_size:expr;
) => {
define_newtype! {
$( #[$attr] )*
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
newtype $name = usize;
}
impl_byte_size!($name, $byte_size);
impl_from_bytes!($name);
impl_ops!($name);
}
}
#[inline]
pub fn size_of<T>() -> Bytes {
Bytes(mem::size_of::<T>())
}
pub trait RoundUpTo<T> {
fn round_up_to(self) -> T;
}
#[inline]
pub(crate) fn round_up_to(n: usize, divisor: usize) -> usize {
(n + divisor - 1) / divisor
}
pub trait ByteSize {
const BYTE_SIZE: Bytes;
}
define_newtype! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
newtype Bytes = usize;
}
impl_byte_size!(Bytes, 1);
impl_ops!(Bytes);
pub mod wasm32 {
use super::*;
use core::ops;
define_unit! {
newtype Words is bytes = 4;
}
define_unit! {
newtype Pages is bytes = 65536;
}
}
#[cfg(target_arch = "wasm32")]
pub mod target {
pub use wasm32::*;
}
#[cfg(not(target_arch = "wasm32"))]
pub mod target {
use super::*;
use core::mem;
use core::ops;
define_unit! {
newtype Words is bytes = mem::size_of::<usize>();
}
define_unit! {
newtype Pages is bytes = 4096;
}
}
pub use target::*;