{"id":21585994,"url":"https://github.com/magiclen/vcard","last_synced_at":"2025-04-10T20:14:58.288Z","repository":{"id":47575912,"uuid":"156332245","full_name":"magiclen/vcard","owner":"magiclen","description":"A pure Rust implementation of vCard based on RFC 6350.","archived":false,"fork":false,"pushed_at":"2023-09-09T05:05:58.000Z","size":185,"stargazers_count":21,"open_issues_count":2,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T17:55:17.991Z","etag":null,"topics":["rust","vcard"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/magiclen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-06T05:46:54.000Z","updated_at":"2025-01-09T19:27:23.000Z","dependencies_parsed_at":"2024-11-24T18:00:29.951Z","dependency_job_id":null,"html_url":"https://github.com/magiclen/vcard","commit_stats":{"total_commits":55,"total_committers":2,"mean_commits":27.5,"dds":"0.018181818181818188","last_synced_commit":"55ccb143b27e9826d7f288403a6e6c07adc78085"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Fvcard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Fvcard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Fvcard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Fvcard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magiclen","download_url":"https://codeload.github.com/magiclen/vcard/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247814898,"owners_count":21000664,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rust","vcard"],"created_at":"2024-11-24T15:12:21.248Z","updated_at":"2025-04-10T20:14:58.262Z","avatar_url":"https://github.com/magiclen.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"vCard\n====================\n\n[![CI](https://github.com/magiclen/vcard/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/vcard/actions/workflows/ci.yml)\n\nA pure Rust implementation of vCard based on RFC 6350.\n\n## Example\n\n```rust\nuse std::collections::HashSet;\n\nuse vcard::{Set, VCard, XPropertyName, IanaToken};\nuse vcard::properties::*;\nuse vcard::values::text::{Text, Component};\nuse vcard::values::language_tag::LanguageTag;\nuse vcard::values::name_value::NameValue;\nuse vcard::values::image_value::ImageValue;\nuse vcard::values::date_time::{DateAndOrTime, Date, Timestamp};\nuse vcard::values::gender_value::{GenderValue, SexType};\nuse vcard::values::address_value::AddressValue;\nuse vcard::values::type_value::{TypeValue, TypeValueWithTelephoneType};\nuse vcard::values::telephone_value::TelephoneValue;\nuse vcard::values::email_value::EmailValue;\nuse vcard::values::url;\n\nuse vcard::parameters::language::Language;\nuse vcard::parameters::typ::{Type, TypeWithTelType};\n\nuse vcard::chrono::prelude::*;\n\nlet formatted_names = {\n    let mut formatted_names = HashSet::new();\n\n    let english_name = {\n        let mut formatted_name = FormattedName::from_text(Text::from_str(\"David Wang\").unwrap());\n        formatted_name.language = Some(Language::from_language_tag(LanguageTag::from_str(\"en\").unwrap()));\n\n        formatted_name\n    };\n\n    formatted_names.insert(english_name);\n\n    let chinese_name = {\n        let mut formatted_name = FormattedName::from_text(Text::from_str(\"王大衛\").unwrap());\n        formatted_name.language = Some(Language::from_language_tag(LanguageTag::from_str(\"zh\").unwrap()));\n\n        formatted_name\n    };\n\n    formatted_names.insert(chinese_name);\n\n    formatted_names\n};\n\nlet mut vcard = VCard::from_formatted_names(Set::from_hash_set(formatted_names).unwrap()).unwrap();\n\nlet names = {\n    let mut names = HashSet::new();\n\n    let name = {\n        let name_value = NameValue::from_components(\n            Some(Component::from_str(\"Wang\").unwrap()),\n            Some(Component::from_str(\"David\").unwrap()),\n            None,\n            Some(Component::from_str(\"Dr.\").unwrap()),\n            None,\n        );\n\n        Name::from_name_value(name_value)\n    };\n\n    names.insert(name);\n\n    names\n};\n\nvcard.names = Some(Set::from_hash_set(names).unwrap());\n\nlet photos = {\n    let mut photos = HashSet::new();\n\n    let photo = {\n        let image_value = ImageValue::from_file(\"photo.png\").unwrap();\n\n        Photo::from_image_value(image_value)\n    };\n\n    photos.insert(photo);\n\n    photos\n};\n\nvcard.photos = Some(Set::from_hash_set(photos).unwrap());\n\nlet birthdays = {\n    let mut birthdays = HashSet::new();\n\n    let birthday = {\n        Birthday::from_date_and_or_time(DateAndOrTime::Date(Date::from_year_month_day(1993, 7, 7).unwrap()))\n    };\n\n    birthdays.insert(birthday);\n\n    birthdays\n};\n\nvcard.birthdays = Some(Set::from_hash_set(birthdays).unwrap());\n\nvcard.gender = Some(Gender::from_gender_value(GenderValue::from_sex_type(SexType::Male)));\n\nlet addresses = {\n    let mut addresses = HashSet::new();\n\n    let home_address = {\n        let address_value = AddressValue::from_components(\n            None,\n            Some(Component::from_str(\"No.5\").unwrap()),\n            Some(Component::from_str(\"Section 5, Xinyi Road, Xinyi District\").unwrap()),\n            Some(Component::from_str(\"Taipei City\").unwrap()),\n            None,\n            Some(Component::from_str(\"110\").unwrap()),\n            Some(Component::from_str(\"Taiwan\").unwrap()),\n        );\n\n        let mut address = Address::from_address_value(address_value);\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValue::Home);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        address.typ = Some(Type::from_type_values(type_values));\n\n        address\n    };\n\n    addresses.insert(home_address);\n\n    let work_address = {\n        let address_value = AddressValue::from_components(\n            None,\n            Some(Component::from_str(\"No.3\").unwrap()),\n            Some(Component::from_str(\"Beiping West Road, Zhongzheng District\").unwrap()),\n            Some(Component::from_str(\"Taipei City\").unwrap()),\n            None,\n            Some(Component::from_str(\"100\").unwrap()),\n            Some(Component::from_str(\"Taiwan\").unwrap()),\n        );\n\n        let mut address = Address::from_address_value(address_value);\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValue::Work);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        address.typ = Some(Type::from_type_values(type_values));\n\n        address\n    };\n\n    addresses.insert(work_address);\n\n    addresses\n};\n\nvcard.addresses = Some(Set::from_hash_set(addresses).unwrap());\n\nlet telephones = {\n    let mut telephones = HashSet::new();\n\n    let home_phone = {\n        let mut telephone = Telephone::from_telephone_value(TelephoneValue::from_telephone_number_str(\n            \"+886 02 1234 5678\",\n            None::\u003c\u0026str\u003e,\n        ).unwrap());\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValueWithTelephoneType::Home);\n            type_values.insert(TypeValueWithTelephoneType::Voice);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        if let Telephone::TelephoneValue { ref mut typ, .. } = telephone {\n            *typ = Some(TypeWithTelType::from_type_values(type_values));\n        }\n\n        telephone\n    };\n\n    telephones.insert(home_phone);\n\n    let cell_phone = {\n        let mut telephone = Telephone::from_telephone_value(TelephoneValue::from_telephone_number_str(\n            \"+886 987 654 321\",\n            None::\u003c\u0026str\u003e,\n        ).unwrap());\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValueWithTelephoneType::Cell);\n            type_values.insert(TypeValueWithTelephoneType::Voice);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        if let Telephone::TelephoneValue { ref mut typ, .. } = telephone {\n            *typ = Some(TypeWithTelType::from_type_values(type_values));\n        }\n\n        telephone\n    };\n\n    telephones.insert(cell_phone);\n\n    let work_phone = {\n        let mut telephone = Telephone::from_telephone_value(TelephoneValue::from_telephone_number_str(\n            \"+886 02 8888 8888\",\n            Some(\"532\"),\n        ).unwrap());\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValueWithTelephoneType::Work);\n            type_values.insert(TypeValueWithTelephoneType::Voice);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        if let Telephone::TelephoneValue { ref mut typ, .. } = telephone {\n            *typ = Some(TypeWithTelType::from_type_values(type_values));\n        }\n\n        telephone\n    };\n\n    telephones.insert(work_phone);\n\n    telephones\n};\n\nvcard.telephones = Some(Set::from_hash_set(telephones).unwrap());\n\nlet emails = {\n    let mut emails = HashSet::new();\n\n    let personal_email = {\n        let mut email = Email::from_email_value(EmailValue::from_str(\"david@gmail.com\").unwrap());\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValue::Home);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        email.typ = Some(Type::from_type_values(type_values));\n\n        email\n    };\n\n    emails.insert(personal_email);\n\n    let work_email = {\n        let mut email = Email::from_email_value(EmailValue::from_str(\"david@thaumaturgiclen.com\").unwrap());\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValue::Work);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        email.typ = Some(Type::from_type_values(type_values));\n\n        email\n    };\n\n    emails.insert(work_email);\n\n    emails\n};\n\nvcard.emails = Some(Set::from_hash_set(emails).unwrap());\n\nlet urls = {\n    let mut urls = HashSet::new();\n\n    let company_site = {\n        let mut url = URL::from_url(url::URL::from_str(\"https://職員.thaumaturgiclen.com:444/王大衛\").unwrap());\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValue::Work);\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        url.typ = Some(Type::from_type_values(type_values));\n\n        url\n    };\n\n    urls.insert(company_site);\n\n    urls\n};\n\nvcard.urls = Some(Set::from_hash_set(urls).unwrap());\n\nlet x_properties = {\n    let mut x_properties = HashSet::new();\n\n    let facebook = {\n        let mut x_socialprofile = XProperty::from_text(XPropertyName::from_str(\"X-SOCIALPROFILE\").unwrap(), Text::from_str(\"https://www.facebook.com/david.vard.wang\").unwrap());\n\n        let type_values = {\n            let mut type_values = HashSet::new();\n\n            type_values.insert(TypeValue::IanaToken(IanaToken::from_str(\"facebook\").unwrap()));\n\n            Set::from_hash_set(type_values).unwrap()\n        };\n\n        x_socialprofile.typ = Some(Type::from_type_values(type_values));\n\n        x_socialprofile\n    };\n\n    x_properties.insert(facebook);\n\n    x_properties\n};\n\nvcard.x_properties = Some(Set::from_hash_set(x_properties).unwrap());\n\n//    vcard.revision = Some(Revision::now()); // this is the default value.\n\nvcard.revision = Some(Revision::from_timestamp(Timestamp::from_date_time(\"2018-11-06T00:00:00Z\".parse::\u003cDateTime\u003cUtc\u003e\u003e().unwrap()).unwrap()));\n\nprintln!(\"{}\", vcard);\n\n//    BEGIN:VCARD\n//    VERSION:4.0\n//    FN;LANGUAGE=en:David Wang\n//    FN;LANGUAGE=zh:王大衛\n//    N:Wang;David;;Dr.;\n//    GENDER:M\n//    BDAY:19930707\n//    ADR;TYPE=home:;No.5;Section 5\\, Xinyi Road\\, Xinyi District;Taipei City;;110;Taiwan\n//    ADR;TYPE=work:;No.3;Beiping West Road\\, Zhongzheng District;Taipei City;;100;Taiwan\n//    TEL;TYPE=\"voice,cell\";VALUE=uri:tel:886-987-654-321\n//    TEL;TYPE=\"voice,home\";VALUE=uri:tel:886-02-1234-5678\n//    TEL;TYPE=\"voice,work\";VALUE=uri:tel:886-02-8888-8888;ext=532\n//    EMAIL;TYPE=work:david@thaumaturgiclen.com\n//    EMAIL;TYPE=home:david@gmail.com\n//    PHOTO:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAAG0OVFdAAAABmJLR0...\n//    URL;TYPE=work:https://xn--gwr372h.thaumaturgiclen.com:444/%E7%8E%8B%E5%A4%A7%E8%A1%9B\n//    X-SOCIALPROFILE;TYPE=facebook:https://www.facebook.com/david.vard.wang\n//    REV:20181106T000000Z\n//    END:VCARD\n```\n\n## TODO\n\n1. Attribute Value (RFC2045)\n1. Language Tag (RFC5646)\n1. Product ID Value (ISO9070 and RFC3406)\n1. Media Type (RFC4288)\n1. VCard Parser\n1. VCard Validator\n1. All versions of VCard (extra 2.1 and 3.0)\n\n## Crates.io\n\nhttps://crates.io/crates/vcard\n\n## Documentation\n\nhttps://docs.rs/vcard\n\n## License\n\n[MIT](LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagiclen%2Fvcard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagiclen%2Fvcard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagiclen%2Fvcard/lists"}