Skip to content

Commit

Permalink
Merge #936
Browse files Browse the repository at this point in the history
936: `no_std` support for `geo-types` r=frewsxcv a=wetheredge

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

This is my take on `no_std` support. This adds a new `std` that behave similarly to `serde`'s.

Rough overview of my changes:
- For the most part, simply swapping `alloc` or `core` in for `std`.
- Also added a second `doc(hidden)` public module (`_alloc`) to give macros access to `Vec` and `Box` even if the crate they are used from does not have `extern crate alloc`. This could be merged into the existing `private_utils`. It could also be dropped entirely, but that would require modifying the macros to reference `std` when that feature is enabled and the cleanest way I found to do that is still somewhat ugly: match on `()` with `cfg`'d branches.

I've looked some at #426 and the main difference I see is that it adds `core-error` for the `Error` trait, while I've just put that behind the `std` feature. If that is preferred, I can add the dependency.

---

I have also started working on `no_std` support in `geo`, but it's not quite as straight-forward, so I was keeping it for a second PR.

fixes #422, partially supersedes #426

Co-authored-by: William Etheredge <[email protected]>
  • Loading branch information
bors[bot] and wetheredge authored Feb 2, 2023
2 parents b559cc3 + 9ce39e1 commit eb67e13
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
- run: rustup target add thumbv6m-none-eabi
- run: cargo check --all-targets --no-default-features
- run: cargo check --lib --target thumbv7em-none-eabihf --no-default-features -F use-rstar_0_9,serde
- run: cargo test --all-features

geo:
Expand Down
2 changes: 2 additions & 0 deletions geo-types/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Return `DoubleEndedIterator` from `LineString::points` and `LineString::points_mut`
* <https://github.com/georust/geo/pull/951>
* POSSIBLY BREAKING: Minimum supported version of Rust (MSRV) is now 1.63
* Add `no_std` compatibility when the new default `std` feature is disabled
* <https://github.com/georust/geo/pull/936>

## 0.7.8

Expand Down
8 changes: 5 additions & 3 deletions geo-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ rust-version = "1.63"
edition = "2021"

[features]
default = ["std"]
std = ["approx/std", "num-traits/std", "serde/std"]
# Prefer `use-rstar` feature rather than enabling rstar directly.
# rstar integration relies on the optional approx crate, but implicit features cannot yet enable other features.
# See: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#namespaced-features
Expand All @@ -20,12 +22,12 @@ use-rstar_0_8 = ["rstar_0_8", "approx"]
use-rstar_0_9 = ["rstar_0_9", "approx"]

[dependencies]
approx = { version = ">= 0.4.0, < 0.6.0", optional = true }
approx = { version = ">= 0.4.0, < 0.6.0", optional = true, default-features = false }
arbitrary = { version = "1.2.0", optional = true }
num-traits = "0.2"
num-traits = { version = "0.2", default-features = false, features = ["libm"] }
rstar_0_8 = { package = "rstar", version = "0.8", optional = true }
rstar_0_9 = { package = "rstar", version = "0.9", optional = true }
serde = { version = "1", optional = true, features = ["derive"] }
serde = { version = "1", optional = true, default-features = false, features = ["alloc", "derive"] }

[dev-dependencies]
approx = ">= 0.4.0, < 0.6.0"
6 changes: 4 additions & 2 deletions geo-types/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fmt;
use core::fmt;

