git_together_ssh/
author.rs1use std::fmt;
2
3use crate::errors::*;
4
5#[derive(Clone, Debug, PartialEq)]
6pub struct Author {
7 pub name: String,
8 pub email: String,
9}
10
11pub struct AuthorParser {
12 pub domain: Option<String>,
13}
14
15impl AuthorParser {
16 pub fn parse(&self, raw: &str) -> Result<Author> {
17 let mut split = raw.split(';').map(str::trim);
18
19 let name = match split.next() {
20 Some(name) if !name.is_empty() => name,
21 _ => {
22 return Err("missing name".into());
23 }
24 };
25
26 let email_seed = match split.next() {
27 Some(email_seed) if !email_seed.is_empty() => email_seed,
28 _ => {
29 return Err("missing email seed".into());
30 }
31 };
32
33 let email = if email_seed.contains('@') {
34 email_seed.into()
35 } else {
36 let domain = match self.domain {
37 Some(ref domain) => domain,
38 None => {
39 return Err("missing domain".into());
40 }
41 };
42 format!("{}@{}", email_seed, domain)
43 };
44
45 Ok(Author {
46 name: name.into(),
47 email,
48 })
49 }
50}
51
52impl fmt::Display for Author {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 write!(f, "{} <{}>", self.name, self.email)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn new() {
64 let author_parser = AuthorParser {
65 domain: Some("example.com".into()),
66 };
67
68 let author = author_parser.parse("Jane Doe; jdoe").unwrap();
69 assert_eq!(author.name, "Jane Doe");
70 assert_eq!(author.email, "jdoe@example.com");
71
72 let author = author_parser.parse("");
73 assert!(author.is_err());
74
75 let author = author_parser.parse("Jane Doe");
76 assert!(author.is_err());
77
78 let author = author_parser.parse("Jane Doe; ");
79 assert!(author.is_err());
80
81 let author = author_parser
82 .parse("Jane Doe; jane.doe@example.edu")
83 .unwrap();
84 assert_eq!(author.name, "Jane Doe");
85 assert_eq!(author.email, "jane.doe@example.edu");
86 }
87}