sqlite_graphrag/parsers/
mod.rs1use chrono::DateTime;
4
5pub fn parse_expected_updated_at(s: &str) -> Result<i64, String> {
7 if let Ok(secs) = s.parse::<i64>() {
8 if secs >= 0 {
9 return Ok(secs);
10 }
11 }
12 DateTime::parse_from_rfc3339(s)
13 .map(|dt| dt.timestamp())
14 .map_err(|e| {
15 format!(
16 "value must be a Unix epoch (integer >= 0) or RFC 3339 (e.g. 2026-04-19T12:00:00Z): {e}"
17 )
18 })
19}
20
21pub fn parse_k_range(s: &str) -> Result<usize, String> {
27 let value: usize = s
28 .parse()
29 .map_err(|_| format!("'{s}' is not a valid non-negative integer"))?;
30 if !(1..=4096).contains(&value) {
31 return Err(format!(
32 "k must be between 1 and 4096 (inclusive); got {value}"
33 ));
34 }
35 Ok(value)
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn accepts_unix_epoch() {
44 assert_eq!(parse_expected_updated_at("1700000000").unwrap(), 1700000000);
45 }
46
47 #[test]
48 fn accepts_zero() {
49 assert_eq!(parse_expected_updated_at("0").unwrap(), 0);
50 }
51
52 #[test]
53 fn accepts_rfc_3339_utc() {
54 let result = parse_expected_updated_at("2020-01-01T00:00:00Z");
55 assert!(result.is_ok());
56 assert_eq!(result.unwrap(), 1577836800);
57 }
58
59 #[test]
60 fn accepts_rfc_3339_with_offset() {
61 let result = parse_expected_updated_at("2026-04-19T12:00:00+00:00");
62 assert!(result.is_ok());
63 }
64
65 #[test]
66 fn rejects_invalid_string() {
67 assert!(parse_expected_updated_at("bananas").is_err());
68 }
69
70 #[test]
71 fn rejects_negative() {
72 let err = parse_expected_updated_at("-1");
73 assert!(err.is_err());
74 }
75
76 #[test]
77 fn error_message_mentions_format() {
78 let msg = parse_expected_updated_at("invalid").unwrap_err();
79 assert!(msg.contains("RFC 3339") || msg.contains("Unix epoch"));
80 }
81
82 #[test]
83 fn k_accepts_valid_range_endpoints() {
84 assert_eq!(parse_k_range("1").unwrap(), 1);
85 assert_eq!(parse_k_range("4096").unwrap(), 4096);
86 assert_eq!(parse_k_range("10").unwrap(), 10);
87 }
88
89 #[test]
90 fn k_rejects_zero() {
91 let msg = parse_k_range("0").unwrap_err();
92 assert!(msg.contains("between 1 and 4096"));
93 }
94
95 #[test]
96 fn k_rejects_above_limit() {
97 let msg = parse_k_range("10000").unwrap_err();
98 assert!(msg.contains("between 1 and 4096"));
99 }
100
101 #[test]
102 fn k_rejects_non_integer() {
103 let msg = parse_k_range("abc").unwrap_err();
104 assert!(msg.contains("not a valid"));
105 }
106
107 #[test]
108 fn k_rejects_negative() {
109 assert!(parse_k_range("-5").is_err());
111 }
112}