-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.rs
83 lines (75 loc) · 2.28 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#![feature(crate_visibility_modifier)]
#![allow(dead_code)]
#[cfg(test)]
mod tests;
mod bits;
pub use self::bits::*;
mod memory;
pub use self::memory::*;
mod meta;
pub use self::meta::*;
mod text;
pub use self::text::*;
mod objects;
pub use self::objects::*;
mod vm;
pub use self::vm::*;
mod window;
pub use self::window::*;
use failure::Fail;
use std::fs::File;
use std::io::{Error as IoError, Read};
use std::path::Path;
/// An implementation of a [Z-Machine](https://en.wikipedia.org/wiki/Z-machine) with a loaded story.
pub struct ZMachine {
crate memory: Vec<u8>,
}
impl ZMachine {
/// Creates a new Z-machine instance from a story file already loaded in memory.
pub fn new(file: impl Into<Vec<u8>>) -> LoadResult<Self> {
let vec = file.into();
if vec.len() < 64 {
return Err(LoadError::TooSmall(vec.len()));
}
Ok(Self { memory: vec })
}
/// Utility function for reading from a filename and passing the contents to [`Self::new`].
pub fn from_file(path: impl AsRef<Path>) -> LoadResult<Self> {
let path = path.as_ref();
let mut vec = Vec::new();
File::open(path)?.read_to_end(&mut vec)?;
Self::new(vec)
}
//todo version-specific header sizing
/// Returns the length of the story in bytes.
pub fn len_bytes(&self) -> usize {
self.memory.len()
}
/// Returns the length of the story in bits.
pub fn len_bits(&self) -> usize {
self.memory.len() * 8
}
/// Returns the length of the story in [`Word`]s.
pub fn len_words(&self) -> usize {
self.memory.len() / 2
}
}
/// Errors that can occur during loading a story.
#[derive(Debug, Fail)]
pub enum LoadError {
/// An error during IO. Only used with [`ZMachine::from_file`].
#[fail(display = "IO error: {}", _0)]
IoError(#[cause] IoError),
/// An error to do with the story's size. A story without a header (64 bytes) cannot be read.
#[fail(display = "Story is too small (was {} bytes, must be at least 64)", _0)]
TooSmall(usize),
/// An unknown error of some other kind.
#[fail(display = "Unknown error")]
Unknown,
}
impl From<IoError> for LoadError {
fn from(err: IoError) -> Self {
LoadError::IoError(err)
}
}
pub type LoadResult<T> = Result<T, LoadError>;