cartography 0.9.0

Cartography is a map rendering library for Geographic features expressed using [georust](https://georust.org/) libraries.
Documentation
use crate::{Feature, Projection};

/// Trait for Map Layers
pub trait Layer<TFeature: Feature>: Send + Sync
{
  /// Return the projection used by this layer.
  fn projection(&self) -> &Projection;
  /// Iterator over the map geometries, filtered by the given rect. The zoom level can be used to select detail of features.
  fn features<'a>(
    &'a self,
    rect: geo::Rect,
    zoom_level: f64,
  ) -> Box<dyn Iterator<Item = ccutils::containers::RefOrValue<'a, TFeature>> + 'a>;
}

#[allow(type_alias_bounds)]
pub(crate) type BoxedLayer<TFeature: Feature> = Box<dyn Layer<TFeature>>;

/// Standard implementation of a Layer containing a vector of features
pub struct FeaturesVecLayer<TFeature: Feature>
{
  projection: Projection,
  features: Vec<TFeature>,
}

impl<TFeature: Feature> FeaturesVecLayer<TFeature>
{
  /// Parse the layer as vector of features of the given type using `geojson`.
  #[cfg(feature = "geojson")]
  #[allow(clippy::result_large_err)]
  pub fn read_from_geo_json<'de, T>(
    feature_collection_reader: impl std::io::Read,
  ) -> geojson::Result<Self>
  where
    T: serde::Deserialize<'de> + Into<TFeature>,
  {
    let projection = Projection::wgs84();
    let features =
      geojson::de::deserialize_feature_collection_to_vec::<T>(feature_collection_reader)?;
    let features = features.into_iter().map(|x| x.into()).collect();
    Ok(Self {
      projection,
      features,
    })
  }
}

impl<TFeature: Feature> From<Vec<TFeature>> for FeaturesVecLayer<TFeature>
{
  fn from(features: Vec<TFeature>) -> Self
  {
    Self {
      projection: Projection::wgs84(),
      features,
    }
  }
}

impl<TFeature, TVecElement> FromIterator<TVecElement> for FeaturesVecLayer<TFeature>
where
  TFeature: Feature,
  TVecElement: Into<TFeature>,
{
  fn from_iter<T: IntoIterator<Item = TVecElement>>(iter: T) -> Self
  {
    Self {
      projection: Projection::wgs84(),
      features: iter.into_iter().map(Into::into).collect(),
    }
  }
}

impl<TFeature: Feature> Layer<TFeature> for FeaturesVecLayer<TFeature>
{
  fn projection(&self) -> &Projection
  {
    &self.projection
  }
  fn features<'a>(
    &'a self,
    rect: geo::Rect,
    _zoom_level: f64,
  ) -> Box<dyn Iterator<Item = crate::RefOrValue<'a, TFeature>> + 'a>
  {
    Box::new(
      self
        .features
        .iter()
        .filter(move |feat| feat.intersects(rect))
        .map(Into::into),
    )
  }
}

/// Trait for converting into a layer
pub trait IntoLayer<TFeature>
where
  TFeature: Feature,
{
  /// Layer type
  type Layer: Layer<TFeature>;
  /// Convert to a layer
  /// ```rust
  /// let layer = geojson::GeoJson::from_reader(reader)?.into_layer::<MyFeature>();
  /// ```
  #[must_use]
  fn into_layer(self) -> Self::Layer;
}

impl<TFeature, TOtherFeature> IntoLayer<TFeature> for Vec<TOtherFeature>
where
  TFeature: From<TOtherFeature> + Feature,
{
  type Layer = FeaturesVecLayer<TFeature>;
  fn into_layer(self) -> Self::Layer
  {
    FeaturesVecLayer::from_iter(self.into_iter().map(Into::<TFeature>::into))
  }
}