Skip to content

Commit

Permalink
Merge pull request #26 from 4LT/refactor-errors
Browse files Browse the repository at this point in the history
refactor errors into crate root
  • Loading branch information
4LT authored Feb 16, 2024
2 parents 200371c + 5169297 commit 8727a2e
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 83 deletions.
33 changes: 26 additions & 7 deletions src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ impl fmt::Display for BinParse {

impl std::error::Error for BinParse {}

pub type BinParseResult<T> = Result<T, BinParse>;

#[derive(Debug, Clone)]
pub struct Line {
pub message: String,
Expand Down Expand Up @@ -81,21 +79,42 @@ impl TextParse {
}

impl From<io::Error> for TextParse {
fn from(err: io::Error) -> TextParse {
fn from(err: io::Error) -> Self {
TextParse::Io(err)
}
}

impl fmt::Display for TextParse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TextParse::Io(msg) => write!(f, "{}", msg),
TextParse::Lexer(err) => write!(f, "{}", err),
TextParse::Parser(err) => write!(f, "{}", err),
Self::Io(msg) => write!(f, "{}", msg),
Self::Lexer(err) => write!(f, "{}", err),
Self::Parser(err) => write!(f, "{}", err),
}
}
}

impl std::error::Error for TextParse {}

pub type TextParseResult<T> = std::result::Result<T, TextParse>;
#[derive(Debug)]
pub enum Write {
Validation(String),
Io(std::io::Error),
}

impl From<io::Error> for Write {
fn from(err: io::Error) -> Self {
Write::Io(err)
}
}

impl fmt::Display for Write {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Validation(msg) => write!(f, "{}", msg),
Self::Io(err) => write!(f, "{}", err),
}
}
}

impl std::error::Error for Write {}
24 changes: 21 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,31 @@ pub use common::{Palette, QUAKE_PALETTE};
#[cfg(feature = "std")]
use common::slice_to_cstring;

#[cfg(feature = "std")]
pub mod error;

#[cfg(feature = "std")]
pub mod lump;

#[cfg(feature = "std")]
pub mod wad;

pub mod qmap;

#[cfg(feature = "std")]
mod error;

#[cfg(feature = "std")]
pub use error::BinParse as BinParseError;

#[cfg(feature = "std")]
pub use error::TextParse as TextParseError;

#[cfg(feature = "std")]
pub use error::Write as WriteError;

#[cfg(feature = "std")]
pub type BinParseResult<T> = Result<T, BinParseError>;

#[cfg(feature = "std")]
pub type TextParseResult<T> = std::result::Result<T, TextParseError>;

