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