1use std::borrow::Cow;
2use std::str::FromStr;
3
4use serde::{Deserialize, Serialize};
5
6use crate::common::StringValue;
7
8pub mod check;
9pub use check::ContactCheck;
10
11pub mod create;
12pub use create::ContactCreate;
13
14pub mod delete;
15pub use delete::ContactDelete;
16
17pub mod info;
18pub use info::ContactInfo;
19
20pub mod update;
21pub use update::ContactUpdate;
22
23pub const XMLNS: &str = "urn:ietf:params:xml:ns:contact-1.0";
24
25#[derive(Serialize, Deserialize, Debug, Clone)]
26pub struct Country(celes::Country);
27
28impl FromStr for Country {
29 type Err = <celes::Country as FromStr>::Err;
30
31 fn from_str(s: &str) -> Result<Self, Self::Err> {
32 Ok(Self(celes::Country::from_str(s)?))
33 }
34}
35
36impl std::ops::Deref for Country {
37 type Target = celes::Country;
38
39 fn deref(&self) -> &Self::Target {
40 &self.0
41 }
42}
43
44#[derive(Serialize, Deserialize, Debug, Clone)]
46pub struct ContactAuthInfo<'a> {
47 #[serde(rename = "contact:pw", alias = "pw")]
49 pub password: StringValue<'a>,
50}
51
52impl<'a> ContactAuthInfo<'a> {
53 pub fn new(password: &'a str) -> Self {
55 Self {
56 password: password.into(),
57 }
58 }
59}
60
61#[derive(Serialize, Deserialize, Debug, Clone)]
63pub struct Phone<'a> {
64 #[serde(rename = "$value")]
66 pub number: Cow<'a, str>,
67 #[serde(rename = "x")]
69 pub extension: Option<Cow<'a, str>>,
70}
71
72impl<'a> Phone<'a> {
73 pub fn new(number: &'a str) -> Self {
75 Self {
76 extension: None,
77 number: number.into(),
78 }
79 }
80
81 pub fn set_extension(&mut self, ext: &'a str) {
83 self.extension = Some(ext.into());
84 }
85}
86
87#[derive(Serialize, Deserialize, Debug, Clone)]
89pub struct Address<'a> {
90 #[serde(rename = "contact:street", alias = "street")]
92 pub street: Vec<StringValue<'a>>,
93 #[serde(rename = "contact:city", alias = "city")]
95 pub city: StringValue<'a>,
96 #[serde(rename = "contact:sp", alias = "sp")]
98 pub province: StringValue<'a>,
99 #[serde(rename = "contact:pc", alias = "pc")]
101 pub postal_code: StringValue<'a>,
102 #[serde(rename = "contact:cc", alias = "cc")]
104 pub country: Country,
105}
106
107impl<'a> Address<'a> {
108 pub fn new(
110 street: &[&'a str],
111 city: &'a str,
112 province: &'a str,
113 postal_code: &'a str,
114 country: Country,
115 ) -> Self {
116 let street = street.iter().map(|&s| s.into()).collect();
117
118 Self {
119 street,
120 city: city.into(),
121 province: province.into(),
122 postal_code: postal_code.into(),
123 country,
124 }
125 }
126}
127
128#[derive(Serialize, Deserialize, Debug, Clone)]
130pub struct PostalInfo<'a> {
131 #[serde(rename = "type")]
133 pub info_type: String,
134 #[serde(rename = "contact:name", alias = "name")]
136 pub name: StringValue<'a>,
137 #[serde(rename = "contact:org", alias = "org")]
139 pub organization: StringValue<'a>,
140 #[serde(rename = "contact:addr", alias = "addr")]
142 pub address: Address<'a>,
143}
144
145impl<'a> PostalInfo<'a> {
146 pub fn new(
148 info_type: &str,
149 name: &'a str,
150 organization: &'a str,
151 address: Address<'a>,
152 ) -> Self {
153 Self {
154 info_type: info_type.to_string(),
155 name: name.into(),
156 organization: organization.into(),
157 address,
158 }
159 }
160}