use irys::*;
use std::any::Any;
use std::fmt;
trait Resettable: Send + Sync {
fn reset(&mut self);
fn value(&self) -> String;
}
struct DisplayCap;
impl Capability for DisplayCap { type Handle = dyn fmt::Display; }
struct DebugCap;
impl Capability for DebugCap { type Handle = dyn fmt::Debug; }
struct ResettableCap;
impl Capability for ResettableCap { type Handle = dyn Resettable; }
register_capability! { slot: 0, cap: DisplayCap, trait_bound: fmt::Display }
register_capability! { slot: 1, cap: DebugCap, trait_bound: fmt::Debug }
register_capability! { slot: 2, cap: ResettableCap, trait_bound: Resettable }
trait DynCloneAny: Send + Sync {
fn clone_boxed(&self) -> Box<dyn Any + Send + Sync>;
}
impl<T: Clone + Send + Sync + 'static> DynCloneAny for T {
fn clone_boxed(&self) -> Box<dyn Any + Send + Sync> { Box::new(self.clone()) }
}
struct CloneCap;
impl Capability for CloneCap { type Handle = dyn DynCloneAny; }
register_capability! { slot: 3, cap: CloneCap, trait_bound: DynCloneAny }
#[derive(Debug, Clone)]
struct FullType { name: String, value: i32 }
impl fmt::Display for FullType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}={}", self.name, self.value)
}
}
impl Resettable for FullType {
fn reset(&mut self) { self.value = 0; }
fn value(&self) -> String { format!("value={}", self.value) }
}
struct OpaqueType;
#[test]
fn test_has_and_capability_count() {
let envelope = reflect!(FullType { name: "x".into(), value: 1 });
assert!(envelope.has::<DisplayCap>());
assert!(envelope.has::<DebugCap>());
assert!(envelope.has::<ResettableCap>());
assert!(envelope.has::<CloneCap>());
assert_eq!(envelope.capability_count(), 4);
let opaque = reflect!(OpaqueType);
assert!(!opaque.has::<DisplayCap>());
assert_eq!(opaque.capability_count(), 0);
}
#[test]
fn test_get_trait_objects() {
let envelope = reflect!(FullType { name: "hello".into(), value: 7 });
let display = envelope.get::<DisplayCap>().unwrap();
assert_eq!(format!("{}", display), "hello=7");
let debug = envelope.get::<DebugCap>().unwrap();
assert!(format!("{:?}", debug).contains("hello"));
assert!(envelope.get::<ResettableCap>().unwrap().value().contains("7"));
assert!(reflect!(OpaqueType).get::<DisplayCap>().is_none());
}
#[test]
fn test_get_mut() {
let mut envelope = reflect!(FullType { name: "x".into(), value: 42 });
envelope.get_mut::<ResettableCap>().unwrap().reset();
assert_eq!(envelope.get::<ResettableCap>().unwrap().value(), "value=0");
}
#[test]
fn test_data_and_into_data() {
let envelope = reflect!(FullType { name: "owned".into(), value: 55 });
assert_eq!(envelope.data::<FullType>().unwrap().value, 55);
assert!(envelope.data::<OpaqueType>().is_none());
let data = envelope.into_data::<FullType>().unwrap();
assert_eq!(data.name, "owned");
}
#[test]
fn test_reflect_ref() {
let value = FullType { name: "alive".into(), value: 10 };
let envelope_ref = reflect_ref!(&value);
assert!(envelope_ref.has::<DisplayCap>());
let display = envelope_ref.get::<DisplayCap>().unwrap();
assert_eq!(format!("{}", display), "alive=10");
assert_eq!(value.value, 10); }
#[test]
fn test_reflect_mut() {
let mut value = FullType { name: "mut".into(), value: 99 };
{
let mut envelope_mut = reflect_mut!(&mut value);
assert!(envelope_mut.has::<ResettableCap>());
envelope_mut.get_mut::<ResettableCap>().unwrap().reset();
}
assert_eq!(value.value, 0); }
#[test]
fn test_as_ref_as_mut_conversions() {
let mut envelope = reflect!(FullType { name: "conv".into(), value: 33 });
let r = envelope.as_ref();
assert_eq!(format!("{}", r.get::<DisplayCap>().unwrap()), "conv=33");
{
let mut m = envelope.as_mut();
m.get_mut::<ResettableCap>().unwrap().reset();
}
assert_eq!(envelope.data::<FullType>().unwrap().value, 0);
}
#[test]
fn test_custom_registry_and_isolation() {
struct RegA;
struct RegB;
struct CapA;
impl Capability for CapA { type Handle = dyn fmt::Display; }
struct CapB;
impl Capability for CapB { type Handle = dyn fmt::Debug; }
register_capability! { registry: RegA, slot: 0, cap: CapA, trait_bound: fmt::Display }
register_capability! { registry: RegB, slot: 0, cap: CapB, trait_bound: fmt::Debug }
let env = reflect!(FullType { name: "x".into(), value: 1 }, [{ registry: RegA, slots: 0..1 }]);
assert!(env.has::<CapA>());
assert!(!env.has::<CapB>());
let env = reflect!(FullType { name: "x".into(), value: 1 }, [
{ registry: RegA, slots: 0..1 },
{ registry: RegB, slots: 0..1 },
]);
assert!(env.has::<CapA>());
assert!(env.has::<CapB>());
}
#[test]
fn test_slot_range_controls_detection() {
let env = reflect!(FullType { name: "x".into(), value: 0 }, [
{ registry: DefaultRegistry, slots: 0..2 },
]);
assert!(env.has::<DisplayCap>()); assert!(env.has::<DebugCap>()); assert!(!env.has::<ResettableCap>()); }
#[test]
fn test_clone_envelope_via_caps_from_raw() {
let envelope = reflect!(FullType { name: "clone".into(), value: 77 });
let cloned = envelope.get::<CloneCap>().unwrap().clone_boxed();
let cloned_env = Envelope::from_raw(cloned, envelope.caps().clone());
assert_eq!(format!("{}", cloned_env.get::<DisplayCap>().unwrap()), "clone=77");
assert_eq!(cloned_env.capability_count(), envelope.capability_count());
}
#[test]
fn test_mismatched_map_returns_none() {
let envelope = reflect!(FullType { name: "a".into(), value: 1 });
let wrong_data: Box<dyn Any + Send + Sync> = Box::new(42u64);
let mismatched = Envelope::from_raw(wrong_data, envelope.caps().clone());
assert!(mismatched.has::<DisplayCap>()); assert!(mismatched.get::<DisplayCap>().is_none()); }