boreholeio 0.1.0

A library for interacting with borehole.io, a subsurface data management, delivery and visualisation platform
Documentation
use serde::{Deserialize, Serialize};

/// Just a `geo_types::Point<f64>` wrapper which allows us to implement methods
/// and traits on it. In particular, `geojson` serialization format is used.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Location {
    /// For more details, please refer to:
    /// https://docs.rs/geojson/latest/geojson/ser/index.html
    #[serde(
        serialize_with = "geojson::ser::serialize_geometry",
        deserialize_with = "geojson::de::deserialize_geometry"
    )]
    inner: geo::Point<f64>,
}

impl Location {
    pub fn new(x: f64, y: f64) -> Self {
        Self {
            inner: geo::Point::new(x, y),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    // Auxiliary data structure for de-/serialization testing.
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    #[serde_with::skip_serializing_none]
    struct S {
        pub location: Option<Location>,
    }

    // Verifies that `Some` field value is serialized and deserialized properly.
    #[test]
    fn serialization_roundtrip_some() {
        let ground_truth = S {
            location: Some(Location::new(3.14, 15.92)),
        };

        let serialized = serde_json::to_string(&ground_truth).unwrap();
        // This is a very important part because `geo_types::Point` has its own
        // serialization format which differs from the `geojson`'s one (it has
        // `x` and `y` fields instead of `[f64; 2]`). The check below verifies
        // the `geojson` format is used.
        assert_eq!(
            serialized,
            "{\"location\":{\"inner\":{\"type\":\"Point\",\"coordinates\":[3.14,15.92]}}}"
        );

        let deserialized: S = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, ground_truth);
    }

    // Verifies that `None` field value is serialized and deserialized properly.
    #[test]
    fn serialization_roundtrip_none() {
        let ground_truth = S { location: None };
        let serialized = serde_json::to_string(&ground_truth).unwrap();
        let deserialized: S = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, ground_truth);
    }

    // Verifies that deserializing invalid data errors out properly.
    #[test]
    fn deserializing_invalid_data_errors_out() {
        for invalid_str in [
            // `geojson` format with a typo.
            "{\"location\":{\"type\":\"Point\",\"coordinates\":[3.14a,15.92]}}",
            // `geo_types` format.
            "{\"location\":{\"inner\":{\"x\":3.14,\"y\":15.92}}}",
        ] {
            assert!(serde_json::from_str::<S>(invalid_str).is_err());
        }
    }
}