rolodex 0.1.2

A Forgiving VCard implementation.
Documentation
use nom::{error::VerboseError, IResult};

use std::fmt;

use crate::property::{ parse_end, parse_begin };
use crate::{ Parse, ParseError, Property };

#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct VCard<'a>(pub Vec<Property<'a>>);

impl<'a> fmt::Display for VCard<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let data = self.0.iter()
            .map(|x|format!("{}", x))
            .collect::<Vec<String>>()
            .join("\r\n");
        write!(f, "BEGIN:VCARD\r\n{}\r\nEND:VCARD", data)?;
        Ok(())
    }
}

impl<'a> VCard<'a> {
    pub fn iter(&self) -> impl Iterator<Item = &Property<'a>> {
        self.0.iter()
    }

    pub fn parse(input: &'a str) -> std::result::Result<VCard<'a>, nom::Err<ParseError>> {
        Ok(Parse::parse(input)?.1)
    }
}

impl<'a> Parse<'a> for VCard<'a> {
    fn parse(mut input: &'a str) -> IResult<&'a str, Self, ParseError> {
        use nom::bytes::complete::tag;
        let mut properties = vec![];
        match parse_begin(input) {
            Ok((remains, _)) => input = remains,
            Err(nom::Err::Incomplete(size)) => return Err(nom::Err::Incomplete(size)),
            Err(nom::Err::Error(err)) => return Err(nom::Err::Error(err.into())),
            Err(nom::Err::Failure(err)) => return Err(nom::Err::Failure(err.into()))
        }
        while let Ok((remaining, prop)) = Parse::parse(input) {
            properties.push(prop);
            match tag::<&str, &str, VerboseError<&str>>("\n")(remaining) {
                Ok((remaining, _)) => input = remaining,
                Err(_) => input = remaining,
            }
        }
        match parse_end(input) {
            Ok((remains, _)) => input = remains,
            Err(nom::Err::Incomplete(size)) => return Err(nom::Err::Incomplete(size)),
            Err(nom::Err::Error(err)) => return Err(nom::Err::Error(err.into())),
            Err(nom::Err::Failure(err)) => return Err(nom::Err::Failure(err.into()))
        }
        Ok((input, VCard(properties)))
    }
}