gmaps-static 0.0.1

A URL builder for Google Maps Static APIs
Documentation
use crate::{Color, Location, MarkerAppearence, MarkerScale, MarkerStyle};
use std::fmt;

#[derive(Clone)]
pub struct Marker<S: AsRef<str> + Clone> {
    appearence: Option<MarkerAppearence<S>>,
    scale: Option<MarkerScale>,
    locations: Vec<Location>,
}

impl<S: AsRef<str> + Clone> Marker<S> {
    pub fn new() -> Self {
        Marker {
            appearence: None,
            scale: None,
            locations: vec![],
        }
    }

    pub fn simple(color: &'static Color, label: char, location: Location) -> Self {
        let marker_style = MarkerStyle::new().color(color).label(label.into());
        Marker::new()
            .appearence(marker_style.into())
            .add_location(location)
    }

    pub fn add_location(&self, location: Location) -> Marker<S> {
        let mut new_marker = self.clone();
        new_marker.locations.push(location);
        new_marker
    }

    pub fn appearence(&self, appearence: MarkerAppearence<S>) -> Marker<S> {
        Marker {
            appearence: Some(appearence),
            ..(*self).clone()
        }
    }

    pub fn scale(&self, scale: MarkerScale) -> Marker<S> {
        Marker {
            scale: Some(scale),
            ..(*self).clone()
        }
    }
}

impl<S: AsRef<str> + Clone> Default for Marker<S> {
    fn default() -> Self {
        Marker::new()
    }
}

impl<S: AsRef<str> + Clone> From<Location> for Marker<S> {
    fn from(location: Location) -> Self {
        Marker {
            appearence: None,
            scale: None,
            locations: vec![location],
        }
    }
}

impl<S: AsRef<str> + Clone> fmt::Display for Marker<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut parts: Vec<String> = vec![];

        if let Some(scale) = &self.scale {
            parts.push(scale.to_string());
        }

        if let Some(appearence) = &self.appearence {
            parts.push(appearence.to_string());
        }

        for location in &self.locations {
            parts.push(location.to_string());
        }

        write!(f, "{}", parts.join("|"))
    }
}

#[cfg(test)]
mod tests {
    use crate::{MarkerIcon, BLUE};

    use super::*;
    use crate::MarkerStyle;

    #[test]
    fn it_builds_a_complete_style() {
        let marker_appearence: MarkerAppearence<String> =
            MarkerStyle::new().color(BLUE).label('S'.into()).into();
        let marker = Marker::new()
            .appearence(marker_appearence)
            .add_location("11211".into())
            .add_location("11206".into())
            .add_location("11222".into());
        assert_eq!("color:blue|label:S|11211|11206|11222", marker.to_string());
    }

    #[test]
    fn it_builds_a_complete_style_2() {
        let marker_appearence: MarkerAppearence<&str> = MarkerIcon::new("https://goo.gl/5y3S82")
            .position((32, 10).into())
            .into();
        let marker = Marker::new()
            .appearence(marker_appearence)
            .add_location("Canberra ACT".into());
        assert_eq!(
            "anchor:32,10|icon:https://goo.gl/5y3S82|Canberra ACT",
            marker.to_string()
        );
    }
}