use bitflags::bitflags;
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[doc(alias(
"FUNC_NORET", "FUNC_FAR", "FUNC_LIB", "FUNC_STATICDEF", "FUNC_FRAME", "FUNC_USERFAR",
"FUNC_HIDDEN", "FUNC_THUNK", "FUNC_BOTTOMBP", "FUNC_NORET_PENDING", "FUNC_SP_READY",
"FUNC_FUZZY_SP", "FUNC_PROLOG_OK", "FUNC_PURGED_OK", "FUNC_TAIL", "FUNC_LUMINA",
"FUNC_OUTLINE", "FUNC_REANALYZE", "FUNC_UNWIND", "FUNC_CATCH", "FUNC_RESERVED"
))]
pub struct FuncFlags: u64 {
#[doc(alias("FUNC_NORET"))]
const NORET = 0x0000_0001;
#[doc(alias("FUNC_FAR"))]
const FAR = 0x0000_0002;
#[doc(alias("FUNC_LIB"))]
const LIB = 0x0000_0004;
#[doc(alias("FUNC_STATICDEF"))]
const STATICDEF = 0x0000_0008;
#[doc(alias("FUNC_FRAME"))]
const FRAME = 0x0000_0010;
#[doc(alias("FUNC_USERFAR"))]
const USERFAR = 0x0000_0020;
#[doc(alias("FUNC_HIDDEN"))]
const HIDDEN = 0x0000_0040;
#[doc(alias("FUNC_THUNK"))]
const THUNK = 0x0000_0080;
#[doc(alias("FUNC_BOTTOMBP"))]
const BOTTOMBP = 0x0000_0100;
#[doc(alias("FUNC_NORET_PENDING"))]
const NORET_PENDING = 0x0000_0200;
#[doc(alias("FUNC_SP_READY"))]
const SP_READY = 0x0000_0400;
#[doc(alias("FUNC_FUZZY_SP"))]
const FUZZY_SP = 0x0000_0800;
#[doc(alias("FUNC_PROLOG_OK"))]
const PROLOG_OK = 0x0000_1000;
#[doc(alias("FUNC_PURGED_OK"))]
const PURGED_OK = 0x0000_4000;
#[doc(alias("FUNC_TAIL"))]
const TAIL = 0x0000_8000;
#[doc(alias("FUNC_LUMINA"))]
const LUMINA = 0x0001_0000;
#[doc(alias("FUNC_OUTLINE"))]
const OUTLINE = 0x0002_0000;
#[doc(alias("FUNC_REANALYZE"))]
const REANALYZE = 0x0004_0000;
#[doc(alias("FUNC_UNWIND"))]
const UNWIND = 0x0008_0000;
#[doc(alias("FUNC_CATCH"))]
const CATCH = 0x0010_0000;
#[doc(alias("FUNC_RESERVED"))]
const RESERVED = 0x8000_0000_0000_0000;
}
}
#[cfg(test)]
mod tests {
use assert2::assert;
use proptest::prelude::*;
use rstest::rstest;
use super::*;
#[rstest]
#[case::noret(FuncFlags::NORET, 0x0000_0001)]
#[case::far(FuncFlags::FAR, 0x0000_0002)]
#[case::lib(FuncFlags::LIB, 0x0000_0004)]
#[case::staticdef(FuncFlags::STATICDEF, 0x0000_0008)]
#[case::frame(FuncFlags::FRAME, 0x0000_0010)]
#[case::userfar(FuncFlags::USERFAR, 0x0000_0020)]
#[case::hidden(FuncFlags::HIDDEN, 0x0000_0040)]
#[case::thunk(FuncFlags::THUNK, 0x0000_0080)]
#[case::bottombp(FuncFlags::BOTTOMBP, 0x0000_0100)]
#[case::noret_pending(FuncFlags::NORET_PENDING, 0x0000_0200)]
#[case::sp_ready(FuncFlags::SP_READY, 0x0000_0400)]
#[case::fuzzy_sp(FuncFlags::FUZZY_SP, 0x0000_0800)]
#[case::prolog_ok(FuncFlags::PROLOG_OK, 0x0000_1000)]
#[case::purged_ok(FuncFlags::PURGED_OK, 0x0000_4000)]
#[case::tail(FuncFlags::TAIL, 0x0000_8000)]
#[case::lumina(FuncFlags::LUMINA, 0x0001_0000)]
#[case::outline(FuncFlags::OUTLINE, 0x0002_0000)]
#[case::reanalyze(FuncFlags::REANALYZE, 0x0004_0000)]
#[case::unwind(FuncFlags::UNWIND, 0x0008_0000)]
#[case::catch(FuncFlags::CATCH, 0x0010_0000)]
#[case::reserved(FuncFlags::RESERVED, 0x8000_0000_0000_0000)]
fn flags_pin_the_raw_sdk_values(#[case] flag: FuncFlags, #[case] raw: u64) {
assert!(flag.bits() == raw);
}
proptest! {
#[test]
fn from_bits_retain_round_trips_every_bit_pattern(raw: u64) {
prop_assert_eq!(FuncFlags::from_bits_retain(raw).bits(), raw);
}
#[test]
fn union_and_intersection_are_raw_bitwise_ops(a: u64, b: u64) {
let (fa, fb) = (FuncFlags::from_bits_retain(a), FuncFlags::from_bits_retain(b));
prop_assert_eq!((fa | fb).bits(), a | b);
prop_assert_eq!((fa & fb).bits(), a & b);
}
#[test]
fn complement_truncates_to_the_known_flag_mask(a: u64) {
let fa = FuncFlags::from_bits_retain(a);
prop_assert_eq!((!fa).bits(), !a & FuncFlags::all().bits());
}
}
}