contack 0.9.2

A simple and easy contact library.
Documentation
//! # `VCard`
//!
//! This contains the `VCard` struct which is used to be turned to and from
//! a text/vcard file.

use super::escape;
use crate::read_write::component::Component;
use super::component::error::ComponentParseError;
use std::fmt;
use std::str::FromStr;

/// A VCard represents an individual vcard within a vcard
/// file. For the most part this will represent `Contact`.
///
/// It implements display to allow you to convert it
/// to a text form of VCard.
#[derive(Clone, Default, Debug, Eq, PartialEq)]
pub struct VCard(pub Vec<Component>);

impl VCard {
    /// Creates a new `VCard`
    ///
    /// The vec of components does not need to include a
    /// `BEGIN`, `END` or `VERSION`.
    #[must_use]
    pub fn new(vec: Vec<Component>) -> Self {
        Self(vec)
    }

    /// Creates a vector of VCards from a string.
    ///
    /// They are separated by `END:VCARD\r\n`.
    ///
    /// # Errors
    ///
    /// Fails for the same reason as during the `FromStr`
    /// implementation.
    pub fn from_str_to_vec(s: &str) -> Result<Vec<Self>, ComponentParseError> {
        let split = s.split_inclusive("\r\nEND:VCARD\r\n");
        let mut vec = Vec::new();
        for split in split {
            vec.push(split.parse()?);
        }
        Ok(vec)
    }

    /// Converts a slice to a `String`.
    ///
    /// This creates many VCards separated by `END:VCARD`
    #[must_use]
    pub fn from_slice_to_string(v: &[Self]) -> String {
        let mut string = String::new();
        for item in v {
            string.push_str(&item.to_string());
            string.push_str("\r\n");
            string.push_str("\r\n");
        }
        string
    }
}

impl fmt::Display for VCard {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "BEGIN:VCARD\r\nVERSION:4.0\r\n")?;
        for comp in &self.0 {
            comp.fmt(f)?;
        }
        write!(f, "END:VCARD\r\n")
    }
}

impl FromStr for VCard {
    type Err = super::component::error::ComponentParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // Unfold all the lines, so that we know what to give the components
        let unfolded = escape::unfold_line(s);

        // Vec to store the components
        let mut components: Vec<Component> = Vec::new();

        // Split it by lines
        for line in unfolded.lines() {
            if !line.is_empty() {
                components.push(line.parse()?);
            }
        }

        // Remove the BEGIN and VERSION components.
        components.retain(|x| {
            x.name != "VERSION" && x.name != "BEGIN" && x.name != "END"
        });

        // Create a VCard
        Ok(Self(components))
    }
}