#[derive(Debug)]
pub enum Error {
Expand All @@ -8,6 +8,7 @@ pub enum Error {
},
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl fmt::Display for Error {
Expand All @@ -23,7 +24,8 @@ impl fmt::Display for Error {
#[cfg(test)]
mod test {
use crate::{Geometry, Point, Rect};
use std::convert::TryFrom;
use alloc::string::ToString;
use core::convert::TryFrom;

#[test]
fn error_output() {
Expand Down
2 changes: 1 addition & 1 deletion geo-types/src/geometry/coord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl<T: CoordNum> Coord<T> {
}
}

use std::ops::{Add, Div, Mul, Neg, Sub};
use core::ops::{Add, Div, Mul, Neg, Sub};

/// Negate a coordinate.
///
Expand Down
14 changes: 9 additions & 5 deletions geo-types/src/geometry/geometry_collection.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::{CoordNum, Geometry};

use alloc::vec;
use alloc::vec::Vec;
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};
use core::iter::FromIterator;
use core::ops::{Index, IndexMut};

/// A collection of [`Geometry`](enum.Geometry.html) types.
///
Expand Down Expand Up @@ -148,7 +150,7 @@ impl<T: CoordNum> IndexMut<usize> for GeometryCollection<T> {
// structure helper for consuming iterator
#[derive(Debug)]
pub struct IntoIteratorHelper<T: CoordNum> {
iter: ::std::vec::IntoIter<Geometry<T>>,
iter: ::alloc::vec::IntoIter<Geometry<T>>,
}

// implement the IntoIterator trait for a consuming iterator. Iteration will
Expand Down Expand Up @@ -178,7 +180,7 @@ impl<T: CoordNum> Iterator for IntoIteratorHelper<T> {
// structure helper for non-consuming iterator
#[derive(Debug)]
pub struct IterHelper<'a, T: CoordNum> {
iter: ::std::slice::Iter<'a, Geometry<T>>,
iter: ::core::slice::Iter<'a, Geometry<T>>,
}

// implement the IntoIterator trait for a non-consuming iterator. Iteration will
Expand Down Expand Up @@ -208,7 +210,7 @@ impl<'a, T: CoordNum> Iterator for IterHelper<'a, T> {
// structure helper for mutable non-consuming iterator
#[derive(Debug)]
pub struct IterMutHelper<'a, T: CoordNum> {
iter: ::std::slice::IterMut<'a, Geometry<T>>,
iter: ::core::slice::IterMut<'a, Geometry<T>>,
}

// implement the IntoIterator trait for a mutable non-consuming iterator. Iteration will
Expand Down Expand Up @@ -323,6 +325,8 @@ where

#[cfg(test)]
mod tests {
use alloc::vec;

use crate::{GeometryCollection, Point};

#[test]
Expand Down
23 changes: 13 additions & 10 deletions geo-types/src/geometry/line_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
use approx::{AbsDiffEq, RelativeEq};

use crate::{Coord, CoordNum, Line, Point, Triangle};
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};
use alloc::vec;
use alloc::vec::Vec;
use core::iter::FromIterator;
use core::ops::{Index, IndexMut};

/// An ordered collection of two or more [`Coord`]s, representing a
/// path between locations.
Expand Down Expand Up @@ -136,7 +138,7 @@ pub struct LineString<T: CoordNum = f64>(pub Vec<Coord<T>>);

/// A [`Point`] iterator returned by the `points` method
#[derive(Debug)]
pub struct PointsIter<'a, T: CoordNum + 'a>(::std::slice::Iter<'a, Coord<T>>);
pub struct PointsIter<'a, T: CoordNum + 'a>(::core::slice::Iter<'a, Coord<T>>);

impl<'a, T: CoordNum> Iterator for PointsIter<'a, T> {
type Item = Point<T>;
Expand Down Expand Up @@ -164,7 +166,7 @@ impl<'a, T: CoordNum> DoubleEndedIterator for PointsIter<'a, T> {

/// A [`Coord`] iterator used by the `into_iter` method on a [`LineString`]
#[derive(Debug)]
pub struct CoordinatesIter<'a, T: CoordNum + 'a>(::std::slice::Iter<'a, Coord<T>>);
pub struct CoordinatesIter<'a, T: CoordNum + 'a>(::core::slice::Iter<'a, Coord<T>>);

impl<'a, T: CoordNum> Iterator for CoordinatesIter<'a, T> {
type Item = &'a Coord<T>;
Expand Down Expand Up @@ -358,7 +360,7 @@ impl<T: CoordNum, IC: Into<Coord<T>>> FromIterator<IC> for LineString<T> {
/// Iterate over all the [`Coord`]s in this [`LineString`].
impl<T: CoordNum> IntoIterator for LineString<T> {
type Item = Coord<T>;
type IntoIter = ::std::vec::IntoIter<Coord<T>>;
type IntoIter = ::alloc::vec::IntoIter<Coord<T>>;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
Expand All @@ -377,9 +379,9 @@ impl<'a, T: CoordNum> IntoIterator for &'a LineString<T> {
/// Mutably iterate over all the [`Coord`]s in this [`LineString`]
impl<'a, T: CoordNum> IntoIterator for &'a mut LineString<T> {
type Item = &'a mut Coord<T>;
type IntoIter = ::std::slice::IterMut<'a, Coord<T>>;
type IntoIter = ::core::slice::IterMut<'a, Coord<T>>;

fn into_iter(self) -> ::std::slice::IterMut<'a, Coord<T>> {
fn into_iter(self) -> ::core::slice::IterMut<'a, Coord<T>> {
self.0.iter_mut()
}
}
Expand Down Expand Up @@ -534,14 +536,15 @@ mod test {
#[test]
fn test_exact_size() {
// see https://github.com/georust/geo/issues/762
let ls = LineString::new(vec![coord! { x: 0., y: 0. }, coord! { x: 10., y: 0. }]);
let first = coord! { x: 0., y: 0. };
let ls = LineString::new(vec![first, coord! { x: 10., y: 0. }]);

// reference to force the `impl IntoIterator for &LineString` impl, giving a `CoordinatesIter`
for c in (&ls).into_iter().rev().skip(1).rev() {
println!("{:?}", c);
assert_eq!(&first, c);
}
for p in ls.points().rev().skip(1).rev() {
println!("{:?}", p);
assert_eq!(Point::from(first), p);
}
}

Expand Down
2 changes: 1 addition & 1 deletion geo-types/src/geometry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{CoordNum, Error};
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};
use core::any::type_name;
use std::convert::TryFrom;
use core::convert::TryFrom;

/// An enum representing any possible geometry type.
///
Expand Down
10 changes: 6 additions & 4 deletions geo-types/src/geometry/multi_line_string.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::{CoordNum, LineString};

use alloc::vec;
use alloc::vec::Vec;
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};
use std::iter::FromIterator;
use core::iter::FromIterator;

/// A collection of
/// [`LineString`s](line_string/struct.LineString.html). Can
Expand Down Expand Up @@ -81,7 +83,7 @@ impl<T: CoordNum, ILS: Into<LineString<T>>> FromIterator<ILS> for MultiLineStrin

impl<T: CoordNum> IntoIterator for MultiLineString<T> {
type Item = LineString<T>;
type IntoIter = ::std::vec::IntoIter<LineString<T>>;
type IntoIter = ::alloc::vec::IntoIter<LineString<T>>;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
Expand All @@ -90,7 +92,7 @@ impl<T: CoordNum> IntoIterator for MultiLineString<T> {

impl<'a, T: CoordNum> IntoIterator for &'a MultiLineString<T> {
type Item = &'a LineString<T>;
type IntoIter = ::std::slice::Iter<'a, LineString<T>>;
type IntoIter = ::alloc::slice::Iter<'a, LineString<T>>;

fn into_iter(self) -> Self::IntoIter {
(self.0).iter()
Expand All @@ -99,7 +101,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiLineString<T> {

impl<'a, T: CoordNum> IntoIterator for &'a mut MultiLineString<T> {
type Item = &'a mut LineString<T>;
type IntoIter = ::std::slice::IterMut<'a, LineString<T>>;
type IntoIter = ::alloc::slice::IterMut<'a, LineString<T>>;

fn into_iter(self) -> Self::IntoIter {
(self.0).iter_mut()
Expand Down
10 changes: 6 additions & 4 deletions geo-types/src/geometry/multi_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use crate::{CoordNum, Point};
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};

use std::iter::FromIterator;
use alloc::vec;
use alloc::vec::Vec;
use core::iter::FromIterator;

/// A collection of [`Point`s](struct.Point.html). Can
/// be created from a `Vec` of `Point`s, or from an
Expand Down Expand Up @@ -58,7 +60,7 @@ impl<T: CoordNum, IP: Into<Point<T>>> FromIterator<IP> for MultiPoint<T> {
/// Iterate over the `Point`s in this `MultiPoint`.
impl<T: CoordNum> IntoIterator for MultiPoint<T> {
type Item = Point<T>;
type IntoIter = ::std::vec::IntoIter<Point<T>>;
type IntoIter = ::alloc::vec::IntoIter<Point<T>>;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
Expand All @@ -67,7 +69,7 @@ impl<T: CoordNum> IntoIterator for MultiPoint<T> {

impl<'a, T: CoordNum> IntoIterator for &'a MultiPoint<T> {
type Item = &'a Point<T>;
type IntoIter = ::std::slice::Iter<'a, Point<T>>;
type IntoIter = ::alloc::slice::Iter<'a, Point<T>>;

fn into_iter(self) -> Self::IntoIter {
(self.0).iter()
Expand All @@ -76,7 +78,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiPoint<T> {

impl<'a, T: CoordNum> IntoIterator for &'a mut MultiPoint<T> {
type Item = &'a mut Point<T>;
type IntoIter = ::std::slice::IterMut<'a, Point<T>>;
type IntoIter = ::alloc::slice::IterMut<'a, Point<T>>;

fn into_iter(self) -> Self::IntoIter {
(self.0).iter_mut()
Expand Down
10 changes: 6 additions & 4 deletions geo-types/src/geometry/multi_polygon.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::{CoordNum, Polygon};

use alloc::vec;
use alloc::vec::Vec;
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};
use std::iter::FromIterator;
use core::iter::FromIterator;

/// A collection of [`Polygon`s](struct.Polygon.html). Can
/// be created from a `Vec` of `Polygon`s, or from an
Expand Down Expand Up @@ -49,7 +51,7 @@ impl<T: CoordNum, IP: Into<Polygon<T>>> FromIterator<IP> for MultiPolygon<T> {

impl<T: CoordNum> IntoIterator for MultiPolygon<T> {
type Item = Polygon<T>;
type IntoIter = ::std::vec::IntoIter<Polygon<T>>;
type IntoIter = ::alloc::vec::IntoIter<Polygon<T>>;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
Expand All @@ -58,7 +60,7 @@ impl<T: CoordNum> IntoIterator for MultiPolygon<T> {

impl<'a, T: CoordNum> IntoIterator for &'a MultiPolygon<T> {
type Item = &'a Polygon<T>;
type IntoIter = ::std::slice::Iter<'a, Polygon<T>>;
type IntoIter = ::alloc::slice::Iter<'a, Polygon<T>>;

fn into_iter(self) -> Self::IntoIter {
(self.0).iter()
Expand All @@ -67,7 +69,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiPolygon<T> {

impl<'a, T: CoordNum> IntoIterator for &'a mut MultiPolygon<T> {
type Item = &'a mut Polygon<T>;
type IntoIter = ::std::slice::IterMut<'a, Polygon<T>>;
type IntoIter = ::alloc::slice::IterMut<'a, Polygon<T>>;

fn into_iter(self) -> Self::IntoIter {
(self.0).iter_mut()
Expand Down
2 changes: 1 addition & 1 deletion geo-types/src/geometry/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{point, Coord, CoordFloat, CoordNum};
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};

use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};

/// A single point in 2D space.
///
Expand Down
2 changes: 2 additions & 0 deletions geo-types/src/geometry/polygon.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::{CoordFloat, CoordNum, LineString, Point, Rect, Triangle};
use alloc::vec;
use alloc::vec::Vec;
use num_traits::{Float, Signed};

#[cfg(any(feature = "approx", test))]
Expand Down
5 changes: 3 additions & 2 deletions geo-types/src/geometry/rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 +467,13 @@ where
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct InvalidRectCoordinatesError;

#[cfg(feature = "std")]
#[allow(deprecated)]
impl std::error::Error for InvalidRectCoordinatesError {}

#[allow(deprecated)]
impl std::fmt::Display for InvalidRectCoordinatesError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl core::fmt::Display for InvalidRectCoordinatesError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", RECT_INVALID_BOUNDS_ERROR)
}
}
Expand Down
Loading

0 comments on commit eb67e13

Please sign in to comment.