From a1b9d5ef4aacbddc62d1f986ae9834c352e557ad Mon Sep 17 00:00:00 2001 From: Zach Heylmun Date: Thu, 29 Aug 2024 03:32:20 -0700 Subject: [PATCH] Add Serde support behind feature flag (#5) * start adding serde feature * Finish adding serde derives * Switch from forbid to deny, false positive is resolved with newer machinery https://github.com/rust-lang/rust/issues/81670 * ask codecov to ignore the derives * Fix some clippy warnings from newer rust version --- Cargo.toml | 6 ++++-- src/angle.rs | 1 + src/ellipsoidal/ellipsoid.rs | 1 + src/length.rs | 1 + src/lib.rs | 3 +-- src/local_frame.rs | 18 +++++++++++------- src/mat33.rs | 1 + src/positions.rs | 4 ++++ src/speed.rs | 3 ++- src/spherical/cap.rs | 1 + src/spherical/great_circle.rs | 1 + src/spherical/minor_arc.rs | 1 + src/spherical/rectangle.rs | 3 +++ src/spherical/sloop.rs | 5 ++++- src/spherical/sphere.rs | 1 + src/vec3.rs | 1 + src/vehicle.rs | 1 + 17 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4f40b43..1126858 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,16 +3,18 @@ name = "jord" version = "0.15.0" edition = "2021" rust-version = "1.65" -authors = ["Cedric Liegeois ", - ] +authors = ["Cedric Liegeois "] repository = "https://github.com/ofmooseandmen/jord-rs" documentation = "https://docs.rs/jord" keywords = ["geo", "geography", "geospatial", "n-vector"] description = "Geographical Position Calculations (Ellipsoidal and Spherical models)" license = "MIT" readme = "README.md" +[features] +serde = ["dep:serde"] [dependencies] +serde = { version = "1", optional = true, features = ["derive"] } [dev-dependencies] criterion = { version = "0.5.1", features = ["html_reports"] } diff --git a/src/angle.rs b/src/angle.rs index ac7f9df..be02a40 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -2,6 +2,7 @@ use crate::{impl_measurement, Measurement}; use std::f64::consts::PI; #[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this /// A one-dimensional angle. /// /// It primarely exists to unambigously represent an angle as opposed to a bare diff --git a/src/ellipsoidal/ellipsoid.rs b/src/ellipsoidal/ellipsoid.rs index b479984..e4c2d0f 100644 --- a/src/ellipsoidal/ellipsoid.rs +++ b/src/ellipsoidal/ellipsoid.rs @@ -4,6 +4,7 @@ use crate::{ /// An ellipsoid. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Ellipsoid { equatorial_radius: Length, polar_radius: Length, diff --git a/src/length.rs b/src/length.rs index f103ad0..8a00f0e 100644 --- a/src/length.rs +++ b/src/length.rs @@ -1,6 +1,7 @@ use crate::{impl_measurement, Angle, Measurement}; #[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this /// A length. /// /// It primarely exists to unambigously represent a length as opposed to a bare diff --git a/src/lib.rs b/src/lib.rs index d20fe7c..2e8bccb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ #![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))] -#![forbid( +#![deny( anonymous_parameters, - illegal_floating_point_literal_pattern, late_bound_lifetime_arguments, path_statements, patterns_in_fns_without_body, diff --git a/src/local_frame.rs b/src/local_frame.rs index 2415f4b..ecb14ed 100644 --- a/src/local_frame.rs +++ b/src/local_frame.rs @@ -4,6 +4,7 @@ use crate::{ }; #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this enum Orientation { // x = north (or forward), y = east (or right), z = down. #[default] @@ -18,9 +19,11 @@ enum Orientation { /// The orientation of the x, y and z axis depends on the [local Cartesian coordinate frame](crate::LocalFrame): /// - x = north (or forward), y = east (or right), z = down: [NED](crate::LocalFrame::ned), [Body](crate::LocalFrame::body) and [Local Level](crate::LocalFrame::local_level), /// - x = east, y = north, z = up: [ENU](crate::LocalFrame::enu). +/// /// However, the [azimuth](crate::LocalPositionVector::azimuth) is always relative to 'north' and the elevation is always positive if above the local /// tangent plane and negative if below. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct LocalPositionVector { x: Length, y: Length, @@ -185,6 +188,7 @@ impl Cartesian3DVector for LocalPositionVector { /// calculations are needed in a limited area, position calculations can be performed /// relative to this system to get approximate horizontal and vertical components #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct LocalFrame { origin: Vec3, dir_rm: Mat33, @@ -200,7 +204,7 @@ where /// East-North-Up (local level) frame. This frame is useful for many targeting and tracking applications. /// /// - Orientation: The x-axis points towards east, the y-axis points towards north (both are - /// horizontal), and the z-axis is pointing up. + /// horizontal), and the z-axis is pointing up. /// /// See also [NED](crate::LocalFrame::ned) pub fn enu(origin: GeodeticPos, surface: S) -> Self { @@ -228,7 +232,7 @@ where /// /// - The origin is directly beneath or above the vehicle (B), at Earth’s surface. /// - Orientation: The x-axis points towards north, the y-axis points towards east (both are - /// horizontal), and the z-axis is pointing down. + /// horizontal), and the z-axis is pointing down. /// /// Note: When moving relative to the Earth, the frame rotates about its z-axis to allow the /// x-axis to always point towards north. When getting close to the poles this rotation rate @@ -279,10 +283,10 @@ where /// /// - The origin is directly beneath or above the vehicle (B), at Earth’s surface. /// - Orientation: The z-axis is pointing down. Initially, the x-axis points towards north, and the - /// y-axis points towards east, but as the vehicle moves they are not rotating about the z-axis - /// (their angular velocity relative to the Earth has zero component along the z-axis). - /// (Note: Any initial horizontal direction of the x- and y-axes is valid for L, but if the - /// initial position is outside the poles, north and east are usually chosen for convenience.) + /// y-axis points towards east, but as the vehicle moves they are not rotating about the z-axis + /// (their angular velocity relative to the Earth has zero component along the z-axis). + /// (Note: Any initial horizontal direction of the x- and y-axes is valid for L, but if the + /// initial position is outside the poles, north and east are usually chosen for convenience.) /// /// Notes: The L-frame is equal to the N-frame except for the rotation about the z-axis, /// which is always zero for this frame (relative to Earth). Hence, at a given time, the only @@ -304,7 +308,7 @@ where } /// Converts the given [GeodeticPos] into a [LocalPositionVector]: the exact vector between this frame - /// origin and the given position. The resulting [LocalPositionVector] orientation is the one of this frame. + /// origin and the given position. The resulting [LocalPositionVector] orientation is the one of this frame. pub fn geodetic_to_local_pos(&self, p: GeodeticPos) -> LocalPositionVector { let p_geocentric = self.surface.geodetic_to_geocentric(p).as_metres(); // delta in 'Earth' frame. diff --git a/src/mat33.rs b/src/mat33.rs index da00380..7d8bedf 100644 --- a/src/mat33.rs +++ b/src/mat33.rs @@ -2,6 +2,7 @@ use crate::Vec3; /// A 3*3 matrix. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Mat33 { r0: Vec3, r1: Vec3, diff --git a/src/positions.rs b/src/positions.rs index 0a9010c..1855988 100644 --- a/src/positions.rs +++ b/src/positions.rs @@ -51,6 +51,7 @@ pub trait Cartesian3DVector: Sized { /// A geocentric position or Earth Centred Earth Fixed (ECEF) vector. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct GeocentricPos { x: Length, y: Length, @@ -104,6 +105,7 @@ impl Cartesian3DVector for GeocentricPos { /// A geodetic position: the horiztonal coordinates (as a [NVector]) and height above the surface. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct GeodeticPos { hp: NVector, height: Length, @@ -130,6 +132,7 @@ impl GeodeticPos { /// An horizontal position represented by a pair of latitude-longitude. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct LatLong { latitude: Angle, longitude: Angle, @@ -223,6 +226,7 @@ impl LatLong { /// - z-axis points to the North Pole along the body's rotation axis, /// - x-axis points towards the point where latitude = longitude = 0 #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct NVector(Vec3); impl NVector { diff --git a/src/speed.rs b/src/speed.rs index 2e037bd..287df26 100644 --- a/src/speed.rs +++ b/src/speed.rs @@ -3,6 +3,7 @@ use std::time::Duration; use crate::{impl_measurement, Length, Measurement}; #[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this /// A speed. /// /// It primarely exists to unambigously represent a speed as opposed to a bare @@ -54,7 +55,7 @@ use crate::{impl_measurement, Length, Measurement}; /// Length::from_nautical_miles(2.0), /// (Speed::from_knots(1.0) * Duration::from_secs(7200)).round_mm() /// ); -/// +/// /// ``` pub struct Speed { mps: f64, diff --git a/src/spherical/cap.rs b/src/spherical/cap.rs index ba0dcd6..7434fdc 100644 --- a/src/spherical/cap.rs +++ b/src/spherical/cap.rs @@ -7,6 +7,7 @@ use super::Sphere; /// A [spherical cap](https://en.wikipedia.org/wiki/Spherical_cap): a portion of a sphere cut off by a plane. /// This struct and implementation is very much based on [S2Cap](https://github.com/google/s2geometry/blob/master/src/s2/s2cap.h). #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Cap { centre: NVector, chord_radius2: f64, diff --git a/src/spherical/great_circle.rs b/src/spherical/great_circle.rs index 7c09da0..a6fe646 100644 --- a/src/spherical/great_circle.rs +++ b/src/spherical/great_circle.rs @@ -9,6 +9,7 @@ use super::base::easting; /// It is internally represented as its normal vector - i.e. the normal vector /// to the plane containing the great circle. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct GreatCircle { normal: Vec3, } diff --git a/src/spherical/minor_arc.rs b/src/spherical/minor_arc.rs index cb8237c..63b6c4e 100644 --- a/src/spherical/minor_arc.rs +++ b/src/spherical/minor_arc.rs @@ -8,6 +8,7 @@ use super::base::{angle_radians_between, exact_side}; /// Oriented minor arc of a great circle between two positions: shortest path between positions /// on a great circle. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct MinorArc { start: NVector, end: NVector, diff --git a/src/spherical/rectangle.rs b/src/spherical/rectangle.rs index 9369bc7..9c634dd 100644 --- a/src/spherical/rectangle.rs +++ b/src/spherical/rectangle.rs @@ -11,6 +11,7 @@ use super::MinorArc; /// /// This struct and implementation is very much based on [S2LatLngRect](https://github.com/google/s2geometry/blob/master/src/s2/s2latlng_rect.h). #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Rectangle { lat: LatitudeInterval, lng: LongitudeInterval, @@ -317,6 +318,7 @@ impl Rectangle { /// latitude interval: {@link #lo} is assumed to be less than {@link #hi}, otherwise the interval is empty. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this struct LatitudeInterval { lo: Angle, hi: Angle, @@ -450,6 +452,7 @@ impl LatitudeInterval { } #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this struct LongitudeInterval { lo: Angle, hi: Angle, diff --git a/src/spherical/sloop.rs b/src/spherical/sloop.rs index bc45398..5f02357 100644 --- a/src/spherical/sloop.rs +++ b/src/spherical/sloop.rs @@ -17,6 +17,7 @@ use super::{ /// - [simple](crate::spherical::Loop::is_simple) - this property is not enforced at runtime, therefore operations are undefined on non-simple loops /// - or, [empty](crate::spherical::Loop::is_empty). #[derive(PartialEq, Clone, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Loop { /// vertices in clockwise order. vertices: Vec, @@ -531,7 +532,7 @@ impl Loop { } /// Triangulates this loop using the [Ear Clipping](https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf) method. - /// + /// /// This method returns either ([loop number vertices](crate::spherical::Loop::num_vertices) - 2) triangles - as triples of [NVector]s, if /// the triangulation succeeds, or [empty](Vec::new) if the triangulation fails - which should only occur for [non simple](crate::spherical::Loop::is_simple) loops. /// @@ -661,6 +662,7 @@ pub fn is_loop_clockwise(vs: &[NVector]) -> bool { } #[derive(PartialEq, Clone, Copy, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this enum Classification { Convex, Reflex, @@ -670,6 +672,7 @@ enum Classification { /// A vertex of a loop: position + classification. #[derive(PartialEq, Clone, Copy, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this struct Vertex(NVector, Classification); /// if first == last, returns [first ... last - 1] otherwise returns given array. diff --git a/src/spherical/sphere.rs b/src/spherical/sphere.rs index 363494b..57b9acd 100644 --- a/src/spherical/sphere.rs +++ b/src/spherical/sphere.rs @@ -14,6 +14,7 @@ use super::{ /// /// [Sphere] implements several usefull navigation algorithms. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Sphere { radius: Length, } diff --git a/src/vec3.rs b/src/vec3.rs index bff41f9..ddf5984 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -3,6 +3,7 @@ /// [Vec3] implements many traits, including [Add](::std::ops::Add), [Sub](::std::ops::Sub), /// [Mul](::std::ops::Mul) and [Div](::std::ops::Div), among others. #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Vec3 { x: f64, y: f64, diff --git a/src/vehicle.rs b/src/vehicle.rs index f34d68b..20ceadb 100644 --- a/src/vehicle.rs +++ b/src/vehicle.rs @@ -2,6 +2,7 @@ use crate::{Angle, NVector, Speed}; /// The state of a vehicle: its horizontal position and velocity (bearing and speed). #[derive(PartialEq, Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] // codecov:ignore:this pub struct Vehicle { position: NVector, bearing: Angle,