use crate::core::*;
use crate::sys;
use core::ffi::c_char;
use core::mem::ManuallyDrop;
#[cfg(feature = "std")]
extern crate std;
extern crate alloc;
use alloc::format;
use alloc::{string::String, vec::Vec};
pub struct MetricBuilder<'a> {
world: WorldRef<'a>,
desc: sys::ecs_metric_desc_t,
created: bool,
str_ptrs_to_free: Vec<ManuallyDrop<String>>,
}
impl Drop for MetricBuilder<'_> {
fn drop(&mut self) {
if !self.created {
unsafe {
sys::ecs_metric_init(self.world_ptr_mut(), &self.desc);
}
}
for s in self.str_ptrs_to_free.iter_mut() {
unsafe { ManuallyDrop::drop(s) };
}
self.str_ptrs_to_free.clear();
}
}
impl<'a> MetricBuilder<'a> {
pub(crate) fn new(world: &'a World, entity: Entity) -> Self {
Self {
world: world.world(),
desc: sys::ecs_metric_desc_t {
entity: *entity,
..Default::default()
},
created: false,
str_ptrs_to_free: Vec::new(),
}
}
pub fn member(&mut self, e: impl IntoEntity) -> &mut Self {
self.desc.member = *e.into_entity(self.world);
self
}
pub fn member_named(&mut self, name: &str) -> &mut Self {
let mut member_id: Entity = Entity::null();
if self.desc.id != 0 {
let type_id = unsafe { sys::ecs_get_typeid(self.world_ptr_mut(), self.desc.id) };
if type_id != 0 {
let ent = EntityView::new_from(self.world(), type_id);
member_id = ent.try_lookup(name).map_or(Entity::null(), |e| *e);
}
} else {
member_id = self.world().try_lookup(name).map_or(Entity::null(), |e| *e);
}
if member_id == 0 {
ecs_assert!(
member_id != 0,
FlecsErrorCode::InvalidParameter,
"member '{}' not found",
name
);
}
self.member(member_id)
}
pub fn member_named_type<T>(&mut self, name: &str) -> &mut Self
where
T: ComponentId,
{
let id = T::entity_id(self.world());
let ent = EntityView::new_from(self.world(), id);
let m = ent.try_lookup(name);
if m.is_none() {
ecs_assert!(
m.is_some(),
FlecsErrorCode::InvalidParameter,
"member '{}' not found in type '{}'",
name,
core::any::type_name::<T>()
);
return self;
}
self.member(m.unwrap())
}
pub fn dotmember_named(&mut self, expr: &str) -> &mut Self {
let expr_cstr = ManuallyDrop::new(format!("{expr}\0"));
self.desc.dotmember = expr_cstr.as_ptr() as *const c_char;
self.str_ptrs_to_free.push(expr_cstr);
self
}
pub fn dotmember<T>(&mut self, expr: &str) -> &mut Self
where
T: ComponentId,
{
let expr_cstr = ManuallyDrop::new(format!("{expr}\0"));
self.desc.dotmember = expr_cstr.as_ptr() as *const c_char;
self.str_ptrs_to_free.push(expr_cstr);
self.desc.id = T::entity_id(self.world());
self
}
pub fn id(&mut self, the_id: impl IntoId) -> &mut Self {
self.desc.id = *the_id.into_id(self.world);
self
}
pub fn targets(&mut self, value: bool) -> &mut Self {
self.desc.targets = value;
self
}
pub fn kind(&mut self, the_kind: impl IntoEntity) -> &mut Self {
self.desc.kind = *the_kind.into_entity(self.world);
self
}
pub fn brief(&mut self, brief: &str) -> &mut Self {
let brief = ManuallyDrop::new(format!("{brief}\0"));
self.desc.brief = brief.as_ptr() as *const c_char;
self.str_ptrs_to_free.push(brief);
self
}
}
impl<'a> WorldProvider<'a> for MetricBuilder<'a> {
fn world(&self) -> WorldRef<'a> {
self.world
}
}