use std::os::raw::c_int;
use crate::ruby;
pub unsafe trait Word: Copy {
const IS_SIGNED: bool;
const ZERO: Self;
}
macro_rules! impl_word {
($signed:expr => $($t:ty)+) => { $(
unsafe impl Word for $t {
const IS_SIGNED: bool = $signed;
const ZERO: Self = 0;
}
)+ }
}
impl_word! { false => usize u128 u64 u32 u16 u8 }
impl_word! { true => isize i128 i64 i32 i16 i8 }
#[derive(Clone, Copy, Debug)]
pub struct Options {
pub(super) byte_order: Order,
pub(super) word_order: Order,
pub(super) is_negative: bool,
}
impl Default for Options {
#[inline]
fn default() -> Self {
Options {
word_order: Order::Least,
#[cfg(target_endian = "little")]
byte_order: Order::Least,
#[cfg(target_endian = "big")]
byte_order: Order::Most,
is_negative: false,
}
}
}
impl Options {
#[inline]
pub(super) fn flags(self) -> c_int {
use ruby::integer_flags::*;
let byte_order = match self.byte_order {
Order::Least => PACK_LSBYTE_FIRST,
Order::Most => PACK_MSBYTE_FIRST,
};
let word_order = match self.word_order {
Order::Least => PACK_LSWORD_FIRST,
Order::Most => PACK_MSWORD_FIRST,
};
word_order | byte_order
}
#[inline]
pub fn big_endian() -> Self {
Self::default().byte_order(Order::Most)
}
#[inline]
pub fn little_endian() -> Self {
Self::default().byte_order(Order::Least)
}
#[cfg_attr(target_endian = "little", doc = "**little-endian**.")]
#[cfg_attr(target_endian = "big", doc = "**big-endian**.")]
#[inline]
#[must_use]
pub fn byte_order(mut self, order: Order) -> Self {
self.byte_order = order;
self
}
#[inline]
#[must_use]
pub fn word_order(mut self, order: Order) -> Self {
self.word_order = order;
self
}
#[inline]
pub fn is_negative(mut self) -> Self {
self.is_negative = true;
self
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Order {
Least,
Most,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Sign {
Zero,
Positive {
did_overflow: bool,
},
Negative {
did_overflow: bool,
},
}
impl Sign {
#[inline]
pub fn did_overflow(&self) -> bool {
use Sign::*;
match *self {
Zero => false,
Positive { did_overflow } |
Negative { did_overflow } => did_overflow,
}
}
#[inline]
pub fn is_negative(&self) -> bool {
if let Sign::Negative { .. } = *self {
true
} else {
false
}
}
}