Change to anyhow in cards
This commit is contained in:
parent
4dd7dba8d5
commit
4123b1c2ee
@ -1,7 +1,6 @@
|
|||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use nullable_result::GeneralIterExt;
|
use nullable_result::GeneralIterExt;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
card::{Card, CardType},
|
card::{Card, CardType},
|
||||||
@ -13,21 +12,14 @@ pub struct Backplane {
|
|||||||
cards: Vec<Box<dyn Card>>,
|
cards: Vec<Box<dyn Card>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, Error)]
|
||||||
pub enum CardAddError {
|
pub enum CardAddError {
|
||||||
|
#[error["Backplane full, could not add card"]]
|
||||||
BackplaneFull,
|
BackplaneFull,
|
||||||
|
#[error("Invalid card type")]
|
||||||
InvalidType,
|
InvalidType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CardAddError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::BackplaneFull => f.write_str("Backplane full, could not add card"),
|
|
||||||
Self::InvalidType => f.write_str("Invalid card type"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Backplane {
|
impl Backplane {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { cards: Vec::new() }
|
Self { cards: Vec::new() }
|
||||||
@ -42,15 +34,15 @@ impl Backplane {
|
|||||||
&mut self.cards
|
&mut self.cards
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_card(&mut self, type_name: &str, config: &Mapping) -> Result<usize, CardAddError> {
|
pub fn add_card(&mut self, type_name: &str, config: &Mapping) -> anyhow::Result<usize> {
|
||||||
if self.cards.len() >= 255 {
|
if self.cards.len() >= 255 {
|
||||||
return Err(CardAddError::BackplaneFull);
|
return Err(CardAddError::BackplaneFull.into());
|
||||||
}
|
}
|
||||||
self.cards.push(
|
self.cards.push(
|
||||||
inventory::iter::<CardType>()
|
inventory::iter::<CardType>()
|
||||||
.find(|card_type| card_type.name == type_name)
|
.find(|card_type| card_type.name == type_name)
|
||||||
.ok_or(CardAddError::InvalidType)?
|
.ok_or(CardAddError::InvalidType)?
|
||||||
.new_card(config),
|
.new_card(config)?,
|
||||||
);
|
);
|
||||||
Ok(self.cards.len() - 1)
|
Ok(self.cards.len() - 1)
|
||||||
}
|
}
|
||||||
|
14
src/card.rs
14
src/card.rs
@ -5,7 +5,7 @@ use std::fmt::{Debug, Display};
|
|||||||
|
|
||||||
pub struct CardType {
|
pub struct CardType {
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
new: fn(data: &Mapping) -> Box<dyn Card>,
|
new: fn(data: &Mapping) -> anyhow::Result<Box<dyn Card>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardType {
|
impl CardType {
|
||||||
@ -16,7 +16,7 @@ impl CardType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_card(&self, data: &Mapping) -> Box<dyn Card> {
|
pub fn new_card(&self, data: &Mapping) -> anyhow::Result<Box<dyn Card>> {
|
||||||
(self.new)(data)
|
(self.new)(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,14 +24,14 @@ impl CardType {
|
|||||||
inventory::collect!(CardType);
|
inventory::collect!(CardType);
|
||||||
|
|
||||||
pub trait Card: Debug + Display {
|
pub trait Card: Debug + Display {
|
||||||
fn new(data: &Mapping) -> Self
|
fn new(data: &Mapping) -> anyhow::Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn new_dyn(data: &Mapping) -> Box<dyn Card>
|
fn new_dyn(data: &Mapping) -> anyhow::Result<Box<dyn Card>>
|
||||||
where
|
where
|
||||||
Self: Sized + 'static,
|
Self: Sized + 'static,
|
||||||
{
|
{
|
||||||
Box::new(Self::new(data))
|
Ok(Box::new(Self::new(data)?))
|
||||||
}
|
}
|
||||||
fn display(&self) -> String {
|
fn display(&self) -> String {
|
||||||
String::new()
|
String::new()
|
||||||
@ -80,7 +80,9 @@ pub trait Card: Debug + Display {
|
|||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd(&mut self, _cmd: &[&str]) {}
|
fn cmd(&mut self, _cmd: &[&str]) -> anyhow::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
fn reset(&mut self) {}
|
fn reset(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +64,7 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
.map_err(|e| anyhow!("Could not parse config file ({})", e))?;
|
.map_err(|e| anyhow!("Could not parse config file ({})", e))?;
|
||||||
let mut backplane = Backplane::new();
|
let mut backplane = Backplane::new();
|
||||||
for card in config.cards {
|
for card in config.cards {
|
||||||
match backplane.add_card(card.typ, &card.config) {
|
backplane.add_card(card.typ, &card.config)?;
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => panic!("{}", e),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
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 {
|
||||||
@ -113,7 +110,7 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.map(String::as_str)
|
.map(String::as_str)
|
||||||
.collect_vec(),
|
.collect_vec(),
|
||||||
);
|
)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
11
src/ram.rs
11
src/ram.rs
@ -1,5 +1,6 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use human_repr::HumanCount;
|
use human_repr::HumanCount;
|
||||||
use nullable_result::NullableResult;
|
use nullable_result::NullableResult;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
@ -20,17 +21,17 @@ pub struct Ram {
|
|||||||
impl Ram {}
|
impl Ram {}
|
||||||
|
|
||||||
impl Card for Ram {
|
impl Card for Ram {
|
||||||
fn new(data: &Mapping) -> Self {
|
fn new(data: &Mapping) -> anyhow::Result<Self> {
|
||||||
let size = data
|
let size = data
|
||||||
.get("size")
|
.get("size")
|
||||||
.expect("No size value for RAM")
|
.ok_or_else(|| anyhow!("No size value for RAM"))?
|
||||||
.as_u64()
|
.as_u64()
|
||||||
.expect("Size value not positive integer");
|
.ok_or_else(|| anyhow!("Size value not a positive integer"))?;
|
||||||
Self {
|
Ok(Self {
|
||||||
data: vec![0; size as usize],
|
data: vec![0; size as usize],
|
||||||
start: 0,
|
start: 0,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
fn read_byte(&mut self, address: u32) -> NullableResult<u8, BusError> {
|
fn read_byte(&mut self, address: u32) -> NullableResult<u8, BusError> {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
|
54
src/rom.rs
54
src/rom.rs
@ -1,5 +1,6 @@
|
|||||||
use std::{fmt::Display, fs::File, io::Read};
|
use std::{fmt::Display, fs::File, io::Read};
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use human_repr::HumanCount;
|
use human_repr::HumanCount;
|
||||||
use nullable_result::NullableResult;
|
use nullable_result::NullableResult;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
@ -22,24 +23,26 @@ pub struct Rom {
|
|||||||
impl Rom {}
|
impl Rom {}
|
||||||
|
|
||||||
impl Card for Rom {
|
impl Card for Rom {
|
||||||
fn new(data: &Mapping) -> Self {
|
fn new(data: &Mapping) -> anyhow::Result<Self> {
|
||||||
let file_name = data
|
let file_name = data
|
||||||
.get("image")
|
.get("image")
|
||||||
.map(|name| name.as_str().expect("File name not string").to_string());
|
.map(|name| name.as_str().ok_or_else(|| anyhow!("File name not string")))
|
||||||
|
.transpose()?
|
||||||
|
.map(|name| name.to_string());
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
if let Some(file_name) = file_name.as_ref() {
|
if let Some(file_name) = file_name.as_ref() {
|
||||||
File::open(file_name)
|
File::open(file_name)
|
||||||
.unwrap_or_else(|e| panic!("Could not open ROM image file {} ({})", file_name, e))
|
.map_err(|e| anyhow!("Could not open ROM image file {} ({})", file_name, e))?
|
||||||
.read_to_end(&mut data)
|
.read_to_end(&mut data)
|
||||||
.unwrap_or_else(|e| panic!("Failed to read ROM image file {} ({})", file_name, e));
|
.map_err(|e| anyhow!("Failed to read ROM image file {} ({})", file_name, e))?;
|
||||||
};
|
};
|
||||||
Self {
|
Ok(Self {
|
||||||
data,
|
data,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ram: [0; 32 * 1024],
|
ram: [0; 32 * 1024],
|
||||||
file_name,
|
file_name,
|
||||||
start: 0,
|
start: 0,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte(&mut self, address: u32) -> NullableResult<u8, BusError> {
|
fn read_byte(&mut self, address: u32) -> NullableResult<u8, BusError> {
|
||||||
@ -92,47 +95,28 @@ impl Card for Rom {
|
|||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd(&mut self, cmd: &[&str]) {
|
fn cmd(&mut self, cmd: &[&str]) -> anyhow::Result<()> {
|
||||||
if cmd[0] == "load" && cmd.len() >= 2 {
|
if cmd[0] == "load" && cmd.len() >= 2 {
|
||||||
let mut file = match File::open(cmd[1]) {
|
let mut file = File::open(cmd[1])
|
||||||
Ok(file) => file,
|
.map_err(|e| anyhow!("Couldn't open ROM image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Could not open ROM image file {} ({})", cmd[1], e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
match file.read_to_end(&mut self.data) {
|
file.read_to_end(&mut self.data)
|
||||||
Ok(_) => (),
|
.map_err(|e| anyhow!("Failed to read ROM image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Failed to read ROM image file {} ({})", cmd[1], e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.file_name = Some(cmd[1].into());
|
self.file_name = Some(cmd[1].into());
|
||||||
println!("Read ROM image file {}", cmd[1]);
|
println!("Read ROM image file {}", cmd[1]);
|
||||||
} else if cmd[0] == "reload" {
|
} else if cmd[0] == "reload" {
|
||||||
if let Some(file_name) = &self.file_name {
|
if let Some(file_name) = &self.file_name {
|
||||||
let mut file = match File::open(file_name) {
|
let mut file = File::open(cmd[1])
|
||||||
Ok(file) => file,
|
.map_err(|e| anyhow!("Couldn't open ROM image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Could not open ROM image file {} ({})", file_name, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
match file.read_to_end(&mut self.data) {
|
file.read_to_end(&mut self.data)
|
||||||
Ok(_) => (),
|
.map_err(|e| anyhow!("Failed to read ROM image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Failed to read ROM image file {} ({})", file_name, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!("Reloaded ROM image file {}", file_name);
|
println!("Reloaded ROM image file {}", file_name);
|
||||||
} else {
|
} else {
|
||||||
println!("No ROM image file to reload");
|
println!("No ROM image file to reload");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::{fmt::Display, fs::File, io::Read};
|
use std::{fmt::Display, fs::File, io::Read};
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use human_repr::HumanCount;
|
use human_repr::HumanCount;
|
||||||
use nullable_result::NullableResult;
|
use nullable_result::NullableResult;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
@ -21,23 +22,26 @@ pub struct Storage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Card for Storage {
|
impl Card for Storage {
|
||||||
fn new(data: &Mapping) -> Self {
|
fn new(data: &Mapping) -> anyhow::Result<Self> {
|
||||||
let file_name = data
|
let file_name = data
|
||||||
.get("disk")
|
.get("image")
|
||||||
.map(|name| name.as_str().expect("File name not string").to_string());
|
.map(|name| name.as_str().ok_or_else(|| anyhow!("File name not string")))
|
||||||
|
.transpose()?
|
||||||
|
.map(|name| name.to_string());
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
if let Some(file_name) = file_name.as_ref() {
|
if let Some(file_name) = file_name.as_ref() {
|
||||||
File::open(file_name)
|
File::open(file_name)
|
||||||
.unwrap_or_else(|e| panic!("Could not open disk image file {} ({})", file_name, e))
|
.map_err(|e| anyhow!("Could not open disk image file {} ({})", file_name, e))?
|
||||||
.read_to_end(&mut data)
|
.read_to_end(&mut data)
|
||||||
.unwrap_or_else(|e| panic!("Failed to read disk image file {} ({})", file_name, e));
|
.map_err(|e| anyhow!("Failed to read disk image file {} ({})", file_name, e))?;
|
||||||
};
|
};
|
||||||
Self {
|
|
||||||
|
Ok(Self {
|
||||||
data,
|
data,
|
||||||
file_name,
|
file_name,
|
||||||
sector: 0,
|
sector: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
||||||
@ -65,47 +69,28 @@ impl Card for Storage {
|
|||||||
NullableResult::Ok(())
|
NullableResult::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd(&mut self, cmd: &[&str]) {
|
fn cmd(&mut self, cmd: &[&str]) -> anyhow::Result<()> {
|
||||||
if cmd[0] == "load" && cmd.len() >= 2 {
|
if cmd[0] == "load" && cmd.len() >= 2 {
|
||||||
let mut file = match File::open(cmd[1]) {
|
let mut file = File::open(cmd[1])
|
||||||
Ok(file) => file,
|
.map_err(|e| anyhow!("Couldn't open disk image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Could not open disk image file {} ({})", cmd[1], e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
match file.read_to_end(&mut self.data) {
|
file.read_to_end(&mut self.data)
|
||||||
Ok(_) => (),
|
.map_err(|e| anyhow!("Failed to read disk image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Failed to read disk image file {} ({})", cmd[1], e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.file_name = Some(cmd[1].into());
|
self.file_name = Some(cmd[1].into());
|
||||||
println!("Read disk image file {}", cmd[1]);
|
println!("Read disk image file {}", cmd[1]);
|
||||||
} else if cmd[0] == "reload" {
|
} else if cmd[0] == "reload" {
|
||||||
if let Some(file_name) = &self.file_name {
|
if let Some(file_name) = &self.file_name {
|
||||||
let mut file = match File::open(cmd[1]) {
|
let mut file = File::open(cmd[1])
|
||||||
Ok(file) => file,
|
.map_err(|e| anyhow!("Couldn't open disk image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Could not open disk image file {} ({})", cmd[1], e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
match file.read_to_end(&mut self.data) {
|
file.read_to_end(&mut self.data)
|
||||||
Ok(_) => (),
|
.map_err(|e| anyhow!("Failed to read disk image file {} ({})", cmd[1], e))?;
|
||||||
Err(e) => {
|
|
||||||
println!("Failed to read disk image file {} ({})", cmd[1], e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!("Reloaded disk image file {}", file_name);
|
println!("Reloaded disk image file {}", file_name);
|
||||||
} else {
|
} else {
|
||||||
println!("No disk image file to reload");
|
println!("No disk image file to reload");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@ impl Display for Term {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Card for Term {
|
impl Card for Term {
|
||||||
fn new(_data: &Mapping) -> Self
|
fn new(_data: &Mapping) -> anyhow::Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
Self
|
Ok(Self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user