deps: add thiserror and anyhow, reduce boilerplate

This adds rudimentary error messages and unsilences some errors.
This commit is contained in:
Tomasz Cichoń 2024-01-13 18:58:20 +01:00
parent 51c02a9f7f
commit 9a4e8357e7
6 changed files with 78 additions and 63 deletions

View File

@ -12,6 +12,8 @@ pathfinder_geometry = { git = "https://github.com/servo/pathfinder" }
pathfinder_gl = { git = "https://github.com/servo/pathfinder" }
pathfinder_renderer = { git = "https://github.com/servo/pathfinder" }
pathfinder_resources = { git = "https://github.com/servo/pathfinder" }
thiserror = "1.0.56"
anyhow = "1.0.79"
[dependencies.geo]
version = "0.25.1"

View File

@ -1,6 +1,6 @@
use contracts::debug_ensures;
use geo::{EuclideanLength, Point};
use thiserror::Error;
use crate::{
graph::{
@ -15,19 +15,18 @@ use crate::{
rules::{Conditions, Rules},
};
#[derive(Debug, Clone, Copy)]
#[derive(Error, Debug, Clone, Copy)]
pub enum DrawException {
NoTangents(NoTangents),
CannotFinishIn(FixedDotIndex, LayoutException),
#[error(transparent)]
NoTangents(#[from] NoTangents),
// TODO add real error messages + these should eventually use Display
#[error("cannot finish in {0:?}")]
CannotFinishIn(FixedDotIndex, #[source] LayoutException),
#[error("cannot wrap around {0:?}")]
// neither of the exceptions is the source on its own, might be useful to give them names?
CannotWrapAround(WraparoundableIndex, LayoutException, LayoutException),
}
impl From<NoTangents> for DrawException {
fn from(err: NoTangents) -> Self {
DrawException::NoTangents(err)
}
}
pub struct Draw<'a> {
layout: &'a mut Layout,
rules: &'a Rules,

View File

@ -7,6 +7,7 @@ use petgraph::Direction::Incoming;
use rstar::primitives::GeomWithData;
use rstar::{RTree, RTreeObject};
use slab::Slab;
use thiserror::Error;
use crate::graph::{
BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex,
@ -26,46 +27,30 @@ use crate::shape::{Shape, ShapeTrait};
pub type RTreeWrapper = GeomWithData<Shape, Index>;
#[enum_dispatch]
#[derive(Debug, Clone, Copy)]
#[derive(Error, Debug, Clone, Copy)]
pub enum LayoutException {
NoTangents(NoTangents),
Infringement(Infringement),
Collision(Collision),
IsConnected(IsConnected),
#[error(transparent)]
NoTangents(#[from] NoTangents),
#[error(transparent)]
Infringement(#[from] Infringement),
#[error(transparent)]
Collision(#[from] Collision),
#[error(transparent)]
AlreadyConnected(#[from] AlreadyConnected),
}
impl From<NoTangents> for LayoutException {
fn from(err: NoTangents) -> Self {
LayoutException::NoTangents(err)
}
}
impl From<Infringement> for LayoutException {
fn from(err: Infringement) -> Self {
LayoutException::Infringement(err)
}
}
impl From<Collision> for LayoutException {
fn from(err: Collision) -> Self {
LayoutException::Collision(err)
}
}
impl From<IsConnected> for LayoutException {
fn from(err: IsConnected) -> Self {
LayoutException::IsConnected(err)
}
}
#[derive(Debug, Clone, Copy)]
// TODO add real error messages + these should eventually use Display
#[derive(Error, Debug, Clone, Copy)]
#[error("{0:?} infringes on {1:?}")]
pub struct Infringement(pub Shape, pub Index);
#[derive(Debug, Clone, Copy)]
#[derive(Error, Debug, Clone, Copy)]
#[error("{0:?} collides with {1:?}")]
pub struct Collision(pub Shape, pub Index);
#[derive(Debug, Clone, Copy)]
pub struct IsConnected(pub i64, pub Index);
#[derive(Error, Debug, Clone, Copy)]
#[error("{1:?} is already connected to net {0}")]
pub struct AlreadyConnected(pub i64, pub Index);
#[derive(Debug, Clone, Copy)]
pub struct Band {
@ -152,7 +137,7 @@ impl Layout {
self.insert_into_rtree(dot.into());
self.fail_and_remove_if_infringes_except(dot.into(), infringables)?;
Ok::<GenericIndex<W>, Infringement>(dot)
Ok(dot)
}
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
@ -471,8 +456,7 @@ impl Layout {
.map_err(|err| {
self.remove(seg_to.into());
err
})
.map_err(|err| LayoutException::Infringement(err))?;
})?;
let bend_to = self
.add_dot_infringably(dot_weight, infringables)
@ -480,8 +464,7 @@ impl Layout {
self.remove(seg.into());
self.remove(seg_to.into());
err
})
.map_err(|err| LayoutException::Infringement(err))?;
})?;
let bend = self
.add_loose_bend_infringably(seg_to, bend_to, around, bend_weight, infringables)
.map_err(|err| {
@ -571,10 +554,10 @@ impl Layout {
let net = self.bands[weight.band].net;
//
if net == around.primitive(self).net() {
return Err(LayoutException::IsConnected(IsConnected(
return Err(AlreadyConnected(
net,
around.into(),
)));
).into());
}
//
if let Some(wraparound) = match around {
@ -583,10 +566,10 @@ impl Layout {
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
} {
if net == wraparound.primitive(self).net() {
return Err(LayoutException::IsConnected(IsConnected(
return Err(AlreadyConnected(
net,
wraparound.into(),
)));
).into());
}
}
@ -673,7 +656,7 @@ impl Layout {
self.insert_into_rtree(bend.into());
self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok::<LooseBendIndex, Infringement>(bend)
Ok(bend)
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]

View File

@ -31,7 +31,7 @@ use layout::{Infringement, Layout, LayoutException};
use mesh::{Mesh, MeshEdgeReference, VertexIndex};
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use primitive::MakeShape;
use router::RouterObserver;
use router::{RouterObserver, RoutingError};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
@ -175,7 +175,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
}
fn main() {
fn main() -> Result<(), anyhow::Error> {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
@ -488,7 +488,7 @@ fn main() {
dot_end,
&mut EmptyRouterObserver,
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
);
)?;
render_times(
&mut event_pump,
@ -521,7 +521,7 @@ fn main() {
dot_end2,
//&mut EmptyRouterObserver,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
);
)?;
render_times(
&mut event_pump,
@ -542,7 +542,7 @@ fn main() {
dot_start3,
dot_end3,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
);
)?;
render_times(
&mut event_pump,
@ -558,6 +558,8 @@ fn main() {
&[],
-1,
);
Ok(())
}
fn render_times(

View File

@ -1,7 +1,9 @@
use geo::{geometry::Point, point, EuclideanDistance, Line};
use std::ops::Sub;
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Error, Debug, Clone, Copy, PartialEq)]
#[error("no tangents for {0:?} and {1:?}")] // TODO add real error message
pub struct NoTangents(pub Circle, pub Circle);
#[derive(Debug, Clone, Copy, PartialEq)]

View File

@ -1,6 +1,7 @@
use geo::geometry::Point;
use petgraph::visit::EdgeRef;
use spade::InsertionError;
use thiserror::Error;
use crate::astar::{astar, AstarStrategy, PathTracker};
use crate::draw::DrawException;
@ -12,6 +13,24 @@ use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
use crate::rules::Rules;
use crate::tracer::{Trace, Tracer};
#[derive(Error, Debug, Clone, Copy)]
#[error("failed to route from {from:?} to {to:?}")] // this should eventually use Display
pub struct RoutingError {
from: FixedDotIndex,
to: FixedDotIndex,
source: RoutingErrorKind,
}
#[derive(Error, Debug, Clone, Copy)]
pub enum RoutingErrorKind {
#[error(transparent)]
MeshInsertion(#[from] InsertionError),
// exposing more details here seems difficult
// TODO more descriptive message
#[error("A* found no path")]
AStar,
}
pub trait RouterObserver {
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace);
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference);
@ -97,12 +116,17 @@ impl Router {
from: FixedDotIndex,
to: FixedDotIndex,
observer: &mut impl RouterObserver,
) -> Result<Mesh, InsertionError> {
) -> Result<Mesh, RoutingError> {
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
// right.
//self.mesh.triangulate(&self.layout)?;
let mut mesh = Mesh::new(&self.layout);
mesh.generate(&self.layout)?;
mesh.generate(&self.layout)
.map_err(|err| RoutingError {
from,
to,
source: err.into(),
})?;
let mut tracer = self.tracer(&mesh);
let trace = tracer.start(from, 3.0);
@ -111,8 +135,11 @@ impl Router {
&mesh,
from.into(),
&mut RouterAstarStrategy::new(tracer, trace, to.into(), observer),
)
.unwrap(); // TODO.
).ok_or(RoutingError {
from,
to,
source: RoutingErrorKind::AStar,
})?;
Ok(mesh)
}