mirror of https://codeberg.org/topola/topola.git
deps: add thiserror and anyhow, reduce boilerplate
This adds rudimentary error messages and unsilences some errors.
This commit is contained in:
parent
51c02a9f7f
commit
9a4e8357e7
|
|
@ -12,6 +12,8 @@ pathfinder_geometry = { git = "https://github.com/servo/pathfinder" }
|
||||||
pathfinder_gl = { git = "https://github.com/servo/pathfinder" }
|
pathfinder_gl = { git = "https://github.com/servo/pathfinder" }
|
||||||
pathfinder_renderer = { git = "https://github.com/servo/pathfinder" }
|
pathfinder_renderer = { git = "https://github.com/servo/pathfinder" }
|
||||||
pathfinder_resources = { git = "https://github.com/servo/pathfinder" }
|
pathfinder_resources = { git = "https://github.com/servo/pathfinder" }
|
||||||
|
thiserror = "1.0.56"
|
||||||
|
anyhow = "1.0.79"
|
||||||
|
|
||||||
[dependencies.geo]
|
[dependencies.geo]
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
|
|
||||||
19
src/draw.rs
19
src/draw.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use contracts::debug_ensures;
|
use contracts::debug_ensures;
|
||||||
|
|
||||||
use geo::{EuclideanLength, Point};
|
use geo::{EuclideanLength, Point};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
graph::{
|
graph::{
|
||||||
|
|
@ -15,19 +15,18 @@ use crate::{
|
||||||
rules::{Conditions, Rules},
|
rules::{Conditions, Rules},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Error, Debug, Clone, Copy)]
|
||||||
pub enum DrawException {
|
pub enum DrawException {
|
||||||
NoTangents(NoTangents),
|
#[error(transparent)]
|
||||||
CannotFinishIn(FixedDotIndex, LayoutException),
|
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),
|
CannotWrapAround(WraparoundableIndex, LayoutException, LayoutException),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NoTangents> for DrawException {
|
|
||||||
fn from(err: NoTangents) -> Self {
|
|
||||||
DrawException::NoTangents(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Draw<'a> {
|
pub struct Draw<'a> {
|
||||||
layout: &'a mut Layout,
|
layout: &'a mut Layout,
|
||||||
rules: &'a Rules,
|
rules: &'a Rules,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use petgraph::Direction::Incoming;
|
||||||
use rstar::primitives::GeomWithData;
|
use rstar::primitives::GeomWithData;
|
||||||
use rstar::{RTree, RTreeObject};
|
use rstar::{RTree, RTreeObject};
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::graph::{
|
use crate::graph::{
|
||||||
BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex,
|
BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex,
|
||||||
|
|
@ -26,46 +27,30 @@ use crate::shape::{Shape, ShapeTrait};
|
||||||
pub type RTreeWrapper = GeomWithData<Shape, Index>;
|
pub type RTreeWrapper = GeomWithData<Shape, Index>;
|
||||||
|
|
||||||
#[enum_dispatch]
|
#[enum_dispatch]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Error, Debug, Clone, Copy)]
|
||||||
pub enum LayoutException {
|
pub enum LayoutException {
|
||||||
NoTangents(NoTangents),
|
#[error(transparent)]
|
||||||
Infringement(Infringement),
|
NoTangents(#[from] NoTangents),
|
||||||
Collision(Collision),
|
#[error(transparent)]
|
||||||
IsConnected(IsConnected),
|
Infringement(#[from] Infringement),
|
||||||
|
#[error(transparent)]
|
||||||
|
Collision(#[from] Collision),
|
||||||
|
#[error(transparent)]
|
||||||
|
AlreadyConnected(#[from] AlreadyConnected),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NoTangents> for LayoutException {
|
// TODO add real error messages + these should eventually use Display
|
||||||
fn from(err: NoTangents) -> Self {
|
#[derive(Error, Debug, Clone, Copy)]
|
||||||
LayoutException::NoTangents(err)
|
#[error("{0:?} infringes on {1:?}")]
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)]
|
|
||||||
pub struct Infringement(pub Shape, pub Index);
|
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);
|
pub struct Collision(pub Shape, pub Index);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Error, Debug, Clone, Copy)]
|
||||||
pub struct IsConnected(pub i64, pub Index);
|
#[error("{1:?} is already connected to net {0}")]
|
||||||
|
pub struct AlreadyConnected(pub i64, pub Index);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Band {
|
pub struct Band {
|
||||||
|
|
@ -152,7 +137,7 @@ impl Layout {
|
||||||
self.insert_into_rtree(dot.into());
|
self.insert_into_rtree(dot.into());
|
||||||
self.fail_and_remove_if_infringes_except(dot.into(), infringables)?;
|
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))]
|
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
|
||||||
|
|
@ -471,8 +456,7 @@ impl Layout {
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
self.remove(seg_to.into());
|
self.remove(seg_to.into());
|
||||||
err
|
err
|
||||||
})
|
})?;
|
||||||
.map_err(|err| LayoutException::Infringement(err))?;
|
|
||||||
|
|
||||||
let bend_to = self
|
let bend_to = self
|
||||||
.add_dot_infringably(dot_weight, infringables)
|
.add_dot_infringably(dot_weight, infringables)
|
||||||
|
|
@ -480,8 +464,7 @@ impl Layout {
|
||||||
self.remove(seg.into());
|
self.remove(seg.into());
|
||||||
self.remove(seg_to.into());
|
self.remove(seg_to.into());
|
||||||
err
|
err
|
||||||
})
|
})?;
|
||||||
.map_err(|err| LayoutException::Infringement(err))?;
|
|
||||||
let bend = self
|
let bend = self
|
||||||
.add_loose_bend_infringably(seg_to, bend_to, around, bend_weight, infringables)
|
.add_loose_bend_infringably(seg_to, bend_to, around, bend_weight, infringables)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
|
@ -571,10 +554,10 @@ impl Layout {
|
||||||
let net = self.bands[weight.band].net;
|
let net = self.bands[weight.band].net;
|
||||||
//
|
//
|
||||||
if net == around.primitive(self).net() {
|
if net == around.primitive(self).net() {
|
||||||
return Err(LayoutException::IsConnected(IsConnected(
|
return Err(AlreadyConnected(
|
||||||
net,
|
net,
|
||||||
around.into(),
|
around.into(),
|
||||||
)));
|
).into());
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if let Some(wraparound) = match around {
|
if let Some(wraparound) = match around {
|
||||||
|
|
@ -583,10 +566,10 @@ impl Layout {
|
||||||
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
|
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
|
||||||
} {
|
} {
|
||||||
if net == wraparound.primitive(self).net() {
|
if net == wraparound.primitive(self).net() {
|
||||||
return Err(LayoutException::IsConnected(IsConnected(
|
return Err(AlreadyConnected(
|
||||||
net,
|
net,
|
||||||
wraparound.into(),
|
wraparound.into(),
|
||||||
)));
|
).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -673,7 +656,7 @@ impl Layout {
|
||||||
|
|
||||||
self.insert_into_rtree(bend.into());
|
self.insert_into_rtree(bend.into());
|
||||||
self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
|
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()))]
|
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
|
||||||
|
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -31,7 +31,7 @@ use layout::{Infringement, Layout, LayoutException};
|
||||||
use mesh::{Mesh, MeshEdgeReference, VertexIndex};
|
use mesh::{Mesh, MeshEdgeReference, VertexIndex};
|
||||||
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
||||||
use primitive::MakeShape;
|
use primitive::MakeShape;
|
||||||
use router::RouterObserver;
|
use router::{RouterObserver, RoutingError};
|
||||||
|
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
use sdl2::keyboard::Keycode;
|
use sdl2::keyboard::Keycode;
|
||||||
|
|
@ -175,7 +175,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
|
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), anyhow::Error> {
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
let video_subsystem = sdl_context.video().unwrap();
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
|
||||||
|
|
@ -488,7 +488,7 @@ fn main() {
|
||||||
dot_end,
|
dot_end,
|
||||||
&mut EmptyRouterObserver,
|
&mut EmptyRouterObserver,
|
||||||
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
|
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
|
||||||
);
|
)?;
|
||||||
|
|
||||||
render_times(
|
render_times(
|
||||||
&mut event_pump,
|
&mut event_pump,
|
||||||
|
|
@ -521,7 +521,7 @@ fn main() {
|
||||||
dot_end2,
|
dot_end2,
|
||||||
//&mut EmptyRouterObserver,
|
//&mut EmptyRouterObserver,
|
||||||
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
|
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
|
||||||
);
|
)?;
|
||||||
|
|
||||||
render_times(
|
render_times(
|
||||||
&mut event_pump,
|
&mut event_pump,
|
||||||
|
|
@ -542,7 +542,7 @@ fn main() {
|
||||||
dot_start3,
|
dot_start3,
|
||||||
dot_end3,
|
dot_end3,
|
||||||
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
|
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
|
||||||
);
|
)?;
|
||||||
|
|
||||||
render_times(
|
render_times(
|
||||||
&mut event_pump,
|
&mut event_pump,
|
||||||
|
|
@ -558,6 +558,8 @@ fn main() {
|
||||||
&[],
|
&[],
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_times(
|
fn render_times(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use geo::{geometry::Point, point, EuclideanDistance, Line};
|
use geo::{geometry::Point, point, EuclideanDistance, Line};
|
||||||
use std::ops::Sub;
|
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);
|
pub struct NoTangents(pub Circle, pub Circle);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use geo::geometry::Point;
|
use geo::geometry::Point;
|
||||||
use petgraph::visit::EdgeRef;
|
use petgraph::visit::EdgeRef;
|
||||||
use spade::InsertionError;
|
use spade::InsertionError;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::astar::{astar, AstarStrategy, PathTracker};
|
use crate::astar::{astar, AstarStrategy, PathTracker};
|
||||||
use crate::draw::DrawException;
|
use crate::draw::DrawException;
|
||||||
|
|
@ -12,6 +13,24 @@ use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
|
||||||
use crate::rules::Rules;
|
use crate::rules::Rules;
|
||||||
use crate::tracer::{Trace, Tracer};
|
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 {
|
pub trait RouterObserver {
|
||||||
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace);
|
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace);
|
||||||
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference);
|
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference);
|
||||||
|
|
@ -97,12 +116,17 @@ impl Router {
|
||||||
from: FixedDotIndex,
|
from: FixedDotIndex,
|
||||||
to: FixedDotIndex,
|
to: FixedDotIndex,
|
||||||
observer: &mut impl RouterObserver,
|
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
|
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
|
||||||
// right.
|
// right.
|
||||||
//self.mesh.triangulate(&self.layout)?;
|
//self.mesh.triangulate(&self.layout)?;
|
||||||
let mut mesh = Mesh::new(&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 mut tracer = self.tracer(&mesh);
|
||||||
let trace = tracer.start(from, 3.0);
|
let trace = tracer.start(from, 3.0);
|
||||||
|
|
@ -111,8 +135,11 @@ impl Router {
|
||||||
&mesh,
|
&mesh,
|
||||||
from.into(),
|
from.into(),
|
||||||
&mut RouterAstarStrategy::new(tracer, trace, to.into(), observer),
|
&mut RouterAstarStrategy::new(tracer, trace, to.into(), observer),
|
||||||
)
|
).ok_or(RoutingError {
|
||||||
.unwrap(); // TODO.
|
from,
|
||||||
|
to,
|
||||||
|
source: RoutingErrorKind::AStar,
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(mesh)
|
Ok(mesh)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue