Refactor card config parsing out of main.rs
This commit is contained in:
parent
76a5f2ccb9
commit
b76c4c7bf5
@ -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,
|
||||||
|
21
src/card.rs
21
src/card.rs
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
src/main.rs
17
src/main.rs
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user