Refactor card config parsing out of main.rs

This commit is contained in:
pjht 2022-11-12 08:59:46 -06:00
parent 76a5f2ccb9
commit b76c4c7bf5
3 changed files with 34 additions and 40 deletions

View File

@ -1,6 +1,5 @@
use anyhow::anyhow;
use nullable_result::{GeneralIterExt, NullableResult}; use nullable_result::{GeneralIterExt, NullableResult};
use thiserror::Error;
use toml::Value;
use crate::{ use crate::{
card::{self, Card}, card::{self, Card},
@ -12,17 +11,17 @@ pub struct Backplane {
cards: Vec<Box<dyn Card>>, cards: Vec<Box<dyn Card>>,
} }
#[derive(Debug, Copy, Clone, Error)]
pub enum CardAddError {
#[error["Backplane full, could not add card"]]
BackplaneFull,
#[error("Invalid card type")]
InvalidType,
}
impl Backplane { impl Backplane {
pub fn new() -> Self { pub fn new(cards: Vec<card::Config<'_>>) -> anyhow::Result<Self> {
Self { cards: Vec::new() } if cards.len() > 255 {
return Err(anyhow!("A maximum of 255 cards are allowed"));
}
Ok(Self {
cards: cards
.into_iter()
.map(|cfg| cfg.into_card())
.collect::<Result<Vec<_>, _>>()?,
})
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -34,19 +33,6 @@ impl Backplane {
&mut self.cards &mut self.cards
} }
pub fn add_card(&mut self, type_name: &str, config: Value) -> anyhow::Result<usize> {
if self.cards.len() >= 255 {
return Err(CardAddError::BackplaneFull.into());
}
self.cards.push(
inventory::iter::<card::Type>()
.find(|card_type| card_type.name == type_name)
.ok_or(CardAddError::InvalidType)?
.new_card(config)?,
);
Ok(self.cards.len() - 1)
}
pub fn read_word(&mut self, address: u32) -> Result<u16, BusError> { pub fn read_word(&mut self, address: u32) -> Result<u16, BusError> {
self.mem_helper( self.mem_helper(
address, address,

View File

@ -1,8 +1,27 @@
use crate::m68k::BusError; use crate::m68k::BusError;
use anyhow::anyhow;
use nullable_result::NullableResult; use nullable_result::NullableResult;
use serde::Deserialize;
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
use toml::Value; use toml::Value;
#[derive(Deserialize, Debug)]
pub struct Config<'a> {
#[serde(rename = "type")]
typ: &'a str,
#[serde(flatten)]
config: Value,
}
impl Config<'_> {
pub fn into_card(self) -> anyhow::Result<Box<dyn Card>> {
inventory::iter::<Type>()
.find(|card_type| card_type.name == self.typ)
.ok_or_else(|| anyhow!("Invalid card type {}", self.typ))?
.new_card(self.config)
}
}
pub struct Type { pub struct Type {
pub name: &'static str, pub name: &'static str,
new: fn(data: Value) -> anyhow::Result<Box<dyn Card>>, new: fn(data: Value) -> anyhow::Result<Box<dyn Card>>,
@ -16,7 +35,7 @@ impl Type {
} }
} }
pub fn new_card(&self, data: Value) -> anyhow::Result<Box<dyn Card>> { fn new_card(&self, data: Value) -> anyhow::Result<Box<dyn Card>> {
(self.new)(data) (self.new)(data)
} }
} }

View File

@ -32,20 +32,11 @@ use reedline_repl_rs::{
use serde::Deserialize; use serde::Deserialize;
use std::{fs, path::Path, process}; use std::{fs, path::Path, process};
use symbol_tables::SymbolTables; use symbol_tables::SymbolTables;
use toml::Value;
#[derive(Deserialize, Debug)]
struct CardConfig<'a> {
#[serde(rename = "type")]
typ: &'a str,
#[serde(flatten)]
config: Value,
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
struct EmuConfig<'a> { struct EmuConfig<'a> {
#[serde(borrow)] #[serde(borrow)]
cards: Vec<CardConfig<'a>>, cards: Vec<card::Config<'a>>,
#[serde(borrow)] #[serde(borrow)]
symbol_tables: Option<Vec<&'a str>>, symbol_tables: Option<Vec<&'a str>>,
} }
@ -61,10 +52,8 @@ fn main() -> Result<(), anyhow::Error> {
.map_err(|e| anyhow!("Could not read config file ({})", e))?; .map_err(|e| anyhow!("Could not read config file ({})", e))?;
let config: EmuConfig = let config: EmuConfig =
toml::from_str(&config_str).map_err(|e| anyhow!("Could not parse config file ({})", e))?; toml::from_str(&config_str).map_err(|e| anyhow!("Could not parse config file ({})", e))?;
let mut backplane = Backplane::new(); dbg!(&config);
for card in config.cards { let backplane = Backplane::new(config.cards)?;
backplane.add_card(card.typ, card.config)?;
}
let mut symbol_tables = SymbolTables::new(); let mut symbol_tables = SymbolTables::new();
if let Some(initial_tables) = config.symbol_tables { if let Some(initial_tables) = config.symbol_tables {
for path in initial_tables { for path in initial_tables {