1use crate::{
4 Account, DataError, MyEmailAddress, ObjectType, Validate, ValidationError, emit_error,
5 validate_sha1sum,
6};
7use core::fmt;
8use email_address::EmailAddress;
9use iri_string::types::UriString;
10use serde::{Deserialize, Serialize};
11use serde_with::skip_serializing_none;
12use std::{collections::HashSet, str::FromStr};
13
14#[skip_serializing_none]
28#[derive(Debug, Deserialize, PartialEq, Serialize)]
29pub struct Person {
30 #[serde(rename = "objectType")]
31 #[serde(default = "default_object_type")]
32 object_type: ObjectType,
33 name: Vec<String>,
34 mbox: Vec<MyEmailAddress>,
35 mbox_sha1sum: Vec<String>,
36 openid: Vec<UriString>,
37 account: Vec<Account>,
38}
39
40impl Person {
41 pub fn builder() -> PersonBuilder {
43 PersonBuilder::default()
44 }
45
46 pub fn check_object_type(&self) -> bool {
48 self.object_type == ObjectType::Person
49 }
50
51 pub fn names(&self) -> &[String] {
53 self.name.as_slice()
54 }
55
56 pub fn mboxes(&self) -> &[MyEmailAddress] {
58 self.mbox.as_slice()
59 }
60
61 pub fn mbox_sha1sums(&self) -> &[String] {
63 self.mbox_sha1sum.as_slice()
64 }
65
66 pub fn openids(&self) -> &[UriString] {
68 self.openid.as_slice()
69 }
70
71 pub fn accounts(&self) -> &[Account] {
73 self.account.as_slice()
74 }
75
76 pub fn unknown() -> Self {
78 Person {
79 object_type: ObjectType::Person,
80 name: vec![],
81 mbox: vec![],
82 mbox_sha1sum: vec![],
83 openid: vec![],
84 account: vec![],
85 }
86 }
87}
88
89impl fmt::Display for Person {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 let mut vec = vec![];
92
93 let y: Vec<_> = self.name.iter().map(|x| x.to_string()).collect();
94 if !y.is_empty() {
95 vec.push(format!("\"name\": [{}]", y.join(", ")))
96 }
97 let y: Vec<_> = self.mbox.iter().map(|x| x.as_ref().to_string()).collect();
98 if !y.is_empty() {
99 vec.push(format!("\"mbox\": [{}]", y.join(", ")))
100 }
101 let y: Vec<_> = self.mbox_sha1sum.iter().map(|x| x.to_string()).collect();
102 if !y.is_empty() {
103 vec.push(format!("\"mbox_sha1sum\": [{}]", y.join(", ")))
104 }
105 let y: Vec<_> = self.openid.iter().map(|x| x.to_string()).collect();
106 if !y.is_empty() {
107 vec.push(format!("\"openid\": [{}]", y.join(", ")))
108 }
109 let y: Vec<_> = self.account.iter().map(|x| x.to_string()).collect();
110 if !y.is_empty() {
111 vec.push(format!("\"account\": [{}]", y.join(", ")))
112 }
113
114 let res = vec
115 .iter()
116 .map(|x| x.to_string())
117 .collect::<Vec<_>>()
118 .join(", ");
119 write!(f, "Person{{ {res} }}")
120 }
121}
122
123impl Validate for Person {
124 fn validate(&self) -> Vec<ValidationError> {
125 let mut vec = vec![];
126
127 if !self.check_object_type() {
128 vec.push(ValidationError::WrongObjectType {
129 expected: ObjectType::Agent,
130 found: self.object_type.to_string().into(),
131 })
132 }
133 self.name.iter().for_each(|x| {
134 if x.trim().is_empty() {
135 vec.push(ValidationError::Empty("name".into()))
136 }
137 });
138 self.mbox_sha1sum.iter().for_each(|x| {
139 if x.trim().is_empty() {
140 vec.push(ValidationError::Empty("mbox_sha1sum".into()))
141 } else {
142 validate_sha1sum(x).unwrap_or_else(|x| vec.push(x))
143 }
144 });
145 self.account
146 .iter()
147 .for_each(|x| x.check_validity().unwrap_or_else(|x| vec.push(x)));
148
149 vec
150 }
151}
152
153#[derive(Default, Debug)]
155pub struct PersonBuilder {
156 _name: HashSet<String>,
157 _mbox: HashSet<MyEmailAddress>,
158 _mbox_sha1sum: HashSet<String>,
159 _openid: HashSet<UriString>,
160 _account: HashSet<Account>,
161}
162
163impl PersonBuilder {
164 pub fn name(mut self, val: &str) -> Result<Self, DataError> {
168 let val = val.trim();
169 if val.is_empty() {
170 emit_error!(DataError::Validation(ValidationError::Empty("name".into())))
171 }
172 self._name.insert(val.to_owned());
173 Ok(self)
174 }
175
176 pub fn mbox(mut self, val: &str) -> Result<Self, DataError> {
181 let val = val.trim();
182 if val.is_empty() {
183 emit_error!(DataError::Validation(ValidationError::Empty("mbox".into())))
184 }
185 let email = if let Some(x) = val.strip_prefix("mailto:") {
187 EmailAddress::from_str(x)?
188 } else {
189 EmailAddress::from_str(val)?
190 };
191 self._mbox.insert(MyEmailAddress::from(email));
192 Ok(self)
193 }
194
195 pub fn mbox_sha1sum(mut self, val: &str) -> Result<Self, DataError> {
199 let val = val.trim();
200 if val.is_empty() {
201 emit_error!(DataError::Validation(ValidationError::Empty(
202 "mbox_sha1sum".into()
203 )))
204 }
205 validate_sha1sum(val)?;
207 self._mbox_sha1sum.insert(val.to_owned());
208 Ok(self)
209 }
210
211 pub fn openid(mut self, val: &str) -> Result<Self, DataError> {
215 let val = val.trim();
216 if val.is_empty() {
217 emit_error!(DataError::Validation(ValidationError::Empty(
218 "openid".into()
219 )))
220 }
221 let uri = UriString::from_str(val)?;
222 self._openid.insert(uri);
223 Ok(self)
224 }
225
226 pub fn account(mut self, val: Account) -> Result<Self, DataError> {
230 val.check_validity()?;
231 self._account.insert(val);
232 Ok(self)
233 }
234
235 pub fn build(self) -> Result<Person, DataError> {
239 Ok(Person {
240 object_type: ObjectType::Person,
241 name: self._name.into_iter().collect(),
242 mbox: self._mbox.into_iter().collect(),
243 mbox_sha1sum: self._mbox_sha1sum.into_iter().collect(),
244 openid: self._openid.into_iter().collect(),
245 account: self._account.into_iter().collect(),
246 })
247 }
248}
249
250fn default_object_type() -> ObjectType {
251 ObjectType::Person
252}