contack 0.9.2

A simple and easy contact library.
Documentation
#[cfg(feature = "read_write")]
use crate::read_write::component::Component;
#[cfg(feature = "read_write")]
use crate::FromComponentError;

/// The components correspond to the sex (biological) and gender identity.
#[derive(Debug, Clone, PartialEq, PartialOrd, Default)]
pub struct Gender {
    /// The biological sex of the contact.
    pub sex: Option<Sex>,
    /// The gender identity of the contact. Free-form as
    /// to allow it to be set to whatever gender the
    /// contact prefers.
    ///
    /// As a side not sorry for using the term identity,
    /// I know its not correct but I am trying to keep
    /// both backwards compatability and compatability with
    /// the standard. It should be `gender` but oh well.
    pub identity: Option<String>,
}

/// A sex component, representing a biological sex.
#[derive(Debug, Clone, PartialEq, PartialOrd, Copy)]
pub enum Sex {
    /// Male sex, XY chromosomes
    Male,
    /// Female sex, XX chromosomes
    Female,
    /// Intersex - ambigouous sex
    Other,
    /// Unnknown, probably should just be represented
    /// by a `None` value on [`Gender`] anyway.
    Unknown,
}

impl From<Sex> for char {
    fn from(s: Sex) -> Self {
        match s {
            Sex::Male => 'M',
            Sex::Female => 'F',
            Sex::Other => 'O',
            Sex::Unknown => 'U',
        }
    }
}

#[cfg(feature = "read_write")]
impl From<Gender> for Component {
    fn from(gender: Gender) -> Self {
        Self {
            name: "GENDER".to_string(),
            values: {
                let mut vec = Vec::with_capacity(2);
                vec.push(
                    vec![
                        gender.sex.map_or('N', char::from).to_string(),
                    ],
                );
                if let Some(identity) = gender.identity {
                    vec.push(vec![identity]);
                }
                vec
            },
            ..Self::default()
        }
    }
}

#[cfg(feature = "read_write")]
impl TryFrom<Component> for Gender {
    type Error = FromComponentError;

    fn try_from(mut comp: Component) -> Result<Self, Self::Error> {
        Ok(Self {
            sex: match comp
                    .values
                    .get_mut(0)
                    .and_then(Vec::pop).as_deref() {
                        None | Some("N") => None,
                        Some("M") => Some(Sex::Male),
                        Some("F") => Some(Sex::Female),
                        Some("O") => Some(Sex::Other),
                        Some("U") => Some(Sex::Unknown),
                        _ => return Err(FromComponentError::InvalidRegex),
                    },
            identity: comp
                .values
                .get_mut(1)
                .and_then(Vec::pop),
        })
    }
}