#vcard #contact #parser #rfc-6350

vcard4

Fast and correct vCard parser for RFC6350

15 releases

0.5.0 Feb 9, 2024
0.4.4 Apr 18, 2023
0.4.3 Mar 20, 2023
0.3.3 Mar 10, 2023
0.1.4 Nov 9, 2022

#919 in Parser implementations

Download history 160/week @ 2023-12-03 98/week @ 2023-12-10 44/week @ 2023-12-17 45/week @ 2024-01-07 152/week @ 2024-01-14 25/week @ 2024-01-21 70/week @ 2024-01-28 86/week @ 2024-02-04 17/week @ 2024-02-18 72/week @ 2024-02-25 45/week @ 2024-03-03 17/week @ 2024-03-10 8/week @ 2024-03-17

143 downloads per month
Used in 4 crates (2 directly)

MIT/Apache

155KB
4K SLoC

vCard

Fast and correct vCard parser based on RFC6350; see the API documentation for more information.

License is MIT or Apache-2.0.


lib.rs:

Fast and correct vCard parser based on RFC6350.

vCards inherently contain private information so this library implements a zeroize feature (which is enabled by default) to securely zero the memory for all the data in a vCard when it is dropped.

Certain external types cannot be zeroize'd due to the restrictions on implementing external traits on external types and are therefore exempt:

  • Uri
  • Time / UtcOffset / OffsetDateTime
  • LanguageTag (feature: language-tags)
  • Mime (feature: mime)

If the mime feature is enabled the MEDIATYPE parameter is parsed to a Mime struct otherwise it is a String.

If the language-tags feature is enabled the LANG property and the LANGUAGE parameter are parsed using the language-tags crate.

Serde support can be enabled with the serde feature.

Examples

Create a new vCard:

use vcard4::VcardBuilder;
let card = VcardBuilder::new("John Doe".to_owned())
    .nickname("Johnny".to_owned())
    .finish();
print!("{}", card);

Decoding and encoding:

use anyhow::Result;
use vcard4::parse;
pub fn main() -> Result<()> {
    let input = r#"BEGIN:VCARD
VERSION:4.0
FN:John Doe
NICKNAME:Johnny
END:VCARD"#;
    let cards = parse(input)?;
    let card = cards.first().unwrap();
    let encoded = card.to_string();
    let decoded = parse(&encoded)?.remove(0);
    assert_eq!(card, &decoded);
    Ok(())
}

Iterative parsing is useful if you only need the first vCard or wish to ignore vCards that have errors (possibly during an import operation):

use anyhow::Result;
use vcard4::iter;

pub fn main() -> Result<()> {
    let input = r#"BEGIN:VCARD
VERSION:4.0
FN:John Doe
END:VCARD

BEGIN:VCARD
VERSION:4.0
FN:Jane Doe
END:VCARD"#;
    let mut it = iter(input, true);
    print!("{}", it.next().unwrap()?);
    print!("{}", it.next().unwrap()?);
    assert!(matches!(it.next(), None));
    Ok(())
}

Implementation

  • The XML property is parsed and propagated but it is not validated as it is optional in the RFC.
  • IANA Tokens are not implemented.
  • The RFC requires a CRLF sequence for line breaks but for easier interoperability between platforms we treat the carriage return as optional.

Dependencies

~5.5MB
~71K SLoC