use crate::numeric_id::NumericId;
use crate::Value;
use super::BaseValue;
macro_rules! impl_small_base_value {
($ty:ty) => {
impl BaseValue for $ty {
const MAY_UNBOX: bool = true;
fn try_unbox(val: Value) -> Option<Self> {
Some(val.rep() as $ty)
}
fn try_box(&self) -> Option<Value> {
Some(Value::new(*self as u32))
}
}
};
($ty:ty, $($rest:ty),+) => {
impl_small_base_value!($ty);
impl_small_base_value!($($rest),+);
};
}
impl_small_base_value!(u8, u16, u32, i8, i16, i32);
impl BaseValue for bool {
const MAY_UNBOX: bool = true;
fn try_unbox(val: Value) -> Option<Self> {
Some(val.rep() != 0)
}
fn try_box(&self) -> Option<Value> {
Some(Value::new(if *self { 1 } else { 0 }))
}
}
impl BaseValue for () {
const MAY_UNBOX: bool = true;
fn try_unbox(_val: Value) -> Option<Self> {
Some(())
}
fn try_box(&self) -> Option<Value> {
Some(Value::new(0))
}
}
const VAL_BITS: u32 = std::mem::size_of::<Value>() as u32 * 8;
const VAL_MASK: u32 = 1 << (VAL_BITS - 1);
macro_rules! impl_medium_base_value {
($ty:ty) => {
impl BaseValue for $ty {
const MAY_UNBOX: bool = true;
fn try_box(&self) -> Option<Value> {
if *self & (VAL_MASK-1) as $ty == *self {
Some(Value::new(*self as u32))
} else {
None
}
}
fn try_unbox(val: Value) -> Option<Self> {
let top_bit_clear = val.rep() & VAL_MASK == 0;
if top_bit_clear {
Some(val.rep() as $ty)
} else {
None
}
}
}
};
($ty:ty, $($rest:ty),+) => {
impl_medium_base_value!($ty);
impl_medium_base_value!($($rest),+);
};
}
impl_medium_base_value!(u64, i64, usize, isize);