geojson 0.3.0

Library for serializing the GeoJSON vector GIS file format
Documentation
// Copyright 2015 The GeoRust Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::str::FromStr;

#[cfg(not(feature = "with-serde"))]
use ::json::ToJson;
#[cfg(feature = "with-serde")]
use ::json::{Serialize, Deserialize, Serializer, Deserializer, SerdeError};

use ::json::{JsonValue, JsonObject};

use ::{Error, Geometry, Feature, FeatureCollection, FromObject};


/// GeoJSON Objects
///
/// [GeoJSON Format Specification ยง 2]
/// (http://geojson.org/geojson-spec.html#geojson-objects)
#[derive(Clone, Debug, PartialEq)]
pub enum GeoJson {
    Geometry(Geometry),
    Feature(Feature),
    FeatureCollection(FeatureCollection),
}

impl<'a> From<&'a GeoJson> for JsonObject {
    fn from(geojson: &'a GeoJson) -> JsonObject {
        return match *geojson {
            GeoJson::Geometry(ref geometry) => geometry.into(),
            GeoJson::Feature(ref feature) => feature.into(),
            GeoJson::FeatureCollection(ref fc) => fc.into(),
        };
    }
}


impl FromObject for GeoJson {
    fn from_object(object: &JsonObject) -> Result<Self, Error> {
        let type_ = expect_string!(expect_property!(object, "type", "Missing 'type' field"));
        return match &type_ as &str {
            "Point" | "MultiPoint" | "LineString" | "MultiLineString" | "Polygon" | "MultiPolygon" =>
                Geometry::from_object(object).map(GeoJson::Geometry),
            "Feature" =>
                Feature::from_object(object).map(GeoJson::Feature),
            "FeatureCollection" =>
                FeatureCollection::from_object(object).map(GeoJson::FeatureCollection),
            _ => Err(Error::GeoJsonUnknownType),
        };
    }
}

#[cfg(not(feature = "with-serde"))]
impl ToJson for GeoJson {
    fn to_json(&self) -> JsonValue {
        return ::rustc_serialize::json::Json::Object(self.into());
    }
}

#[cfg(feature = "with-serde")]
impl Serialize for GeoJson {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
    where S: Serializer {
        JsonObject::from(self).serialize(serializer)
    }
}

#[cfg(feature = "with-serde")]
impl Deserialize for GeoJson {
    fn deserialize<D>(deserializer: &mut D) -> Result<GeoJson, D::Error>
    where D: Deserializer {
        use std::error::Error as StdError;

        let val = try!(JsonValue::deserialize(deserializer));

        if let Some(geo) = val.as_object() {
            GeoJson::from_object(geo).map_err(|e| D::Error::custom(e.description()))
        }
        else {
            Err(D::Error::custom("expected json object"))
        }
    }
}

impl FromStr for GeoJson {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let object = try!(get_object(s));

        return GeoJson::from_object(&object);
    }
}

#[cfg(not(feature = "with-serde"))]
fn get_object(s: &str) -> Result<JsonObject, Error> {
    let decoded_json = match JsonValue::from_str(s) {
        Ok(j) => j,
        Err(..) => return Err(Error::MalformedJson),
    };
    match decoded_json {
        ::rustc_serialize::json::Json::Object(object) => Ok(object),
        _ => return Err(Error::GeoJsonExpectedObject),
    }
}
#[cfg(feature = "with-serde")]
fn get_object(s: &str) -> Result<JsonObject, Error> {
    let decoded_json: ::serde_json::Value = match ::serde_json::from_str(s) {
        Ok(j) => j,
        Err(..) => return Err(Error::MalformedJson),
    };

    if let Some(geo) = decoded_json.as_object() {
        return Ok(geo.clone());
    }
    else {
        return Err(Error::MalformedJson);
    }
}

#[cfg(not(feature = "with-serde"))]
impl ToString for GeoJson {
    fn to_string(&self) -> String {
        return self.to_json().to_string();
    }
}
#[cfg(feature = "with-serde")]
impl ToString for GeoJson {
    fn to_string(&self) -> String {
        return ::serde_json::to_string(self).unwrap_or(String::new());
    }
}