georust / geos

Rust bindings for GEOS
https://docs.rs/geos/
MIT License
122 stars 42 forks source link

Implement std::error::Error for geos::Error #91

Closed msakuta closed 3 years ago

msakuta commented 3 years ago

Geos is excellent binding library, but there is one inconvenience.

When we try to catch the error returned from geos in Boxed error trait or anyhow::Error with ? operator, it fails to compile, e.g.

use geos::Geom;

fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let gg1 = geos::Geometry::new_from_wkt("POLYGON ((0 0, 0 5, 6 6, 6 0, 0 0))")?;
    let gg2 = geos::Geometry::new_from_wkt("POLYGON ((1 1, 1 3, 5 5, 5 1, 1 1))")?;
    let gg3 = gg1.difference(&gg2)?;
    assert_eq!(
        gg3.to_wkt_precision(0).expect("to_wkt failed"),
        "POLYGON ((0 0, 0 5, 6 6, 6 0, 0 0), (1 1, 5 1, 5 5, 1 3, 1 1))",
    );

    Ok(())
}
use geos::Geom;
use anyhow::Result;

fn main() -> Result<()> {
    let gg1 = geos::Geometry::new_from_wkt("POLYGON ((0 0, 0 5, 6 6, 6 0, 0 0))")?;
    let gg2 = geos::Geometry::new_from_wkt("POLYGON ((1 1, 1 3, 5 5, 5 1, 1 1))")?;
    let gg3 = gg1.difference(&gg2)?;
    assert_eq!(
        gg3.to_wkt_precision(0).expect("to_wkt failed"),
        "POLYGON ((0 0, 0 5, 6 6, 6 0, 0 0), (1 1, 5 1, 5 5, 1 3, 1 1))",
    );

    Ok(())
}

because geos::Error does not implement std::error::Error.

It would be much more convenient if we can catch errors like this, especially when mixed with other crates' errors.

It is very easy to fix on library side by putting one line like below but it's not possible to fix on user code because of orphan rule.

impl std::error::Error for Error {}
GuillaumeGomez commented 3 years ago

Sounds good to me, thanks!

GuillaumeGomez commented 3 years ago

I released a new version.