use core::convert::Infallible;
use facet::Facet;
use facet_core::Opaque;
use facet_reflect::Peek;
use facet_testhelpers::test;
#[derive(Facet)]
#[repr(u8)]
enum SimpleEnum {
Variant,
}
#[test]
fn option_of_enum_niche_optimization() {
let none_value: Option<SimpleEnum> = None;
let peek = Peek::new(&none_value);
let peek_enum = peek.into_enum().unwrap();
assert_eq!(
peek_enum.variant_name_active().unwrap(),
"None",
"Option::None was incorrectly identified as Some"
);
let some_value: Option<SimpleEnum> = Some(SimpleEnum::Variant);
let peek = Peek::new(&some_value);
let peek_enum = peek.into_enum().unwrap();
assert_eq!(
peek_enum.variant_name_active().unwrap(),
"Some",
"Option::Some was incorrectly identified"
);
}
#[derive(Facet)]
#[repr(u8)]
enum DefinitelyNotAnEnum {
#[allow(dead_code)]
Some(u32),
None,
}
#[test]
fn peek_enum() {
let some_value = DefinitelyNotAnEnum::Some(42);
let peek_value = Peek::new(&some_value);
let peek_enum = peek_value.into_enum().unwrap();
let peek_def_not_enum = peek_enum;
assert!(peek_def_not_enum.variant_name_active().unwrap() == "Some");
if peek_def_not_enum.variant_name_active().unwrap() == "Some" {
let inner_value = peek_def_not_enum.field(0).unwrap().unwrap();
let value = *inner_value.get::<u32>().unwrap();
assert_eq!(value, 42);
} else {
panic!("Expected Some variant");
}
let none_value = DefinitelyNotAnEnum::None;
let peek_value = Peek::new(&none_value);
let peek_enum = peek_value.into_enum().unwrap();
let peek_def_not_enum = peek_enum;
assert!(peek_def_not_enum.variant_name_active().unwrap() == "None");
}
#[derive(Facet)]
#[repr(C)]
#[allow(dead_code)]
enum ReprCEnum {
Unit,
Tuple(u32),
Struct { a: u8, b: String },
}
#[test]
fn peek_repr_c_enum() {
let unit_value = ReprCEnum::Unit;
let peek_value = Peek::new(&unit_value);
let peek_enum = peek_value.into_enum().unwrap();
assert!(peek_enum.variant_name_active().unwrap() == "Unit");
let unit_value = ReprCEnum::Tuple(42);
let peek_value = Peek::new(&unit_value);
let peek_enum = peek_value.into_enum().unwrap();
assert!(peek_enum.variant_name_active().unwrap() == "Tuple");
let inner_value = peek_enum.field(0).unwrap().unwrap();
let value = *inner_value.get::<u32>().unwrap();
assert_eq!(value, 42);
let unit_value = ReprCEnum::Struct {
a: 42,
b: "Hello".to_string(),
};
let peek_value = Peek::new(&unit_value);
let peek_enum = peek_value.into_enum().unwrap();
assert!(peek_enum.variant_name_active().unwrap() == "Struct");
let inner_value = peek_enum.field(0).unwrap().unwrap();
let value = *inner_value.get::<u8>().unwrap();
assert_eq!(value, 42);
let inner_value = peek_enum.field_by_name("b").unwrap().unwrap();
let value = inner_value.get::<String>().unwrap();
assert_eq!(value, "Hello");
}
#[test]
fn option_of_zst_no_segfault() {
assert_eq!(
core::mem::size_of::<Option<Opaque<Infallible>>>(),
0,
"Expected Option<Opaque<Infallible>> to be a ZST"
);
let none_value: Option<Opaque<Infallible>> = None;
let peek = Peek::new(&none_value);
let peek_enum = peek.into_enum().unwrap();
assert_eq!(
peek_enum.variant_name_active().unwrap(),
"None",
"Option::None was incorrectly identified"
);
let _ = peek_enum.discriminant();
}