#![allow(clippy::module_name_repetitions)]
use crate::tagged_box::TaggedBox;
pub trait TaggableContainer {
type Inner;
fn into_inner(self) -> Self::Inner;
}
pub trait TaggableInner: Sized {
fn into_tagged_box(self) -> TaggedBox<Self>;
fn from_tagged_box(tagged: TaggedBox<Self>) -> Self;
unsafe fn ref_from_tagged_box<F>(tagged: &TaggedBox<Self>, callback: F)
where
F: FnOnce(&Self);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tagged_box;
tagged_box! {
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
struct Container, enum Item {
Int(usize),
Bool(bool),
Float(f32),
}
}
#[test]
fn container_into_inner() {
let int = Container::from(usize::max_value());
assert_eq!(int.into_inner(), Item::Int(usize::max_value()));
let boolean = Container::from(true);
assert_eq!(boolean.into_inner(), Item::Bool(true));
let float = Container::from(core::f32::MAX);
assert_eq!(float.into_inner(), Item::Float(core::f32::MAX));
}
#[test]
fn inner_into_tagged_box() {
assert_eq!(
Item::Int(usize::max_value()),
Container {
value: Item::Int(usize::max_value()).into_tagged_box()
}
.into_inner()
);
assert_eq!(
Item::Bool(false),
Container {
value: Item::Bool(false).into_tagged_box()
}
.into_inner()
);
assert_eq!(
Item::Float(core::f32::MIN),
Container {
value: Item::Float(core::f32::MIN).into_tagged_box()
}
.into_inner()
);
}
#[test]
fn inner_from_tagged_box() {
assert_eq!(
Item::Int(usize::max_value()),
Item::from_tagged_box(Item::Int(usize::max_value()).into_tagged_box())
);
assert_eq!(
Item::Bool(true),
Item::from_tagged_box(Item::Bool(true).into_tagged_box())
);
assert_eq!(
Item::Float(core::f32::MAX),
Item::from_tagged_box(Item::Float(core::f32::MAX).into_tagged_box())
);
}
#[test]
fn inner_ref_from_tagged_box() {
unsafe {
let int = Item::Int(usize::max_value());
let boolean = Item::Bool(false);
let float = Item::Float(core::f32::MIN);
Item::ref_from_tagged_box(&Item::Int(usize::max_value()).into_tagged_box(), |item| {
assert_eq!(item, &int);
assert_ne!(item, &boolean);
assert_ne!(item, &float);
});
Item::ref_from_tagged_box(&Item::Bool(false).into_tagged_box(), |item| {
assert_eq!(item, &boolean);
assert_ne!(item, &int);
assert_ne!(item, &float);
});
Item::ref_from_tagged_box(&Item::Float(core::f32::MIN).into_tagged_box(), |item| {
assert_eq!(item, &float);
assert_ne!(item, &int);
assert_ne!(item, &boolean);
});
}
}
#[test]
fn wrapped_refs_from_tagged_box() {
let big = Item::Int(10_000).into_tagged_box();
let small = Item::Int(100).into_tagged_box();
unsafe {
Item::ref_from_tagged_box(&big, |big| {
Item::ref_from_tagged_box(&small, |small| {
assert_ne!(big, small);
assert!(big > small);
assert!(small < big);
});
});
}
assert_eq!(Item::from_tagged_box(big), Item::Int(10_000));
assert_eq!(Item::from_tagged_box(small), Item::Int(100));
}
}