#[cfg(feature = "std")]
pub type WriteAttempt = Result<(), WriteError>;
2 changes: 1 addition & 1 deletion src/lump/parse.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::common::Palette;
use crate::error;
use crate::lump::{Image, MipTexture, MipTextureHead};
use error::BinParseResult;
use crate::BinParseResult;
use std::boxed::Box;
use std::io::{Read, Seek, SeekFrom};
use std::mem::{size_of, transmute, MaybeUninit};
Expand Down
8 changes: 2 additions & 6 deletions src/qmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
//! #
//! # let mut dest = Vec::<u8>::new();
//! #
//! use quake_util::qmap;
//! use qmap::{Entity, WriteError};
//! use quake_util::error::TextParse as TextParseError;
//! use quake_util::{qmap, WriteError, TextParseError};
//! use qmap::Entity;
//!
//! let mut map = qmap::parse(&mut source).map_err(|err| match err {
//! TextParseError::Io(_) => String::from("Failed to read map"),
Expand Down Expand Up @@ -67,9 +66,6 @@ pub use repr::{
#[cfg(feature = "std")]
pub use parser::parse;

#[cfg(feature = "std")]
pub use repr::{WriteAttempt, WriteError};

// test suites

#[cfg(all(test, feature = "std"))]
Expand Down
59 changes: 29 additions & 30 deletions src/qmap/parser.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
#[cfg(feature = "std")]
extern crate std;

use std::{
cell::Cell, io::Read, iter::Peekable, num::NonZeroU8, str::FromStr,
vec::Vec,
};

use crate::{common, error, qmap};
use crate::{common, qmap, TextParseError, TextParseResult};
use common::CellOptionExt;
use qmap::lexer::{Token, TokenIterator};
use qmap::repr::{Alignment, Brush, Edict, Entity, Point, QuakeMap, Surface};

type TokenPeekable<R> = Peekable<TokenIterator<R>>;

trait Extract {
fn extract(&mut self) -> Result<Option<Token>, error::TextParse>;
fn extract(&mut self) -> TextParseResult<Option<Token>>;
}

impl<R> Extract for TokenPeekable<R>
where
R: Read,
{
fn extract(&mut self) -> Result<Option<Token>, error::TextParse> {
fn extract(&mut self) -> Result<Option<Token>, TextParseError> {
self.next().transpose().map_err(|e| e.into_unwrapped())
}
}

trait Normalize {
fn normalize(&self) -> Result<&Option<Token>, error::TextParse>;
fn normalize(&self) -> TextParseResult<&Option<Token>>;
}

impl Normalize for Result<Option<Token>, Cell<Option<error::TextParse>>> {
fn normalize(&self) -> Result<&Option<Token>, error::TextParse> {
impl Normalize for Result<Option<Token>, Cell<Option<TextParseError>>> {
fn normalize(&self) -> Result<&Option<Token>, TextParseError> {
self.as_ref().map_err(|e| e.steal())
}
}
Expand All @@ -44,7 +43,7 @@ const MIN_BRUSH_SURFACES: usize = 4;
/// `brushDef`s/`patchDef`s are not presently supported) but may have texture
/// alignment in either "Valve220" format or the "legacy" predecessor (i.e.
/// without texture axes)
pub fn parse<R: Read>(reader: &mut R) -> error::TextParseResult<QuakeMap> {
pub fn parse<R: Read>(reader: &mut R) -> TextParseResult<QuakeMap> {
let mut entities: Vec<Entity> = Vec::new();
let mut peekable_tokens = TokenIterator::new(reader).peekable();

Expand All @@ -58,7 +57,7 @@ pub fn parse<R: Read>(reader: &mut R) -> error::TextParseResult<QuakeMap> {

fn parse_entity<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Entity> {
) -> TextParseResult<Entity> {
expect_byte(&tokens.extract()?, b'{')?;

let edict = parse_edict(tokens)?;
Expand All @@ -71,7 +70,7 @@ fn parse_entity<R: Read>(

fn parse_edict<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Edict> {
) -> TextParseResult<Edict> {
let mut edict = Edict::new();

while let Some(tok_res) = tokens.peek() {
Expand All @@ -98,7 +97,7 @@ fn parse_edict<R: Read>(

fn parse_brushes<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Vec<Brush>> {
) -> TextParseResult<Vec<Brush>> {
let mut brushes = Vec::new();

while let Some(tok_res) = tokens.peek() {
Expand All @@ -114,7 +113,7 @@ fn parse_brushes<R: Read>(

fn parse_brush<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Brush> {
) -> TextParseResult<Brush> {
let mut surfaces = Vec::with_capacity(MIN_BRUSH_SURFACES);
expect_byte(&tokens.extract()?, b'{')?;

Expand All @@ -132,14 +131,14 @@ fn parse_brush<R: Read>(

fn parse_surface<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Surface> {
) -> TextParseResult<Surface> {
let pt1 = parse_point(tokens)?;
let pt2 = parse_point(tokens)?;
let pt3 = parse_point(tokens)?;

let half_space = [pt1, pt2, pt3];

let texture_token = &tokens.extract()?.ok_or_else(error::TextParse::eof)?;
let texture_token = &tokens.extract()?.ok_or_else(TextParseError::eof)?;

let texture = if b'"' == (&texture_token.text)[0].into() {
strip_quoted(&texture_token.text[..]).to_vec().into()
Expand All @@ -154,7 +153,7 @@ fn parse_surface<R: Read>(
parse_legacy_alignment(tokens)?
}
} else {
return Err(error::TextParse::eof());
return Err(TextParseError::eof());
};

Ok(Surface {
Expand All @@ -166,7 +165,7 @@ fn parse_surface<R: Read>(

fn parse_point<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Point> {
) -> TextParseResult<Point> {
expect_byte(&tokens.extract()?, b'(')?;
let x = expect_float(&tokens.extract()?)?;
let y = expect_float(&tokens.extract()?)?;
Expand All @@ -178,7 +177,7 @@ fn parse_point<R: Read>(

fn parse_legacy_alignment<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Alignment> {
) -> TextParseResult<Alignment> {
let offset_x = expect_float(&tokens.extract()?)?;
let offset_y = expect_float(&tokens.extract()?)?;
let rotation = expect_float(&tokens.extract()?)?;
Expand All @@ -195,7 +194,7 @@ fn parse_legacy_alignment<R: Read>(

fn parse_valve_alignment<R: Read>(
tokens: &mut TokenPeekable<R>,
) -> error::TextParseResult<Alignment> {
) -> TextParseResult<Alignment> {
expect_byte(&tokens.extract()?, b'[')?;
let u_x = expect_float(&tokens.extract()?)?;
let u_y = expect_float(&tokens.extract()?)?;
Expand All @@ -222,26 +221,26 @@ fn parse_valve_alignment<R: Read>(
})
}

fn expect_byte(token: &Option<Token>, byte: u8) -> error::TextParseResult<()> {
fn expect_byte(token: &Option<Token>, byte: u8) -> TextParseResult<()> {
match token.as_ref() {
Some(payload) if payload.match_byte(byte) => Ok(()),
Some(payload) => Err(error::TextParse::from_parser(
Some(payload) => Err(TextParseError::from_parser(
format!(
"Expected `{}`, got `{}`",
char::from(byte),
payload.text_as_string()
),
payload.line_number,
)),
_ => Err(error::TextParse::eof()),
_ => Err(TextParseError::eof()),
}
}

fn expect_byte_or(
token: &Option<Token>,
byte: u8,
rest: &[u8],
) -> error::TextParseResult<()> {
) -> TextParseResult<()> {
match token.as_ref() {
Some(payload) if payload.match_byte(byte) => Ok(()),
Some(payload) => {
Expand All @@ -252,7 +251,7 @@ fn expect_byte_or(
.collect::<Vec<_>>()[..]
.join(", ");

Err(error::TextParse::from_parser(
Err(TextParseError::from_parser(
format!(
"Expected {} or `{}`, got `{}`",
rest_str,
Expand All @@ -262,31 +261,31 @@ fn expect_byte_or(
payload.line_number,
))
}
_ => Err(error::TextParse::eof()),
_ => Err(TextParseError::eof()),
}
}

fn expect_quoted(token: &Option<Token>) -> error::TextParseResult<()> {
fn expect_quoted(token: &Option<Token>) -> TextParseResult<()> {
match token.as_ref() {
Some(payload) if payload.match_quoted() => Ok(()),
Some(payload) => Err(error::TextParse::from_parser(
Some(payload) => Err(TextParseError::from_parser(
format!("Expected quoted, got `{}`", payload.text_as_string()),
payload.line_number,
)),
_ => Err(error::TextParse::eof()),
_ => Err(TextParseError::eof()),
}
}

fn expect_float(token: &Option<Token>) -> error::TextParseResult<f64> {
fn expect_float(token: &Option<Token>) -> TextParseResult<f64> {
match token.as_ref() {
Some(payload) => match f64::from_str(&payload.text_as_string()) {
Ok(num) => Ok(num),
Err(_) => Err(error::TextParse::from_parser(
Err(_) => Err(TextParseError::from_parser(
format!("Expected number, got `{}`", payload.text_as_string()),
payload.line_number,
)),
},
None => Err(error::TextParse::eof()),
None => Err(TextParseError::eof()),
}
}

Expand Down
29 changes: 3 additions & 26 deletions src/qmap/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ extern crate alloc;
#[cfg(feature = "std")]
use std::{
collections::HashMap,
error,
ffi::{CStr, CString},
fmt,
fmt::{Display, Formatter},
io,
string::String,
vec::Vec,
Expand All @@ -22,6 +19,9 @@ use {
core::ffi::CStr, hashbrown::HashMap,
};

#[cfg(feature = "std")]
use crate::{WriteAttempt, WriteError};

/// Return type for validating writability of entities and other items
pub type ValidationResult = Result<(), String>;

Expand All @@ -36,29 +36,6 @@ pub trait CheckWritable {
fn check_writable(&self) -> ValidationResult;
}

#[cfg(feature = "std")]
#[derive(Debug)]
pub enum WriteError {
Validation(String),
Io(std::io::Error),
}

#[cfg(feature = "std")]
impl Display for WriteError {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
match self {
Self::Validation(msg) => write!(formatter, "Validation: {}", msg),
Self::Io(err) => write!(formatter, "I/O: {}", err),
}
}
}

#[cfg(feature = "std")]
impl error::Error for WriteError {}

#[cfg(feature = "std")]
pub type WriteAttempt = Result<(), WriteError>;

/// 3-dimensional point used to determine the half-space a surface lies on
pub type Point = [f64; 3];
pub type Vec3 = [f64; 3];
Expand Down
Loading

0 comments on commit 8727a2e

Please sign in to comment.