Skip to content

Commit

Permalink
Use thiserror for error handling (#51)
Browse files Browse the repository at this point in the history
* Use thiserror for error handling

* Prepare release
  • Loading branch information
odarbelaeze authored Sep 4, 2024
1 parent 737bded commit faa8a2f
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 130 deletions.
8 changes: 2 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "vegas-lattice"
version = "0.6.0"
version = "0.7.0"
authors = ["Oscar David Arbeláez Echeverri <[email protected]>"]
description = "CLI and library to work with lattices"
documentation = "https://docs.rs/vegas-lattice"
Expand All @@ -12,14 +12,10 @@ categories = ["command-line-utilities", "science", "simulation"]
license-file = "LICENSE.txt"
edition = "2021"

[badges]
is-it-maintained-issue-resolution = { repository = "odarbelaeze/vegas-lattice-rs" }
is-it-maintained-open-issues = { repository = "odarbelaeze/vegas-lattice-rs" }
maintenance = { status = "actively-developed" }

[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
image = "0.24"
rand = "0.8"
clap = { version = "4.5.16", features = ["cargo"] }
thiserror = "1.0.63"
2 changes: 1 addition & 1 deletion src/alloy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl Alloy {
}

/// Picks a kind of atom from the alloy
pub fn pick<R: Rng + ?Sized>(&self, rng: &mut R) -> String {
pub fn pick<R: Rng>(&self, rng: &mut R) -> String {
self.kinds[self.weights.sample(rng)].clone()
}
}
75 changes: 16 additions & 59 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,66 +1,23 @@
//! Error handling for the lattice crate
//! Error handling for the vegas lattice crate

use serde_json::Error as SerdeError;
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;

/// Error type for the lattice crate
#[derive(Debug)]
pub enum LatticeError {
IoError(IoError),
JsonParseError(SerdeError),
ImageReadError(image::ImageError),
use thiserror::Error;

/// Error type for the vegas lattice crate
#[derive(Error, Debug)]
pub enum VegasLatticeError {
#[error("IO error: {0}")]
IoError(#[from] IoError),
#[error("serialization error: {0}")]
SerializationError(#[from] SerdeError),
#[error("Formatter error: {0}")]
ImageReadError(#[from] image::ImageError),
#[error("inconsistent vertices")]
InconsistentVertices,
#[error("negative size")]
NegativeSize,
}

impl StdError for LatticeError {
fn description(&self) -> &str {
match self {
LatticeError::IoError(_) => "There was an error reading your file",
LatticeError::JsonParseError(_) => "There was a problem parsing json",
LatticeError::ImageReadError(_) => "There was a problem reading the image",
LatticeError::InconsistentVertices => "These vertices are inconsistent",
LatticeError::NegativeSize => "What are you up to don't give me a negative size",
}
}

fn cause(&self) -> Option<&dyn StdError> {
match self {
LatticeError::IoError(err) => Some(err),
LatticeError::JsonParseError(err) => Some(err),
_ => None,
}
}
}

impl fmt::Display for LatticeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
LatticeError::IoError(_) => f.write_str("IoError"),
LatticeError::JsonParseError(_) => f.write_str("JsonParseError"),
LatticeError::ImageReadError(_) => f.write_str("ImageReadError"),
LatticeError::InconsistentVertices => f.write_str("InconsistentVertices"),
LatticeError::NegativeSize => f.write_str("NegativeSize"),
}
}
}

impl From<SerdeError> for LatticeError {
fn from(err: SerdeError) -> Self {
LatticeError::JsonParseError(err)
}
}

impl From<IoError> for LatticeError {
fn from(err: IoError) -> Self {
LatticeError::IoError(err)
}
}

impl From<image::ImageError> for LatticeError {
fn from(err: image::ImageError) -> Self {
LatticeError::ImageReadError(err)
}
}
/// Result type for the vegas lattice crate
pub type Result<T> = std::result::Result<T, VegasLatticeError>;
2 changes: 1 addition & 1 deletion src/io.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Defines the `to_writer_lattice` function for serializing a type to a writer

use crate::error::Result;
use serde::ser;
use serde_json::error::Result;
use serde_json::ser::{Formatter, Serializer};
use std::io;

Expand Down
26 changes: 12 additions & 14 deletions src/lattice.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
//! Lattice data structure
use std::iter::repeat;
use std::str::FromStr;

use crate::alloy::Alloy;
use crate::error::VegasLatticeError;
use crate::mask::Mask;
use crate::site::Site;
use crate::util::Axis;
use crate::vertex::Vertex;
use rand::thread_rng;

use super::alloy::Alloy;
use super::error::LatticeError;
use super::mask::Mask;
use super::site::Site;
use super::util::Axis;
use super::vertex::Vertex;
use serde::{Deserialize, Serialize};
use std::iter::repeat;
use std::str::FromStr;

/// A lattice is a collection of sites and vertices.
///
Expand Down Expand Up @@ -155,12 +153,12 @@ impl Lattice {
}

/// Validates the lattice
pub fn validate(self) -> Result<Self, LatticeError> {
pub fn validate(self) -> Result<Self, VegasLatticeError> {
if !self.are_vertices_consistent() {
return Err(LatticeError::InconsistentVertices);
return Err(VegasLatticeError::InconsistentVertices);
}
if self.size.0 < 0.0 || self.size.1 < 0.0 || self.size.2 < 0.0 {
return Err(LatticeError::NegativeSize);
return Err(VegasLatticeError::NegativeSize);
}
Ok(self)
}
Expand Down Expand Up @@ -257,7 +255,7 @@ impl Lattice {
}

impl FromStr for Lattice {
type Err = LatticeError;
type Err = VegasLatticeError;
fn from_str(source: &str) -> Result<Lattice, Self::Err> {
let lattice: Lattice = serde_json::from_str(source)?;
lattice.validate()
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,11 @@
//! assert!(lattice.sites()[0].kind() == "B" || lattice.sites()[0].kind() == "C");
//! ```

extern crate image;
extern crate rand;
extern crate serde;
extern crate serde_json;
extern crate thiserror;

pub mod error;
pub mod io;
Expand Down
59 changes: 24 additions & 35 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
extern crate serde;
extern crate serde_json;
extern crate vegas_lattice;

use clap::parser::ValuesRef;
use clap::{Arg, ArgAction, Command};
use std::error::Error;
use std::fs::File;
use std::io::{stdin, Read};
use std::path::Path;
use vegas_lattice::{error::Result, io, Alloy, Axis, Lattice, Mask};

use clap::{Arg, ArgAction, Command};
use vegas_lattice::{io, Alloy, Axis, Lattice, Mask};

fn read(input: Option<&str>) -> Result<Lattice, Box<dyn Error>> {
fn read(input: Option<&str>) -> Result<Lattice> {
let mut data = String::new();
if let Some(filename) = input {
let mut file = File::open(filename)?;
Expand All @@ -30,7 +29,7 @@ fn write_pretty(lattice: Lattice) {
println!("{}", io::to_string_lattice(&lattice).unwrap());
}

fn check_error(res: Result<(), Box<dyn Error>>) {
fn check_error(res: Result<()>) {
if let Err(e) = res {
eprintln!("Error: {}", e);
if let Some(source) = e.source() {
Expand All @@ -41,24 +40,19 @@ fn check_error(res: Result<(), Box<dyn Error>>) {

// Commands over here

fn check(input: Option<&str>) -> Result<(), Box<dyn Error>> {
fn check(input: Option<&str>) -> Result<()> {
let lattice = read(input)?;
write(lattice);
Ok(())
}

fn pretty(input: Option<&str>) -> Result<(), Box<dyn Error>> {
fn pretty(input: Option<&str>) -> Result<()> {
let lattice = read(input)?;
write_pretty(lattice);
Ok(())
}

fn drop(
input: Option<&str>,
drop_x: bool,
drop_y: bool,
drop_z: bool,
) -> Result<(), Box<dyn Error>> {
fn drop(input: Option<&str>, drop_x: bool, drop_y: bool, drop_z: bool) -> Result<()> {
let mut lattice = read(input)?;
if drop_x {
lattice = lattice.drop(Axis::X);
Expand All @@ -78,7 +72,7 @@ fn expand(
along_x: Option<&usize>,
along_y: Option<&usize>,
along_z: Option<&usize>,
) -> Result<(), Box<dyn Error>> {
) -> Result<()> {
let mut lattice = read(input)?;
if let Some(size) = along_x {
lattice = lattice.expand_along(Axis::X, *size);
Expand All @@ -93,27 +87,23 @@ fn expand(
Ok(())
}

fn alloy(
input: Option<&str>,
source: &str,
targets: Vec<(&str, u32)>,
) -> Result<(), Box<dyn Error>> {
fn alloy(input: Option<&str>, source: &str, targets: Vec<(&str, u32)>) -> Result<()> {
let alloy = Alloy::from_targets(targets);
let mut lattice = read(input)?;
lattice = lattice.alloy_sites(source, alloy);
write(lattice);
Ok(())
}

fn mask(input: Option<&str>, path: &str, ppu: f64) -> Result<(), Box<dyn Error>> {
fn mask(input: Option<&str>, path: &str, ppu: f64) -> Result<()> {
let mask = Mask::new(Path::new(&path), ppu)?;
let mut lattice = read(input)?;
lattice = lattice.apply_mask(mask);
write(lattice);
Ok(())
}

fn into(input: Option<&str>, format: &str) -> Result<(), Box<dyn Error>> {
fn into(input: Option<&str>, format: &str) -> Result<()> {
let lattice = read(input)?;
match format {
"tsv" => {
Expand Down Expand Up @@ -292,7 +282,7 @@ fn main() {
);

let matches = cmd.get_matches();
let result: Result<(), Box<dyn Error>> = match matches.subcommand() {
let result: Result<()> = match matches.subcommand() {
Some(("sc", sub_matches)) => {
let a = sub_matches.get_one::<f64>("a").unwrap();
let lattice = Lattice::sc(*a);
Expand Down Expand Up @@ -336,18 +326,17 @@ fn main() {
Some(("alloy", sub_matches)) => {
let input = sub_matches.get_one::<String>("input").map(|s| s.as_str());
let source = sub_matches.get_one::<String>("source").unwrap();
if let Some(target) = sub_matches.get_many::<String>("target") {
let kinds: Vec<_> = target.clone().step_by(2).map(|s| s.as_str()).collect();
let ratios: Vec<_> = target
.skip(1)
.step_by(2)
.map(|s| s.parse::<u32>().unwrap())
.collect();
let target: Vec<_> = kinds.into_iter().zip(ratios).collect();
alloy(input, source, target)
} else {
Err("No target provided".into())
}
let targets = sub_matches
.get_many::<String>("target")
.unwrap_or(ValuesRef::default());
let kinds: Vec<_> = targets.clone().step_by(2).map(|s| s.as_str()).collect();
let ratios: Vec<_> = targets
.skip(1)
.step_by(2)
.map(|s| s.parse::<u32>().unwrap())
.collect();
let target: Vec<_> = kinds.into_iter().zip(ratios).collect();
alloy(input, source, target)
}
Some(("mask", sub_matches)) => {
let path = sub_matches.get_one::<String>("mask").unwrap();
Expand Down
12 changes: 4 additions & 8 deletions src/mask.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
//! Simpe tools for dealing with masks, and abstracts the requirement of
//! image.

extern crate image;

use std::path::Path;

use crate::error::LatticeError;

use self::image::{DynamicImage, GenericImageView, Pixel};
use crate::error::VegasLatticeError;
use image::{DynamicImage, GenericImageView, Pixel};
use rand::Rng;
use std::path::Path;

/// A mask represents a 2D image that can be used to filter out points
///
Expand All @@ -32,7 +28,7 @@ pub struct Mask {

impl Mask {
/// Create a new mask from a path and a pixels per unit ratio
pub fn new(path: &Path, ppu: f64) -> Result<Self, LatticeError> {
pub fn new(path: &Path, ppu: f64) -> Result<Self, VegasLatticeError> {
let img = image::open(path)?;
Ok(Self {
image: Box::new(img),
Expand Down
5 changes: 2 additions & 3 deletions src/site.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::str::FromStr;

use super::util::{Axis, Tagged};
use crate::util::{Axis, Tagged};
use serde::{Deserialize, Serialize};
use serde_json::Error as SerdeError;
use std::str::FromStr;

/// Represetns a site in a lattice.
///
Expand Down
5 changes: 2 additions & 3 deletions src/vertex.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::str::FromStr;

use super::util::{python_mod, Axis, Tagged};
use crate::util::{python_mod, Axis, Tagged};
use serde::{Deserialize, Serialize};
use serde_json::Error as SerdeError;
use std::str::FromStr;

/// Represents a vertex in a lattice.
///
Expand Down

0 comments on commit faa8a2f

Please sign in to comment.