1use crate::{
8 Entry, Parser,
9 common::{CalendarScale, Data, IanaParse, IanaString, IanaType, PartialDateTime},
10};
11
12pub mod builder;
13pub mod parser;
14pub mod types;
15pub mod utils;
16pub mod writer;
17
18#[cfg(feature = "rkyv")]
19pub mod rkyv_types;
20#[cfg(feature = "rkyv")]
21pub mod rkyv_utils;
22#[cfg(feature = "rkyv")]
23pub mod rkyv_writer;
24
25#[derive(Debug, Default, Clone, PartialEq, Eq)]
26#[cfg_attr(
27 any(test, feature = "serde"),
28 derive(serde::Serialize, serde::Deserialize)
29)]
30#[cfg_attr(
31 feature = "rkyv",
32 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
33)]
34#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq)))]
35pub struct VCard {
36 pub entries: Vec<VCardEntry>,
37}
38
39#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub enum VCardVersion {
41 V2_0 = 20,
42 V2_1 = 21,
43 V3_0 = 30,
44 #[default]
45 V4_0 = 40,
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
49#[cfg_attr(
50 any(test, feature = "serde"),
51 derive(serde::Serialize, serde::Deserialize)
52)]
53#[cfg_attr(
54 feature = "rkyv",
55 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
56)]
57#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq)))]
58pub struct VCardEntry {
59 pub group: Option<String>,
60 pub name: VCardProperty,
61 pub params: Vec<VCardParameter>,
62 pub values: Vec<VCardValue>,
63}
64
65#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
66#[cfg_attr(
67 any(test, feature = "serde"),
68 derive(serde::Serialize, serde::Deserialize)
69)]
70#[cfg_attr(any(test, feature = "serde"), serde(tag = "type", content = "data"))]
71#[cfg_attr(
72 feature = "rkyv",
73 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
74)]
75#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
76pub enum VCardProperty {
77 Other(String),
78 Begin,
79 End,
80 Source, Kind, Xml, Fn, N, Nickname, Photo, Bday, Anniversary, Gender, Adr, Tel, Email, Impp, Lang, Tz, Geo, Title, Role, Logo, Org, Member, Related, Categories, Note, Prodid, Rev, Sound, Uid, Clientpidmap, Url, Version, Key, Fburl, Caladruri, Caluri, Birthplace, Deathplace, Deathdate, Expertise, Hobby, Interest, OrgDirectory, ContactUri, Created, Gramgender, Language, Pronouns, Socialprofile, Jsprop, }
131
132#[derive(Debug, Clone, PartialEq)]
133#[cfg_attr(
134 any(test, feature = "serde"),
135 derive(serde::Serialize, serde::Deserialize)
136)]
137#[cfg_attr(any(test, feature = "serde"), serde(tag = "type", content = "data"))]
138#[cfg_attr(
139 feature = "rkyv",
140 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
141)]
142#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq)))]
143pub enum VCardValue {
144 Text(String),
145 Integer(i64),
146 Float(f64),
147 Boolean(bool),
148 PartialDateTime(PartialDateTime),
149 Binary(Data),
150 Sex(VCardSex),
151 GramGender(VCardGramGender),
152 Kind(VCardKind),
153 Component(Vec<String>),
154}
155
156#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
157#[cfg_attr(
158 any(test, feature = "serde"),
159 derive(serde::Serialize, serde::Deserialize)
160)]
161#[cfg_attr(
162 feature = "rkyv",
163 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
164)]
165#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq)))]
166pub struct VCardParameter {
167 pub name: VCardParameterName,
168 pub value: VCardParameterValue,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
172#[cfg_attr(
173 any(test, feature = "serde"),
174 derive(serde::Serialize, serde::Deserialize)
175)]
176#[cfg_attr(any(test, feature = "serde"), serde(tag = "type", content = "data"))]
177#[cfg_attr(
178 feature = "rkyv",
179 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
180)]
181#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq)))]
182pub enum VCardParameterValue {
183 Text(String),
184 Integer(u32),
185 Timestamp(i64),
186 Bool(bool),
187 ValueType(VCardValueType),
188 Type(VCardType),
189 Calscale(CalendarScale),
190 Level(VCardLevel),
191 Phonetic(VCardPhonetic),
192 Jscomps(Vec<Jscomp>),
193 Null,
194}
195
196#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
197#[cfg_attr(
198 any(test, feature = "serde"),
199 derive(serde::Serialize, serde::Deserialize)
200)]
201#[cfg_attr(
202 feature = "rkyv",
203 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
204)]
205#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
206pub enum Jscomp {
207 Entry { position: u32, value: u32 },
208 Separator(String),
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
212#[cfg_attr(
213 any(test, feature = "serde"),
214 derive(serde::Serialize, serde::Deserialize)
215)]
216#[cfg_attr(
217 feature = "rkyv",
218 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
219)]
220#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(PartialEq)))]
221pub enum VCardParameterName {
222 Other(String),
223 Language, Value, Pref, Altid, Pid, Type, Mediatype, Calscale, SortAs, Geo, Tz, Index, Level, Group, Cc, Author, AuthorName, Created, Derived, Label, Phonetic, PropId, Script, ServiceType, Username, Jsptr, Jscomps, }
251
252#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
253#[cfg_attr(
254 any(test, feature = "serde"),
255 derive(serde::Serialize, serde::Deserialize)
256)]
257#[cfg_attr(any(test, feature = "serde"), serde(tag = "type", content = "data"))]
258#[cfg_attr(
259 feature = "rkyv",
260 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
261)]
262#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
263pub enum VCardValueType {
264 Boolean, Date, DateAndOrTime, DateTime, Float, Integer, LanguageTag, Text, Time, Timestamp, Uri, UtcOffset, }
277
278#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
279#[cfg_attr(
280 any(test, feature = "serde"),
281 derive(serde::Serialize, serde::Deserialize)
282)]
283#[cfg_attr(
284 feature = "rkyv",
285 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
286)]
287#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
288pub enum VCardLevel {
289 Beginner, Average, Expert, High, Medium, Low, }
296
297#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
298#[cfg_attr(
299 any(test, feature = "serde"),
300 derive(serde::Serialize, serde::Deserialize)
301)]
302#[cfg_attr(any(test, feature = "serde"), serde(tag = "type", content = "data"))]
303#[cfg_attr(
304 feature = "rkyv",
305 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
306)]
307#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
308pub enum VCardPhonetic {
309 Ipa, Jyut, Piny, Script, }
314
315#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
316#[cfg_attr(
317 any(test, feature = "serde"),
318 derive(serde::Serialize, serde::Deserialize)
319)]
320#[cfg_attr(any(test, feature = "serde"), serde(tag = "type", content = "data"))]
321#[cfg_attr(
322 feature = "rkyv",
323 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
324)]
325#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
326pub enum VCardType {
327 Work, Home, Billing, Delivery, Contact, Acquaintance, Friend, Met, CoWorker, Colleague, CoResident, Neighbor, Child, Parent, Sibling, Spouse, Kin, Muse, Crush, Date, Sweetheart, Me, Agent, Emergency, Text, Voice, Fax, Cell, Video, Pager, Textphone, MainNumber, }
360
361#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
362#[cfg_attr(
363 any(test, feature = "serde"),
364 derive(serde::Serialize, serde::Deserialize)
365)]
366#[cfg_attr(
367 feature = "rkyv",
368 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
369)]
370#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
371pub enum VCardGramGender {
372 Animate, Common, Feminine, Inanimate, Masculine, Neuter, }
379
380#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
381#[cfg_attr(
382 any(test, feature = "serde"),
383 derive(serde::Serialize, serde::Deserialize)
384)]
385#[cfg_attr(
386 feature = "rkyv",
387 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
388)]
389#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
390pub enum VCardSex {
391 Male,
392 Female,
393 Other,
394 NoneOrNotApplicable,
395 Unknown,
396}
397
398#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
399#[cfg_attr(
400 any(test, feature = "serde"),
401 derive(serde::Serialize, serde::Deserialize)
402)]
403#[cfg_attr(
404 feature = "rkyv",
405 derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)
406)]
407#[cfg_attr(feature = "rkyv", rkyv(compare(PartialEq), derive(Debug)))]
408pub enum VCardKind {
409 Individual, Group, Org, Location, Application, Device, }
416
417#[derive(Debug, Clone, Copy, PartialEq, Eq)]
418pub(crate) enum ValueSeparator {
419 None,
420 Comma,
421 Semicolon,
422 SemicolonAndComma,
423 Skip,
424}
425
426#[derive(Debug, Clone, Copy, PartialEq, Eq)]
427pub(crate) enum ValueType {
428 Vcard(VCardValueType),
429 Kind,
430 Sex,
431 GramGender,
432}
433
434impl ValueType {
435 pub fn unwrap_vcard(self) -> VCardValueType {
436 match self {
437 ValueType::Vcard(v) => v,
438 _ => VCardValueType::Text,
439 }
440 }
441}
442
443impl VCard {
444 pub fn parse(value: impl AsRef<str>) -> Result<Self, Entry> {
445 let mut parser = Parser::new(value.as_ref());
446 match parser.entry() {
447 Entry::VCard(vcard) => Ok(vcard),
448 other => Err(other),
449 }
450 }
451}