From 2ff0444854482fd2e80292e074bd5a41640c2f1f Mon Sep 17 00:00:00 2001 From: lifning <> Date: Sun, 17 Oct 2021 22:08:49 -0700 Subject: [PATCH] get rid of "component id" business --- ferretro_components/src/base/mod.rs | 45 ++++++++++++++--------------- ferretro_components/src/lib.rs | 2 +- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/ferretro_components/src/base/mod.rs b/ferretro_components/src/base/mod.rs index 96f6693..6109ebc 100644 --- a/ferretro_components/src/base/mod.rs +++ b/ferretro_components/src/base/mod.rs @@ -5,13 +5,15 @@ use std::os::raw::c_uint; use std::path::{PathBuf, Path}; use std::pin::Pin; use std::io::Read; +use std::collections::HashMap; pub struct RetroComponentBase { retro: LibretroWrapper, libretro_path: PathBuf, + // TODO: control when things get added to this with lifetime constraints defined by implementers components: Vec>>, - component_ptrs: Vec<(TypeId, *mut ())>, + component_ptrs: HashMap, // replaying env calls for late-added components cached_rom_path: Option, @@ -27,9 +29,6 @@ pub struct RetroComponentBase { cached_geometry: Option, } -#[derive(Copy, Clone, Debug)] -pub struct RetroComponentId(usize); - // TODO: replace with std::ops::ControlFlow when it becomes stable pub enum ControlFlow { Continue, @@ -59,8 +58,8 @@ impl RetroComponentBase { let emu = RetroComponentBase { retro, libretro_path: core_path.as_ref().to_path_buf(), - components: Vec::new(), - component_ptrs: Vec::new(), + components: Default::default(), + component_ptrs: Default::default(), cached_rom_path: None, cached_pixel_format: None, cached_input_descriptors: None, @@ -93,11 +92,14 @@ impl RetroComponentBase { Ok(()) } - pub fn register_component(&mut self, comp: T) -> Result + pub fn register_component(&mut self, comp: T) -> Result<()> where T: RetroComponent + Any { // TODO: match comp.schedule { BeforeInit, BeforeLoad, BeforeFirstRun, Anytime } let comp_type = comp.type_id(); + if self.component_ptrs.contains_key(&comp_type) { + return Err(format!("A component of type {:?} has already been registered.", comp_type).into()) + } let mut comp = Box::pin(comp); let comp_ptr = comp.as_mut().get_mut() as *mut T; if let Some(cached) = &self.cached_pixel_format { @@ -138,32 +140,27 @@ impl RetroComponentBase { } self.components.push(comp); - self.component_ptrs.push((comp_type, comp_ptr as *mut ())); + self.component_ptrs.insert(comp_type, comp_ptr as *mut ()); - Ok(RetroComponentId(self.components.len() - 1)) + Ok(()) } - pub fn component_ref(&self, id: RetroComponentId) -> Result<&T> { - self.component_ptr(id) + pub fn component_ref(&self) -> Result<&T> { + self.component_ptr() .map(|x| unsafe { &*x }) } - pub fn component_mut(&mut self, id: RetroComponentId) -> Result<&mut T> { - self.component_ptr(id) + pub fn component_mut(&mut self) -> Result<&mut T> { + self.component_ptr() .map(|x| unsafe { &mut *x }) } - fn component_ptr(&self, id: RetroComponentId) -> Result<*mut T> { - let (comp_type, comp_ptr) = self.component_ptrs.get(id.0) - .ok_or_else(|| format!("Invalid ID given to component_mut: {:?}", id))?; - if *comp_type == TypeId::of::() { - Ok(*comp_ptr as *mut T) - } else { - Err(format!( - "Invalid downcast for {:?}: {:?} != {:?}", - id, comp_type, TypeId::of::() - ).into()) - } + fn component_ptr(&self) -> Result<*mut T> { + let id = TypeId::of::(); + let comp_ptr = self.component_ptrs + .get(&id) + .ok_or_else(|| format!("No component of type {:?} has been registered.", id))?; + Ok(*comp_ptr as *mut T) } pub fn load_game(&mut self, rom: impl AsRef) -> Result<()> { diff --git a/ferretro_components/src/lib.rs b/ferretro_components/src/lib.rs index 170ce1d..87754d8 100644 --- a/ferretro_components/src/lib.rs +++ b/ferretro_components/src/lib.rs @@ -2,7 +2,7 @@ pub mod provided; pub mod base; pub mod prelude { - pub use crate::base::{RetroComponent, RetroComponentBase, RetroComponentId}; + pub use crate::base::{RetroComponent, RetroComponentBase}; pub use ferretro_base::retro::constants::*; pub use ferretro_base::retro::wrapped_types::*; pub use ferretro_base::retro::wrapper::{RetroCallbacks, LibretroWrapper, LibretroWrapperAccess};