Skip to content

Commit ca7800c

Browse files
committed
refactor
- make `parse_raw()` private as it will proabbloy be merged into `parse_header()` one day. - add more tests for good measure
1 parent 9c28f33 commit ca7800c

File tree

3 files changed

+72
-36
lines changed

3 files changed

+72
-36
lines changed

gix-date/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub mod time;
1313

1414
///
1515
pub mod parse;
16-
pub use parse::function::{parse, parse_header, parse_raw};
16+
pub use parse::function::{parse, parse_header};
1717

1818
/// A timestamp with timezone.
1919
#[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]

gix-date/src/parse.rs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ pub(crate) mod function {
252252
///
253253
/// The goal is to only accept inputs that _unambiguously_ look like
254254
/// git's raw date format.
255-
pub fn parse_raw(input: &str) -> Option<Time> {
255+
fn parse_raw(input: &str) -> Option<Time> {
256256
let mut split = input.split_whitespace();
257257
let seconds = split.next()?.parse::<SecondsSinceUnixEpoch>().ok()?;
258258
let offset_str = split.next()?;
@@ -279,7 +279,7 @@ pub(crate) mod function {
279279
return None;
280280
}
281281
let offset: i32 = sign * ((hours as i32) * 3600 + (minutes as i32) * 60);
282-
Some(Time { seconds, offset })
282+
Time { seconds, offset }.into()
283283
}
284284

285285
/// This is just like `Zoned::strptime`, but it allows parsing datetimes
@@ -298,6 +298,75 @@ pub(crate) mod function {
298298
static P: rfc2822::DateTimeParser = rfc2822::DateTimeParser::new().relaxed_weekday(true);
299299
P.parse_zoned(input)
300300
}
301+
302+
#[cfg(test)]
303+
mod tests {
304+
use super::*;
305+
306+
#[test]
307+
fn parse_raw_valid() {
308+
// These examples show how it's more loose than it has to be,
309+
// merely as a side effect of the implementation.
310+
for (valid, expected_seconds, expected_offset) in [
311+
("12345 +0000", 12345, 0),
312+
("-1234567 +0000", -1234567, 0),
313+
("+1234567 -000000", 1234567, 0),
314+
(" +0 -000000 ", 0, 0),
315+
("\t-0\t-0000\t", 0, 0),
316+
("\n-0\r\n-0000\n", 0, 0),
317+
] {
318+
assert_eq!(
319+
parse_raw(valid),
320+
Some(Time {
321+
seconds: expected_seconds,
322+
offset: expected_offset
323+
}),
324+
"should succeed: '{valid}'"
325+
);
326+
}
327+
}
328+
329+
#[test]
330+
fn parse_raw_invalid() {
331+
for (bad_date_str, message) in [
332+
("123456 !0600", "invalid sign - must be + or -"),
333+
("123456 0600", "missing offset sign"),
334+
("123456 +060", "positive offset too short"),
335+
("123456 -060", "negative offset too short"),
336+
("123456 +06000", "not enough offset seconds"),
337+
("123456 --060", "duplicate offset sign with correct offset length"),
338+
("123456 -+060", "multiple offset signs with correct offset length"),
339+
("123456 --0600", "multiple offset signs, but incorrect offset length"),
340+
("123456 +-06000", "multiple offset signs with correct offset length"),
341+
("123456 +-0600", "multiple offset signs with incorrect offset length"),
342+
("123456 +-060", "multiple offset signs with correct offset length"),
343+
("123456 +10030", "invalid offset length with one 'second' field"),
344+
("123456 06000", "invalid offset length, missing sign"),
345+
("123456 +0600 extra", "extra field past offset"),
346+
("123456 +0600 2005", "extra field past offset that looks like year"),
347+
("123456+0600", "missing space between unix timestamp and offset"),
348+
(
349+
"123456 + 600",
350+
"extra spaces between sign and offset (which also is too short)",
351+
),
352+
("123456 -1500", "negative offset hours out of bounds"),
353+
("123456 +1500", "positive offset hours out of bounds"),
354+
("123456 +6600", "positive offset hours out of bounds"),
355+
("123456 +0660", "invalid offset minutes"),
356+
("123456 +060010", "positive offset seconds is allowed but only if zero"),
357+
("123456 -060010", "negative offset seconds is allowed but only if zero"),
358+
("123456 +0075", "positive offset minutes invalid"),
359+
("++123456 +0000", "duplicate timestamp sign"),
360+
("--123456 +0000", "duplicate timestamp sign"),
361+
("1234567 -+1+1+0", "unsigned offset parsing rejects '+'"),
362+
] {
363+
assert!(
364+
parse_raw(bad_date_str).is_none(),
365+
"should fail: '{bad_date_str}': {message}"
366+
);
367+
}
368+
}
369+
}
301370
}
302371

303372
mod relative {

gix-date/tests/time/parse.rs

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -122,39 +122,6 @@ fn raw() -> gix_testtools::Result {
122122
Ok(())
123123
}
124124

125-
#[test]
126-
fn bad_raw_strict() {
127-
for bad_date_str in [
128-
"123456 !0600",
129-
"123456 0600",
130-
"123456 +060",
131-
"123456 -060",
132-
"123456 +06000",
133-
"123456 --060",
134-
"123456 -+060",
135-
"123456 --0600",
136-
"123456 +-06000",
137-
"123456 +-0600",
138-
"123456 +-060",
139-
"123456 +10030",
140-
"123456 06000",
141-
"123456 0600",
142-
"123456 +0600 extra",
143-
"123456 +0600 2005",
144-
"123456+0600",
145-
"123456 + 600",
146-
"123456 -1500",
147-
"123456 +1500",
148-
"123456 +6600",
149-
"123456 +0660",
150-
"123456 +060010",
151-
"123456 -060010",
152-
"123456 +0075",
153-
] {
154-
assert!(gix_date::parse_raw(bad_date_str).is_none());
155-
}
156-
}
157-
158125
#[test]
159126
fn bad_raw() {
160127
for bad_date_str in [

0 commit comments

Comments
 (0)