Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse inner GeoJson members directly from str #188

Merged
merged 1 commit into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* <https://github.com/georust/geojson/pull/182>
* Overhauled front page documentation.
* <https://github.com/georust/geojson/pull/183>
* Parse `Geometry`/`Feature`/`FeatureCollection` directly from str rather than
via `GeoJson` when you know what you're expecting.
* <https://github.com/georust/geojson/pull/188>
* `Feature` now derives `Default`
* <https://github.com/georust/geojson/pull/190>

Expand Down
48 changes: 48 additions & 0 deletions src/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

use std::convert::TryFrom;
use std::str::FromStr;

use crate::errors::Error;
use crate::json::{json, Deserialize, Deserializer, JsonObject, JsonValue, Serialize, Serializer};
Expand Down Expand Up @@ -42,6 +43,14 @@ impl From<Value> for Feature {
}
}

impl FromStr for Feature {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(crate::GeoJson::from_str(s)?)
}
}

impl<'a> From<&'a Feature> for JsonObject {
fn from(feature: &'a Feature) -> JsonObject {
let mut map = JsonObject::new();
Expand Down Expand Up @@ -211,8 +220,11 @@ impl Serialize for Id {

#[cfg(test)]
mod tests {
use crate::json::json;
use crate::{feature, Error, Feature, GeoJson, Geometry, Value};

use std::str::FromStr;

fn feature_json_str() -> &'static str {
"{\"geometry\":{\"coordinates\":[1.1,2.1],\"type\":\"Point\"},\"properties\":{},\"type\":\
\"Feature\"}"
Expand Down Expand Up @@ -460,4 +472,40 @@ mod tests {
assert_eq!(feature.contains_property("foo"), false);
assert_eq!(feature.properties_iter().collect::<Vec<_>>(), vec![]);
}

#[test]
fn test_from_str_ok() {
let feature_json = json!({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
})
.to_string();

let feature = Feature::from_str(&feature_json).unwrap();
assert_eq!("Dinagat Islands", feature.property("name").unwrap());
}

#[test]
fn test_from_str_with_unexpected_type() {
let geometry_json = json!({
"type": "Point",
"coordinates": [125.6, 10.1]
})
.to_string();

let actual_failure = Feature::from_str(&geometry_json).unwrap_err();
match actual_failure {
Error::ExpectedType { actual, expected } => {
assert_eq!(actual, "Geometry");
assert_eq!(expected, "Feature");
}
e => panic!("unexpected error: {}", e),
};
}
}
62 changes: 61 additions & 1 deletion src/feature_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use std::convert::TryFrom;
use std::iter::FromIterator;
use std::str::FromStr;

use crate::errors::Error;
use crate::json::{json, Deserialize, Deserializer, JsonObject, JsonValue, Serialize, Serializer};
Expand Down Expand Up @@ -132,6 +133,14 @@ impl TryFrom<JsonValue> for FeatureCollection {
}
}

impl FromStr for FeatureCollection {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(crate::GeoJson::from_str(s)?)
}
}

impl Serialize for FeatureCollection {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -222,7 +231,10 @@ impl FromIterator<Feature> for FeatureCollection {

#[cfg(test)]
mod tests {
use crate::{Feature, FeatureCollection, Value};
use crate::json::json;
use crate::{Error, Feature, FeatureCollection, Value};

use std::str::FromStr;

#[test]
fn test_fc_from_iterator() {
Expand All @@ -244,4 +256,52 @@ mod tests {
assert_eq!(fc.features.len(), 2);
assert_eq!(fc.bbox, Some(vec![-1., -1., -1., 11., 11., 11.]));
}

#[test]
fn test_from_str_ok() {
let fc_json = json!({ "type": "FeatureCollection", "features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
},
]})
.to_string();

let feature_collection = FeatureCollection::from_str(&fc_json).unwrap();
assert_eq!(2, feature_collection.features.len());
}

#[test]
fn test_from_str_with_unexpected_type() {
let geometry_json = json!({
"type": "Point",
"coordinates": [125.6, 10.1]
})
.to_string();

let actual_failure = FeatureCollection::from_str(&geometry_json).unwrap_err();
match actual_failure {
Error::ExpectedType { actual, expected } => {
assert_eq!(actual, "Geometry");
assert_eq!(expected, "FeatureCollection");
}
e => panic!("unexpected error: {}", e),
};
}
}
50 changes: 48 additions & 2 deletions src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::str::FromStr;
use std::{convert::TryFrom, fmt};

use crate::errors::Error;
Expand Down Expand Up @@ -300,6 +301,14 @@ impl TryFrom<JsonValue> for Geometry {
}
}

impl FromStr for Geometry {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(crate::GeoJson::from_str(s)?)
}
}

impl Serialize for Geometry {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -333,9 +342,10 @@ where

#[cfg(test)]
mod tests {
use std::str::FromStr;

use crate::json::JsonObject;
use crate::{GeoJson, Geometry, Value};
use crate::json::{json, JsonObject};
use crate::{Error, GeoJson, Geometry, Value};

fn encode(geometry: &Geometry) -> String {
serde_json::to_string(&geometry).unwrap()
Expand Down Expand Up @@ -466,4 +476,40 @@ mod tests {
};
assert_eq!(decoded_geometry, geometry_collection);
}

#[test]
fn test_from_str_ok() {
let geometry_json = json!({
"type": "Point",
"coordinates": [125.6f64, 10.1]
})
.to_string();

let geometry = Geometry::from_str(&geometry_json).unwrap();
assert!(matches!(geometry.value, Value::Point(_)));
}

#[test]
fn test_from_str_with_unexpected_type() {
let feature_json = json!({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
})
.to_string();

let actual_failure = Geometry::from_str(&feature_json).unwrap_err();
match actual_failure {
Error::ExpectedType { actual, expected } => {
assert_eq!(actual, "Feature");
assert_eq!(expected, "Geometry");
}
e => panic!("unexpected error: {}", e),
};
}
}