diff --git a/src/gemtext/parser.rs b/src/gemtext/parser.rs index 86e2d03..42a9955 100644 --- a/src/gemtext/parser.rs +++ b/src/gemtext/parser.rs @@ -80,7 +80,7 @@ impl<'a> GemtextNode { } fn parse_senders(text: &'a str) -> Self { - let Some(line) = text.strip_prefix('<') else { + let Some(line) = text.strip_prefix('<').map(|x| x.trim()) else { return Self::Text(text.to_string()); }; if let Ok(user) = line.parse() { @@ -107,7 +107,10 @@ impl<'a> GemtextNode { } fn parse_timestamp(text: &'a str) -> Self { - todo!() + let Some(line) = text.strip_prefix('@').map(|x| x.trim()) else { + return Self::Text(text.to_string()); + }; + Self::Timestamp(line.to_string()) } } @@ -206,6 +209,10 @@ impl<'a> Parser<'a> { self.lines.push(GemtextNode::parse_recipients(line)); } + fn timestamp(&mut self, line: &'a str) { + self.lines.push(GemtextNode::parse_timestamp(line)); + } + fn parse_normal(&mut self, line: &'a str) { match line { s if s.starts_with("=>") => self.link(s), @@ -215,7 +222,7 @@ impl<'a> Parser<'a> { s if s.starts_with("```") => self.enter_preformatted(s), s if s.starts_with('<') => self.senders(s), s if s.starts_with(':') => self.recipients(s), - s if s.starts_with('@') => {} + s if s.starts_with('@') => self.timestamp(s), s => self.lines.push(GemtextNode::Text(s.to_string())), } } @@ -242,3 +249,76 @@ impl<'a> Parser<'a> { } } } + +#[cfg(test)] +mod tests { + use crate::prelude::Host; + + use super::*; + + static RAW: &'static str = + include_str!("../../test/mailstore/misfin.example.org/jane/Lists/700070.gmi"); + + fn parse_raw() -> Vec { + Parser::new().parse(RAW) + } + + #[test] + fn nodes() { + let nodes = parse_raw(); + let mut nodes = nodes.iter(); + assert_eq!( + nodes.next().cloned().unwrap(), + GemtextNode::Sender(Mailbox { + username: "ed".to_string(), + host: Host { + subdomain: None, + domain: "iron".to_string(), + tld: "maiden".to_string() + }, + blurb: Some("Eddy the Head".to_string()) + }) + ); + assert_eq!( + nodes.next().cloned().unwrap(), + GemtextNode::Sender(Mailbox { + username: "bruce".to_string(), + host: Host { + subdomain: None, + domain: "dickinson".to_string(), + tld: "jam".to_string(), + }, + blurb: Some("Bruce Dickinson".to_string()), + }) + ); + assert_eq!( + nodes.next().cloned().unwrap(), + GemtextNode::Recipients(Recipients { + boxes: vec![ + Mailbox { + username: "nicko".to_string(), + host: Host { + subdomain: None, + domain: "iron".to_string(), + tld: "maiden".to_string(), + }, + blurb: None, + }, + Mailbox { + username: "steve".to_string(), + host: Host { + subdomain: None, + domain: "iron".to_string(), + tld: "maiden".to_string() + }, + blurb: None, + } + ] + }) + ); + assert_eq!( + nodes.next().cloned().unwrap(), + GemtextNode::Timestamp("2023-06-07T21:27:15Z".to_string()), + ) + } +} diff --git a/src/message/parser.rs b/src/message/parser.rs index 5d2c44c..dd5ef49 100644 --- a/src/message/parser.rs +++ b/src/message/parser.rs @@ -96,18 +96,22 @@ impl Parser { mod tests { use super::*; - const RAW: &'static str = include_str!("../../test/ox42sc69.gmi"); + const RAW: &'static str = + include_str!("../../test/mailstore/misfin.example.org/dick/Inbox/619310.gmi"); #[test] fn parse_message() { - let msg: Message = Parser::new("ox42sc69").parse(RAW).unwrap(); - assert_eq!(msg.id, "ox42sc69"); + let msg: Message = Parser::new("619310").parse(RAW).unwrap(); + assert_eq!(msg.id, "619310"); assert_eq!(msg.from.to_string(), "joe@gemini.example.org"); assert_eq!(msg.timestamp.unwrap(), "2023-06-07T16:09:42Z"); assert!(msg.senders.is_empty()); assert!(msg.recipients.is_empty()); assert_eq!(msg.title.unwrap(), "How 'bout dose Bears?"); - assert_eq!(msg.body, "# How 'bout dose Bears?\nWhen are they coming for dinner anyway?\n"); + assert_eq!( + msg.body, + "# How 'bout dose Bears?\nWhen are they coming for dinner anyway?\n" + ); } #[test] diff --git a/src/status/mod.rs b/src/status/mod.rs index c1a1777..ffe642a 100644 --- a/src/status/mod.rs +++ b/src/status/mod.rs @@ -216,33 +216,106 @@ mod tests { #[test] fn to_number_temporary() { - assert_eq!(u8::from(Status::TemporaryFailure(TemporaryFailure::TemporaryError)), 40); - assert_eq!(u8::from(Status::TemporaryFailure(TemporaryFailure::ServerUnavailable)), 41); - assert_eq!(u8::from(Status::TemporaryFailure(TemporaryFailure::CgiError)), 42); - assert_eq!(u8::from(Status::TemporaryFailure(TemporaryFailure::ProxyError)), 43); - assert_eq!(u8::from(Status::TemporaryFailure(TemporaryFailure::RateLimit)), 44); - assert_eq!(u8::from(Status::TemporaryFailure(TemporaryFailure::MailboxFull)), 45); - assert_eq!(u8::from(Status::TemporaryFailure(TemporaryFailure::Other)), 46); + assert_eq!( + u8::from(Status::TemporaryFailure(TemporaryFailure::TemporaryError)), + 40 + ); + assert_eq!( + u8::from(Status::TemporaryFailure( + TemporaryFailure::ServerUnavailable + )), + 41 + ); + assert_eq!( + u8::from(Status::TemporaryFailure(TemporaryFailure::CgiError)), + 42 + ); + assert_eq!( + u8::from(Status::TemporaryFailure(TemporaryFailure::ProxyError)), + 43 + ); + assert_eq!( + u8::from(Status::TemporaryFailure(TemporaryFailure::RateLimit)), + 44 + ); + assert_eq!( + u8::from(Status::TemporaryFailure(TemporaryFailure::MailboxFull)), + 45 + ); + assert_eq!( + u8::from(Status::TemporaryFailure(TemporaryFailure::Other)), + 46 + ); } #[test] fn to_number_permanent() { - assert_eq!(u8::from(Status::PermanentFailure(PermanentFailure::PermanentError)), 50); - assert_eq!(u8::from(Status::PermanentFailure(PermanentFailure::MailboxNonexistent)), 51); - assert_eq!(u8::from(Status::PermanentFailure(PermanentFailure::MailboxGone)), 52); - assert_eq!(u8::from(Status::PermanentFailure(PermanentFailure::DomainNotServiced)), 53); - assert_eq!(u8::from(Status::PermanentFailure(PermanentFailure::BadRequest)), 59); - assert_eq!(u8::from(Status::PermanentFailure(PermanentFailure::Other)), 54); + assert_eq!( + u8::from(Status::PermanentFailure(PermanentFailure::PermanentError)), + 50 + ); + assert_eq!( + u8::from(Status::PermanentFailure( + PermanentFailure::MailboxNonexistent + )), + 51 + ); + assert_eq!( + u8::from(Status::PermanentFailure(PermanentFailure::MailboxGone)), + 52 + ); + assert_eq!( + u8::from(Status::PermanentFailure( + PermanentFailure::DomainNotServiced + )), + 53 + ); + assert_eq!( + u8::from(Status::PermanentFailure(PermanentFailure::BadRequest)), + 59 + ); + assert_eq!( + u8::from(Status::PermanentFailure(PermanentFailure::Other)), + 54 + ); } #[test] fn to_number_auth() { - assert_eq!(u8::from(Status::AuthenticationFailure(AuthenticationFailure::CertificateRequired)), 60); - assert_eq!(u8::from(Status::AuthenticationFailure(AuthenticationFailure::UnauthorizedSender)), 61); - assert_eq!(u8::from(Status::AuthenticationFailure(AuthenticationFailure::CertificateInvalid)), 62); - assert_eq!(u8::from(Status::AuthenticationFailure(AuthenticationFailure::IdentityMismatch)), 63); - assert_eq!(u8::from(Status::AuthenticationFailure(AuthenticationFailure::ProofRequired)), 64); - assert_eq!(u8::from(Status::AuthenticationFailure(AuthenticationFailure::Other)), 65); + assert_eq!( + u8::from(Status::AuthenticationFailure( + AuthenticationFailure::CertificateRequired + )), + 60 + ); + assert_eq!( + u8::from(Status::AuthenticationFailure( + AuthenticationFailure::UnauthorizedSender + )), + 61 + ); + assert_eq!( + u8::from(Status::AuthenticationFailure( + AuthenticationFailure::CertificateInvalid + )), + 62 + ); + assert_eq!( + u8::from(Status::AuthenticationFailure( + AuthenticationFailure::IdentityMismatch + )), + 63 + ); + assert_eq!( + u8::from(Status::AuthenticationFailure( + AuthenticationFailure::ProofRequired + )), + 64 + ); + assert_eq!( + u8::from(Status::AuthenticationFailure(AuthenticationFailure::Other)), + 65 + ); } #[test] diff --git a/test/mailstore/mail.gmi.org/dick/Inbox/623273.gmi b/test/mailstore/mail.gmi.org/dick/Inbox/623273.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/dick/Inbox/738127.gmi b/test/mailstore/mail.gmi.org/dick/Inbox/738127.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/dick/Lists/158468.gmi b/test/mailstore/mail.gmi.org/dick/Lists/158468.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/dick/Lists/431652.gmi b/test/mailstore/mail.gmi.org/dick/Lists/431652.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/dick/blurb b/test/mailstore/mail.gmi.org/dick/blurb new file mode 100644 index 0000000..418b2fa --- /dev/null +++ b/test/mailstore/mail.gmi.org/dick/blurb @@ -0,0 +1 @@ +Richard Stallman diff --git a/test/mailstore/mail.gmi.org/jane/Inbox/488571.gmi b/test/mailstore/mail.gmi.org/jane/Inbox/488571.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/jane/Inbox/867017.gmi b/test/mailstore/mail.gmi.org/jane/Inbox/867017.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/jane/Lists/476324.gmi b/test/mailstore/mail.gmi.org/jane/Lists/476324.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/jane/Lists/891249.gmi b/test/mailstore/mail.gmi.org/jane/Lists/891249.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/mail.gmi.org/jane/blurb b/test/mailstore/mail.gmi.org/jane/blurb new file mode 100644 index 0000000..b549676 --- /dev/null +++ b/test/mailstore/mail.gmi.org/jane/blurb @@ -0,0 +1 @@ +Janet Weiss diff --git a/test/ox42sc69.gmi b/test/mailstore/misfin.example.org/dick/Inbox/619310.gmi similarity index 100% rename from test/ox42sc69.gmi rename to test/mailstore/misfin.example.org/dick/Inbox/619310.gmi diff --git a/test/mailstore/misfin.example.org/dick/Inbox/868379.gmi b/test/mailstore/misfin.example.org/dick/Inbox/868379.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/misfin.example.org/dick/Lists/448785.gmi b/test/mailstore/misfin.example.org/dick/Lists/448785.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/misfin.example.org/dick/Lists/645815.gmi b/test/mailstore/misfin.example.org/dick/Lists/645815.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/misfin.example.org/dick/blurb b/test/mailstore/misfin.example.org/dick/blurb new file mode 100644 index 0000000..a956b32 --- /dev/null +++ b/test/mailstore/misfin.example.org/dick/blurb @@ -0,0 +1 @@ +Rick Baker diff --git a/test/mailstore/misfin.example.org/jane/Inbox/252366.gmi b/test/mailstore/misfin.example.org/jane/Inbox/252366.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/misfin.example.org/jane/Inbox/654064.gmi b/test/mailstore/misfin.example.org/jane/Inbox/654064.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/misfin.example.org/jane/Lists/620426.gmi b/test/mailstore/misfin.example.org/jane/Lists/620426.gmi new file mode 100644 index 0000000..e69de29 diff --git a/test/mailstore/misfin.example.org/jane/Lists/700070.gmi b/test/mailstore/misfin.example.org/jane/Lists/700070.gmi new file mode 100644 index 0000000..27977f0 --- /dev/null +++ b/test/mailstore/misfin.example.org/jane/Lists/700070.gmi @@ -0,0 +1,12 @@ +< ed@iron.maiden Eddy the Head +< bruce@dickinson.jam Bruce Dickinson +: nicko@iron.maiden steve@iron.maiden +@ 2023-06-07T21:27:15Z + +# Checking in +The new album's in the can. A few things: +* Needs more cowbell +* Adrian's guitar is too loud, drowning out the cowbell +* Steve has a fever + +> You're gonna want that cowbell! diff --git a/test/mailstore/misfin.example.org/jane/blurb b/test/mailstore/misfin.example.org/jane/blurb new file mode 100644 index 0000000..176be3c --- /dev/null +++ b/test/mailstore/misfin.example.org/jane/blurb @@ -0,0 +1 @@ +Jane Doh