openaip 0.2.0

OpenAIP file parser for Rust
Documentation
use std::convert::TryFrom;
use std::fmt;

use minidom::Element;

use crate::xml::ElementExt;
use crate::AltitudeReference;
use crate::AltitudeUnit;
use crate::Error;

/// # Examples
///
/// ```
/// # use openaip::{AltitudeLimit, AltitudeReference, AltitudeUnit};
/// #
/// let limit1 = AltitudeLimit::new(4500, AltitudeUnit::Feet, AltitudeReference::MSL);
///
/// let limit2 = AltitudeLimit::new(65, AltitudeUnit::FlightLevel, AltitudeReference::STD);
/// ```
#[derive(Debug)]
pub struct AltitudeLimit {
    pub reference: AltitudeReference,
    pub unit: AltitudeUnit,
    pub value: i32,
}

impl AltitudeLimit {
    pub fn new(value: i32, unit: AltitudeUnit, reference: AltitudeReference) -> Self {
        AltitudeLimit {
            reference,
            unit,
            value,
        }
    }
}

impl<'a> TryFrom<&'a Element> for AltitudeLimit {
    type Error = Error;

    fn try_from(element: &Element) -> Result<Self, Self::Error> {
        let alt = element.get_element("ALT")?;

        let reference = element.get_attr("REFERENCE")?.parse()?;
        let unit = alt.get_attr("UNIT")?.parse()?;
        let value = alt.text().parse()?;

        Ok(AltitudeLimit {
            reference,
            unit,
            value,
        })
    }
}

impl fmt::Display for AltitudeLimit {
    /// # Examples
    ///
    /// ```
    /// # use openaip::{AltitudeLimit, AltitudeReference, AltitudeUnit};
    /// #
    /// let limit = AltitudeLimit::new(4500, AltitudeUnit::Feet, AltitudeReference::MSL);
    /// assert_eq!(format!("{}", limit), "4500ft MSL");
    ///
    /// let limit = AltitudeLimit::new(65, AltitudeUnit::FlightLevel, AltitudeReference::STD);
    /// assert_eq!(format!("{}", limit), "FL65");
    ///
    /// let limit = AltitudeLimit::new(1500, AltitudeUnit::Feet, AltitudeReference::GND);
    /// assert_eq!(format!("{}", limit), "1500ft GND");
    ///
    /// let limit = AltitudeLimit::new(0, AltitudeUnit::Feet, AltitudeReference::GND);
    /// assert_eq!(format!("{}", limit), "GND");
    /// ```
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.unit == AltitudeUnit::FlightLevel {
            write!(f, "FL{}", self.value)
        } else if self.reference == AltitudeReference::GND && self.value == 0 {
            write!(f, "GND")
        } else {
            let suffix = match self.reference {
                AltitudeReference::GND => "GND",
                AltitudeReference::MSL => "MSL",
                AltitudeReference::STD => "STD",
            };
            write!(f, "{}ft {}", self.value, suffix)
        }
    }
}