Skip to content

Commit

Permalink
Merge #622
Browse files Browse the repository at this point in the history
622: Add optional `arbitrary` integration in geo-types. r=michaelkirk a=frewsxcv

- [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md).
- [x] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users.
---

Extracted from #532

If people feel this is too niche, this could also just be a separate crate that lives in this repo or a separate one 🤷🏻 


Co-authored-by: Corey Farwell <coreyf@rwell.org>
  • Loading branch information
bors[bot] and frewsxcv committed Feb 25, 2021
2 parents 5a4c924 + c381187 commit 60d26f8
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
2 changes: 2 additions & 0 deletions geo-types/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
* <https://github.com/georust/geo/pull/616>
* Add specific details about conversion failures in the newly public `geo_types::Error`
* <https://github.com/georust/geo/pull/614>
* Add optional `arbitrary` feature for integration with the [arbitrary](https://github.com/rust-fuzz/arbitrary) crate
* <https://github.com/georust/geo/pull/622>

## 0.7.0

Expand Down
1 change: 1 addition & 0 deletions geo-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use-rstar = ["rstar", "approx"]

[dependencies]
approx = { version = "0.4.0", optional = true }
arbitrary = { version = "1", optional = true }
num-traits = "0.2"
serde = { version = "1", optional = true, features = ["derive"] }
# Prefer `use-rstar` feature rather than enabling rstar directly.
Expand Down
108 changes: 108 additions & 0 deletions geo-types/src/arbitrary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use std::mem;
use crate::{
CoordFloat, Coordinate, Geometry, GeometryCollection, LineString, MultiLineString, MultiPoint,
MultiPolygon, Point, Polygon, Rect, Triangle,
};

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for Coordinate<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let x = u.arbitrary::<T>()?;
let y = u.arbitrary::<T>()?;
Ok(Coordinate { x, y })
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for Point<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary::<Coordinate<T>>().map(Point)
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for LineString<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let coords = u.arbitrary::<Vec<Coordinate<T>>>()?;

if coords.len() < 2 {
return Err(arbitrary::Error::IncorrectFormat);
}

Ok(LineString(coords))
}

fn size_hint(_depth: usize) -> (usize, Option<usize>) {
(mem::size_of::<T>() * 2, None)
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for Polygon<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Polygon::new(
u.arbitrary::<LineString<T>>()?,
u.arbitrary::<Vec<LineString<T>>>()?,
))
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for MultiPoint<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary::<Vec<Point<T>>>().map(MultiPoint)
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for MultiLineString<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary::<Vec<LineString<T>>>().map(MultiLineString)
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for MultiPolygon<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary::<Vec<Polygon<T>>>().map(MultiPolygon)
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a>
for GeometryCollection<T>
{
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
u.arbitrary()
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for Rect<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Rect::new(
u.arbitrary::<Coordinate<T>>()?,
u.arbitrary::<Coordinate<T>>()?,
))
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for Triangle<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Triangle(
u.arbitrary::<Coordinate<T>>()?,
u.arbitrary::<Coordinate<T>>()?,
u.arbitrary::<Coordinate<T>>()?,
))
}
}

impl<'a, T: arbitrary::Arbitrary<'a> + CoordFloat> arbitrary::Arbitrary<'a> for Geometry<T> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let n = u.int_in_range(0..=8)?;

Ok(match n {
0 => Geometry::Point(u.arbitrary()?),
1 => Geometry::LineString(u.arbitrary()?),
2 => Geometry::Polygon(u.arbitrary()?),
3 => Geometry::MultiPoint(u.arbitrary()?),
4 => Geometry::MultiLineString(u.arbitrary()?),
5 => Geometry::MultiPolygon(u.arbitrary()?),
6 => Geometry::GeometryCollection(u.arbitrary()?),
7 => Geometry::Triangle(u.arbitrary()?),
8 => Geometry::Rect(u.arbitrary()?),
_ => unreachable!(),
})
}
}
5 changes: 5 additions & 0 deletions geo-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
//! The following optional [Cargo features] are available:
//!
//! - `approx`: Allows geometry types to be checked for approximate equality with [approx]
//! - `arbitrary`: Allows geometry types to be created from unstructured input with [arbitrary]
//! - `serde`: Allows geometry types to be serialized and deserialized with [Serde]
//! - `use-rstar`: Allows geometry types to be inserted into [rstar] R*-trees
//!
//! [approx]: https://github.com/brendanzab/approx
//! [arbitrary]: https://github.com/rust-fuzz/arbitrary
//! [Cargo features]: https://doc.rust-lang.org/cargo/reference/features.html
//! [GeoRust]: https://georust.org
//! [GEOS]: https://trac.osgeo.org/geos
Expand Down Expand Up @@ -123,6 +125,9 @@ pub use error::Error;
#[macro_use]
mod macros;

#[cfg(feature = "arbitrary")]
mod arbitrary;

#[cfg(feature = "rstar")]
#[doc(hidden)]
pub mod private_utils;
Expand Down

0 comments on commit 60d26f8

Please sign in to comment.