Skip to content

Commit 67c8c6a

Browse files
committed
parse returns Result.
1 parent 6c40ac1 commit 67c8c6a

File tree

3 files changed

+39
-20
lines changed

3 files changed

+39
-20
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

git-date/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ bstr = { version = "0.2.13", default-features = false, features = ["std"]}
1919
serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"]}
2020
itoa = "1.0.1"
2121
time = { version = "0.3.2", default-features = false, features = ["local-offset", "formatting", "macros", "parsing"] }
22+
thiserror = "1.0.32"
2223

2324
document-features = { version = "0.2.0", optional = true }
2425

git-date/src/parse.rs

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
use crate::time::format::{DEFAULT, ISO8601, ISO8601_STRICT, RFC2822, SHORT};
22
use crate::time::Sign;
33
use crate::Time;
4+
use std::num::ParseIntError;
45
use std::str::FromStr;
56
use time::{Date, OffsetDateTime};
67

8+
#[derive(thiserror::Error, Debug)]
9+
#[allow(missing_docs)]
10+
pub enum Error {
11+
#[error("Date string can not be parsed")]
12+
InvalidDateString,
13+
#[error("Timezone offset can not be parsed")]
14+
InvalidTzOffset,
15+
#[error("Relative period can not be parsed")]
16+
InvalidPeriod,
17+
#[error("Integer string can not be parsed")]
18+
InvalidInteger(#[from] ParseIntError),
19+
}
20+
721
#[allow(missing_docs)]
822
pub fn parse(input: &str) -> Option<Time> {
923
// TODO: actual implementation, this is just to not constantly fail
@@ -27,24 +41,24 @@ pub fn parse(input: &str) -> Option<Time> {
2741
} else if let Ok(val) = parse_raw(input) {
2842
// Format::Raw
2943
Some(val)
30-
} else if let Some(val) = relative::parse(input) {
44+
} else if let Ok(val) = relative::parse(input) {
3145
Some(Time::new(val.unix_timestamp() as u32, val.offset().whole_seconds()))
3246
} else {
3347
None
3448
};
3549
}
3650
}
3751

38-
fn parse_raw(input: &str) -> Result<Time, ()> {
52+
fn parse_raw(input: &str) -> Result<Time, Error> {
3953
let mut split = input.split_whitespace();
40-
let seconds_since_unix_epoch: u32 = split.next().ok_or(())?.parse().map_err(|_| ())?;
41-
let offset = split.next().ok_or(())?;
54+
let seconds_since_unix_epoch: u32 = split.next().ok_or(Error::InvalidDateString)?.parse()?;
55+
let offset = split.next().ok_or(Error::InvalidDateString)?;
4256
if offset.len() != 5 {
43-
return Err(());
57+
return Err(Error::InvalidTzOffset);
4458
}
4559
let sign = if &offset[..1] == "-" { Sign::Plus } else { Sign::Minus };
46-
let hours: i32 = offset[1..3].parse().map_err(|_| ())?;
47-
let minutes: i32 = offset[3..5].parse().map_err(|_| ())?;
60+
let hours: i32 = offset[1..3].parse()?;
61+
let minutes: i32 = offset[3..5].parse()?;
4862
let offset_in_seconds = hours * 3600 + minutes * 60;
4963
let time = Time {
5064
seconds_since_unix_epoch,
@@ -55,29 +69,32 @@ fn parse_raw(input: &str) -> Result<Time, ()> {
5569
}
5670

5771
mod relative {
72+
use crate::parse::Error;
5873
use std::str::FromStr;
5974
use time::{Duration, OffsetDateTime};
6075

61-
pub(crate) fn parse(input: &str) -> Option<OffsetDateTime> {
76+
pub(crate) fn parse(input: &str) -> Result<OffsetDateTime, Error> {
6277
let mut split = input.split_whitespace();
63-
let multiplier = i64::from_str(split.next()?).ok()?;
64-
let period = period_to_seconds(split.next()?)?;
65-
if split.next()? != "ago" {
66-
return None;
78+
let multiplier = i64::from_str(split.next().ok_or(Error::InvalidDateString)?)?;
79+
let period = period_to_seconds(split.next().ok_or(Error::InvalidDateString)?)?;
80+
if split.next().ok_or(Error::InvalidDateString)? != "ago" {
81+
return Err(Error::InvalidDateString);
6782
}
68-
Some(OffsetDateTime::now_utc().checked_sub(Duration::seconds(multiplier * period))?)
83+
Ok(OffsetDateTime::now_utc()
84+
.checked_sub(Duration::seconds(multiplier * period))
85+
.ok_or(Error::InvalidDateString)?)
6986
}
7087

71-
fn period_to_seconds(period: &str) -> Option<i64> {
88+
fn period_to_seconds(period: &str) -> Result<i64, Error> {
7289
let period = period.strip_suffix("s").unwrap_or(period);
7390
return match period {
74-
"second" => Some(1),
75-
"minute" => Some(60),
76-
"hour" => Some(60 * 60),
77-
"day" => Some(24 * 60 * 60),
78-
"week" => Some(7 * 24 * 60 * 60),
91+
"second" => Ok(1),
92+
"minute" => Ok(60),
93+
"hour" => Ok(60 * 60),
94+
"day" => Ok(24 * 60 * 60),
95+
"week" => Ok(7 * 24 * 60 * 60),
7996
// TODO months & years
80-
_ => None,
97+
_ => Err(Error::InvalidPeriod),
8198
};
8299
}
83100
}

0 commit comments

Comments
 (0)