gazetta_model_ext/
person.rs

1//  Copyright (C) 2015 Steven Allen
2//
3//  This file is part of gazetta.
4//
5//  This program is free software: you can redistribute it and/or modify it under the terms of the
6//  GNU General Public License as published by the Free Software Foundation version 3 of the
7//  License.
8//
9//  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
11//  the GNU General Public License for more details.
12//
13//  You should have received a copy of the GNU General Public License along with this program.  If
14//  not, see <http://www.gnu.org/licenses/>.
15//
16
17use std::fmt;
18
19use crate::link::Link;
20use crate::yaml::{self, Yaml};
21
22#[derive(Debug, Clone)]
23pub struct Person {
24    pub name: String,
25    pub email: Option<String>,
26    pub photo: Option<String>,
27    pub key: Option<Key>,
28    pub nicknames: Vec<String>,
29    pub also: Vec<Link>,
30}
31
32#[derive(Debug, Clone)]
33pub struct Key {
34    pub url: String,
35    pub fingerprint: String,
36}
37
38impl Key {
39    pub fn from_yaml(key: Yaml) -> Result<Self, &'static str> {
40        match key {
41            Yaml::Hash(mut key) => Ok(Key {
42                url: match key.remove(&yaml::KEYS.url) {
43                    Some(Yaml::String(url)) => url,
44                    Some(..) => return Err("key url must be a string"),
45                    None => return Err("key url missing"),
46                },
47                fingerprint: match key.remove(&yaml::KEYS.fingerprint) {
48                    Some(Yaml::String(fprint)) => fprint,
49                    Some(..) => return Err("key fingerprint must be a string"),
50                    None => return Err("key fingerprint missing"),
51                },
52            }),
53            _ => Err("if specified, key must be a hash"),
54        }
55    }
56}
57
58impl fmt::Display for Person {
59    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60        write!(f, "{}", self.name)?;
61        if let Some(ref email) = self.email {
62            write!(f, " <{email}>")?;
63        }
64        Ok(())
65    }
66}
67
68impl Person {
69    pub fn from_yaml(person: Yaml) -> Result<Self, &'static str> {
70        Ok(match person {
71            Yaml::Hash(mut person) => Person {
72                name: match person.remove(&yaml::KEYS.name) {
73                    Some(Yaml::String(name)) => name,
74                    None => return Err("missing name"),
75                    _ => return Err("name must be a string"),
76                },
77                photo: match person.remove(&yaml::KEYS.photo) {
78                    Some(Yaml::String(photo)) => Some(photo),
79                    None => None,
80                    _ => return Err("if specified, photo must be a string"),
81                },
82                email: match person.remove(&yaml::KEYS.email) {
83                    Some(Yaml::String(email)) => Some(email),
84                    None => None,
85                    _ => return Err("if specified, email must be a string"),
86                },
87                nicknames: match person.remove(&yaml::KEYS.nicknames) {
88                    Some(Yaml::String(nick)) => vec![nick],
89                    Some(Yaml::Array(nicks)) => nicks
90                        .into_iter()
91                        .map(|nick| match nick {
92                            Yaml::String(nick) => Ok(nick),
93                            _ => Err("nicknames must be strings"),
94                        })
95                        .collect::<Result<_, _>>()?,
96                    Some(..) => return Err("invalid nicknames value"),
97                    None => vec![],
98                },
99                also: person
100                    .remove(&yaml::KEYS.also)
101                    .map(Link::many_from_yaml)
102                    .transpose()?
103                    .unwrap_or_else(Vec::new),
104                key: person
105                    .remove(&yaml::KEYS.key)
106                    .map(Key::from_yaml)
107                    .transpose()?,
108            },
109            Yaml::String(name) => Person {
110                name,
111                email: None,
112                key: None,
113                also: Vec::new(),
114                photo: None,
115                nicknames: Vec::new(),
116            },
117            _ => return Err("invalid person"),
118        })
119    }
120}