diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 81a967e65e..b0c7216980 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -76,7 +76,9 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 + - run: rustup target add thumbv7em-none-eabihf - 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: diff --git a/geo-types/CHANGES.md b/geo-types/CHANGES.md index 1ef29d0d27..27e39a2247 100644 --- a/geo-types/CHANGES.md +++ b/geo-types/CHANGES.md @@ -5,6 +5,8 @@ * Return `DoubleEndedIterator` from `LineString::points` and `LineString::points_mut` * * POSSIBLY BREAKING: Minimum supported version of Rust (MSRV) is now 1.63 +* Add `no_std` compatibility when the new default `std` feature is disabled + * ## 0.7.8 diff --git a/geo-types/Cargo.toml b/geo-types/Cargo.toml index 8d46164e97..1d44c5ece4 100644 --- a/geo-types/Cargo.toml +++ b/geo-types/Cargo.toml @@ -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 @@ -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" diff --git a/geo-types/src/error.rs b/geo-types/src/error.rs index fab140efff..d955a181ad 100644 --- a/geo-types/src/error.rs +++ b/geo-types/src/error.rs @@ -1,4 +1,4 @@ -use std::fmt; +use core::fmt; #[derive(Debug)] pub enum Error { @@ -8,6 +8,7 @@ pub enum Error { }, } +#[cfg(feature = "std")] impl std::error::Error for Error {} impl fmt::Display for Error { @@ -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() { diff --git a/geo-types/src/geometry/coord.rs b/geo-types/src/geometry/coord.rs index 345d11acce..eb676369b5 100644 --- a/geo-types/src/geometry/coord.rs +++ b/geo-types/src/geometry/coord.rs @@ -100,7 +100,7 @@ impl Coord { } } -use std::ops::{Add, Div, Mul, Neg, Sub}; +use core::ops::{Add, Div, Mul, Neg, Sub}; /// Negate a coordinate. /// diff --git a/geo-types/src/geometry/geometry_collection.rs b/geo-types/src/geometry/geometry_collection.rs index 540f6ebee7..ce5bb23383 100644 --- a/geo-types/src/geometry/geometry_collection.rs +++ b/geo-types/src/geometry/geometry_collection.rs @@ -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. /// @@ -148,7 +150,7 @@ impl IndexMut for GeometryCollection { // structure helper for consuming iterator #[derive(Debug)] pub struct IntoIteratorHelper { - iter: ::std::vec::IntoIter>, + iter: ::alloc::vec::IntoIter>, } // implement the IntoIterator trait for a consuming iterator. Iteration will @@ -178,7 +180,7 @@ impl Iterator for IntoIteratorHelper { // structure helper for non-consuming iterator #[derive(Debug)] pub struct IterHelper<'a, T: CoordNum> { - iter: ::std::slice::Iter<'a, Geometry>, + iter: ::core::slice::Iter<'a, Geometry>, } // implement the IntoIterator trait for a non-consuming iterator. Iteration will @@ -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>, + iter: ::core::slice::IterMut<'a, Geometry>, } // implement the IntoIterator trait for a mutable non-consuming iterator. Iteration will @@ -323,6 +325,8 @@ where #[cfg(test)] mod tests { + use alloc::vec; + use crate::{GeometryCollection, Point}; #[test] diff --git a/geo-types/src/geometry/line_string.rs b/geo-types/src/geometry/line_string.rs index 53ed436478..39846b94e3 100644 --- a/geo-types/src/geometry/line_string.rs +++ b/geo-types/src/geometry/line_string.rs @@ -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. @@ -136,7 +138,7 @@ pub struct LineString(pub Vec>); /// A [`Point`] iterator returned by the `points` method #[derive(Debug)] -pub struct PointsIter<'a, T: CoordNum + 'a>(::std::slice::Iter<'a, Coord>); +pub struct PointsIter<'a, T: CoordNum + 'a>(::core::slice::Iter<'a, Coord>); impl<'a, T: CoordNum> Iterator for PointsIter<'a, T> { type Item = Point; @@ -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>); +pub struct CoordinatesIter<'a, T: CoordNum + 'a>(::core::slice::Iter<'a, Coord>); impl<'a, T: CoordNum> Iterator for CoordinatesIter<'a, T> { type Item = &'a Coord; @@ -358,7 +360,7 @@ impl>> FromIterator for LineString { /// Iterate over all the [`Coord`]s in this [`LineString`]. impl IntoIterator for LineString { type Item = Coord; - type IntoIter = ::std::vec::IntoIter>; + type IntoIter = ::alloc::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() @@ -377,9 +379,9 @@ impl<'a, T: CoordNum> IntoIterator for &'a LineString { /// Mutably iterate over all the [`Coordinate`]s in this [`LineString`] impl<'a, T: CoordNum> IntoIterator for &'a mut LineString { type Item = &'a mut Coord; - type IntoIter = ::std::slice::IterMut<'a, Coord>; + type IntoIter = ::core::slice::IterMut<'a, Coord>; - fn into_iter(self) -> ::std::slice::IterMut<'a, Coord> { + fn into_iter(self) -> ::core::slice::IterMut<'a, Coord> { self.0.iter_mut() } } @@ -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); } } diff --git a/geo-types/src/geometry/mod.rs b/geo-types/src/geometry/mod.rs index 02f29749a5..4faf01753a 100644 --- a/geo-types/src/geometry/mod.rs +++ b/geo-types/src/geometry/mod.rs @@ -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. /// diff --git a/geo-types/src/geometry/multi_line_string.rs b/geo-types/src/geometry/multi_line_string.rs index dc18ca98b7..5cc84b5150 100644 --- a/geo-types/src/geometry/multi_line_string.rs +++ b/geo-types/src/geometry/multi_line_string.rs @@ -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 @@ -81,7 +83,7 @@ impl>> FromIterator for MultiLineStrin impl IntoIterator for MultiLineString { type Item = LineString; - type IntoIter = ::std::vec::IntoIter>; + type IntoIter = ::alloc::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() @@ -90,7 +92,7 @@ impl IntoIterator for MultiLineString { impl<'a, T: CoordNum> IntoIterator for &'a MultiLineString { type Item = &'a LineString; - type IntoIter = ::std::slice::Iter<'a, LineString>; + type IntoIter = ::alloc::slice::Iter<'a, LineString>; fn into_iter(self) -> Self::IntoIter { (self.0).iter() @@ -99,7 +101,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiLineString { impl<'a, T: CoordNum> IntoIterator for &'a mut MultiLineString { type Item = &'a mut LineString; - type IntoIter = ::std::slice::IterMut<'a, LineString>; + type IntoIter = ::alloc::slice::IterMut<'a, LineString>; fn into_iter(self) -> Self::IntoIter { (self.0).iter_mut() diff --git a/geo-types/src/geometry/multi_point.rs b/geo-types/src/geometry/multi_point.rs index 54ff997b1d..c59622013d 100644 --- a/geo-types/src/geometry/multi_point.rs +++ b/geo-types/src/geometry/multi_point.rs @@ -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 @@ -58,7 +60,7 @@ impl>> FromIterator for MultiPoint { /// Iterate over the `Point`s in this `MultiPoint`. impl IntoIterator for MultiPoint { type Item = Point; - type IntoIter = ::std::vec::IntoIter>; + type IntoIter = ::alloc::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() @@ -67,7 +69,7 @@ impl IntoIterator for MultiPoint { impl<'a, T: CoordNum> IntoIterator for &'a MultiPoint { type Item = &'a Point; - type IntoIter = ::std::slice::Iter<'a, Point>; + type IntoIter = ::alloc::slice::Iter<'a, Point>; fn into_iter(self) -> Self::IntoIter { (self.0).iter() @@ -76,7 +78,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiPoint { impl<'a, T: CoordNum> IntoIterator for &'a mut MultiPoint { type Item = &'a mut Point; - type IntoIter = ::std::slice::IterMut<'a, Point>; + type IntoIter = ::alloc::slice::IterMut<'a, Point>; fn into_iter(self) -> Self::IntoIter { (self.0).iter_mut() diff --git a/geo-types/src/geometry/multi_polygon.rs b/geo-types/src/geometry/multi_polygon.rs index 5fbd952bec..15116353e3 100644 --- a/geo-types/src/geometry/multi_polygon.rs +++ b/geo-types/src/geometry/multi_polygon.rs @@ -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 @@ -49,7 +51,7 @@ impl>> FromIterator for MultiPolygon { impl IntoIterator for MultiPolygon { type Item = Polygon; - type IntoIter = ::std::vec::IntoIter>; + type IntoIter = ::alloc::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() @@ -58,7 +60,7 @@ impl IntoIterator for MultiPolygon { impl<'a, T: CoordNum> IntoIterator for &'a MultiPolygon { type Item = &'a Polygon; - type IntoIter = ::std::slice::Iter<'a, Polygon>; + type IntoIter = ::alloc::slice::Iter<'a, Polygon>; fn into_iter(self) -> Self::IntoIter { (self.0).iter() @@ -67,7 +69,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiPolygon { impl<'a, T: CoordNum> IntoIterator for &'a mut MultiPolygon { type Item = &'a mut Polygon; - type IntoIter = ::std::slice::IterMut<'a, Polygon>; + type IntoIter = ::alloc::slice::IterMut<'a, Polygon>; fn into_iter(self) -> Self::IntoIter { (self.0).iter_mut() diff --git a/geo-types/src/geometry/point.rs b/geo-types/src/geometry/point.rs index 0828c19f59..a95ca618fc 100644 --- a/geo-types/src/geometry/point.rs +++ b/geo-types/src/geometry/point.rs @@ -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. /// diff --git a/geo-types/src/geometry/polygon.rs b/geo-types/src/geometry/polygon.rs index 407d367b5b..a7ef579e8a 100644 --- a/geo-types/src/geometry/polygon.rs +++ b/geo-types/src/geometry/polygon.rs @@ -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))] diff --git a/geo-types/src/geometry/rect.rs b/geo-types/src/geometry/rect.rs index 5b57bab492..84e8b71e7c 100644 --- a/geo-types/src/geometry/rect.rs +++ b/geo-types/src/geometry/rect.rs @@ -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) } } diff --git a/geo-types/src/lib.rs b/geo-types/src/lib.rs index 4331d441b9..84bb21026d 100644 --- a/geo-types/src/lib.rs +++ b/geo-types/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_debug_implementations)] #![doc(html_logo_url = "https://raw.githubusercontent.com/georust/meta/master/logo/logo.png")] //! The `geo-types` library defines geometric types for the [GeoRust] ecosystem. @@ -60,12 +61,17 @@ //! //! The following optional [Cargo features] are available: //! +//! - `std`: Enables use of the full `std` library. Enabled by default. //! - `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_0_8`: Allows geometry types to be inserted into [rstar] R*-trees (`rstar v0.8`) //! - `use-rstar_0_9`: Allows geometry types to be inserted into [rstar] R*-trees (`rstar v0.9`) //! +//! This library can be used in `#![no_std]` environments if the default `std` feature is disabled. At +//! the moment, the `arbitrary` and `use-rstar_0_8` features require `std`. This may change in a +//! future release. +//! //! [approx]: https://github.com/brendanzab/approx //! [arbitrary]: https://github.com/rust-fuzz/arbitrary //! [Cargo features]: https://doc.rust-lang.org/cargo/reference/features.html @@ -75,9 +81,11 @@ //! [OGC-SFA]: https://www.ogc.org/standards/sfa //! [rstar]: https://github.com/Stoeoef/rstar //! [Serde]: https://serde.rs/ +extern crate alloc; extern crate num_traits; + +use core::fmt::Debug; use num_traits::{Float, Num, NumCast}; -use std::fmt::Debug; #[cfg(feature = "serde")] #[macro_use] @@ -131,10 +139,22 @@ mod arbitrary; #[doc(hidden)] pub mod private_utils; +#[doc(hidden)] +pub mod _alloc { + //! Needed to access these types from `alloc` in macros when the std feature is + //! disabled and the calling context is missing `extern crate alloc`. These are + //! _not_ meant for public use. + + pub use ::alloc::boxed::Box; + pub use ::alloc::vec; +} + #[cfg(test)] mod tests { + use alloc::vec; + use super::*; - use std::convert::TryFrom; + use core::convert::TryFrom; #[test] fn type_test() { diff --git a/geo-types/src/macros.rs b/geo-types/src/macros.rs index 65b3052a14..491a8e73a9 100644 --- a/geo-types/src/macros.rs +++ b/geo-types/src/macros.rs @@ -140,7 +140,7 @@ macro_rules! line_string { ) => { $crate::LineString::new( <[_]>::into_vec( - ::std::boxed::Box::new( + $crate::_alloc::Box::new( [$($coord), *] ) ) @@ -263,7 +263,7 @@ macro_rules! polygon { $($exterior_coord), * ], <[_]>::into_vec( - ::std::boxed::Box::new( + $crate::_alloc::Box::new( [ $( $crate::line_string![$($interior_coord),*] @@ -287,7 +287,7 @@ macro_rules! polygon { ) => { $crate::Polygon::new( $crate::line_string![$($coord,)*], - vec![], + $crate::_alloc::vec![], ) }; }