use godot_ffi as sys;
use sys::interface_fn;
use crate::builtin::StringName;
use crate::meta::ClassId;
pub struct IntegerConstant {
name: StringName,
value: i64,
}
impl IntegerConstant {
pub fn new<T>(name: &str, value: T) -> Self
where
T: TryInto<i64> + Copy + std::fmt::Debug,
{
Self {
name: StringName::from(name),
value: value.try_into().ok().unwrap_or_else(|| {
panic!("exported constant `{value:?}` must be representable as `i64`")
}),
}
}
fn register(&self, class_name: ClassId, enum_name: &StringName, is_bitfield: bool) {
unsafe {
interface_fn!(classdb_register_extension_class_integer_constant)(
sys::get_library(),
class_name.string_sys(),
enum_name.string_sys(),
self.name.string_sys(),
self.value,
sys::conv::bool_to_sys(is_bitfield),
);
}
}
}
pub enum ConstantKind {
Integer(IntegerConstant),
Enum {
name: StringName,
enumerators: Vec<IntegerConstant>,
},
Bitfield {
name: StringName,
flags: Vec<IntegerConstant>,
},
}
impl ConstantKind {
fn register(&self, class_name: ClassId) {
match self {
ConstantKind::Integer(integer) => {
integer.register(class_name, &StringName::default(), false)
}
ConstantKind::Enum { name, enumerators } => {
for enumerator in enumerators.iter() {
enumerator.register(class_name, name, false)
}
}
ConstantKind::Bitfield { name, flags } => {
for flag in flags.iter() {
flag.register(class_name, name, true)
}
}
}
}
}
pub struct ExportConstant {
class_name: ClassId,
kind: ConstantKind,
}
impl ExportConstant {
pub fn new(class_name: ClassId, kind: ConstantKind) -> Self {
Self { class_name, kind }
}
pub fn register(&self) {
self.kind.register(self.class_name)
}
}