From 51012c19a757918f06cc955db3d8b82d9e9d1c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Thu, 30 Jan 2025 21:59:59 +0100 Subject: [PATCH] Add jiff instead of time for time parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- Cargo.lock | 53 +++++++++++++++++++++++++++++++---- crates/plaixt/Cargo.toml | 2 +- crates/plaixt/src/main.rs | 59 +++++++++++++++++++++++++++------------ examples/changelog.plrecs | 9 ++++-- 4 files changed, 97 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d6666c..0e72155 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,7 +231,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -247,7 +246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -401,6 +400,35 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +[[package]] +name = "jiff" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c607c728e28764fecde611a2764a3a5db19ae21dcec46f292244f5cc5c085a81" +dependencies = [ + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", + "windows-sys 0.59.0", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2cec2f5d266af45a071ece48b1fb89f3b00b2421ac3a5fe10285a6caaa60d3" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a63c62e404e7b92979d2792352d885a7f8f83fd1d0d31eea582d77b2ceca697e" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "kdl" version = "6.3.3" @@ -715,10 +743,10 @@ dependencies = [ "camino", "clap", "futures", + "jiff", "kdl", "miette", "owo-colors", - "time", "tokio", "tokio-stream", "tracing", @@ -738,6 +766,21 @@ dependencies = [ "time", ] +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -840,7 +883,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1269,7 +1312,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/crates/plaixt/Cargo.toml b/crates/plaixt/Cargo.toml index a7bcc36..f9b430b 100644 --- a/crates/plaixt/Cargo.toml +++ b/crates/plaixt/Cargo.toml @@ -9,10 +9,10 @@ license.workspace = true camino = { version = "1.1.9", features = ["serde", "serde1"] } clap = { version = "4.5.27", features = ["derive"] } futures = "0.3.31" +jiff = "0.1.28" kdl.workspace = true miette = { version = "7.4.0", features = ["fancy", "syntect-highlighter"] } owo-colors = "4.1.0" -time = { version = "0.3.37", features = ["macros", "parsing", "serde-well-known"] } tokio = { version = "1.43.0", features = ["full"] } tokio-stream = { version = "0.1.17", features = ["full"] } tracing = "0.1.41" diff --git a/crates/plaixt/src/main.rs b/crates/plaixt/src/main.rs index fd6443c..8def3c7 100644 --- a/crates/plaixt/src/main.rs +++ b/crates/plaixt/src/main.rs @@ -6,13 +6,14 @@ use camino::Utf8PathBuf; use clap::Parser; use futures::StreamExt; use futures::TryStreamExt; +use jiff::fmt::temporal::DateTimeParser; +use jiff::Timestamp; use kdl::KdlDocument; use kdl::KdlValue; use miette::IntoDiagnostic; use miette::LabeledSpan; use miette::NamedSource; use owo_colors::OwoColorize; -use time::OffsetDateTime; use tokio_stream::wrappers::ReadDirStream; use tracing::info; @@ -40,10 +41,28 @@ async fn main() -> miette::Result<()> { #[derive(Debug)] pub struct Record { kind: String, - at: OffsetDateTime, + at: Timestamp, fields: BTreeMap, } +fn parse_timestamp(value: &str) -> miette::Result { + let parser = DateTimeParser::new(); + + parser + .parse_timestamp(value) + .or_else(|_| { + parser + .parse_datetime(value) + .and_then(|date| date.in_tz("UTC").map(|z| z.timestamp())) + }) + .or_else(|_| { + parser + .parse_date(value) + .and_then(|date| date.in_tz("UTC").map(|z| z.timestamp())) + }) + .into_diagnostic() +} + fn parse_record( bytes: &str, definitions: &BTreeMap>, @@ -74,8 +93,7 @@ fn parse_record( ))?; }; - let Ok(at) = OffsetDateTime::parse(at, &time::format_description::well_known::Rfc3339) - else { + let Ok(at) = parse_timestamp(at) else { return Err(miette::diagnostic!( labels = vec![LabeledSpan::new_primary_with_span(None, at_entry.span())], "This datetime should be a string formatted as RFC3339." @@ -100,9 +118,13 @@ fn parse_record( let kind = &matching_def.fields[name.value()]; - if !kind.is_valid(&val) { - return Err(miette::diagnostic!( - labels = vec![LabeledSpan::new_primary_with_span(None, name.span())], + if let Err(e) = kind.validate(&val) { + Err(miette::diagnostic!( + labels = vec![LabeledSpan::new_primary_with_span( + Some(String::from("here")), + name.span() + )], + help = e, "This field has the wrong kind." ))?; } @@ -143,9 +165,8 @@ async fn load_records( }) .flat_map(|val| futures::stream::iter(val.transpose())) .and_then(|(name, bytes)| async move { - Ok(parse_record(&bytes, definitions).map_err(|e| { - e.with_source_code(NamedSource::new(name, bytes).with_language("kdl")) - })?) + parse_record(&bytes, definitions) + .map_err(|e| e.with_source_code(NamedSource::new(name, bytes).with_language("kdl"))) }) .map(|val| val.map(|recs| futures::stream::iter(recs).map(Ok::<_, miette::Report>))) .try_flatten() @@ -161,12 +182,17 @@ pub enum DefinitionKind { OneOf(Vec), } impl DefinitionKind { - fn is_valid(&self, val: &KdlValue) -> bool { + fn validate(&self, val: &KdlValue) -> Result<(), String> { match self { - DefinitionKind::String => val.is_string(), + DefinitionKind::String => val + .is_string() + .then_some(()) + .ok_or("Expected a string here".to_string()), DefinitionKind::OneOf(options) => val .as_string() - .is_some_and(|val| options.iter().any(|o| o == val)), + .is_some_and(|val| options.iter().any(|o| o == val)) + .then_some(()) + .ok_or_else(|| format!("Expected one of: {}", options.join(", "))), } } } @@ -183,7 +209,7 @@ impl TryFrom<&str> for DefinitionKind { #[derive(Debug)] pub struct Definition { - since: OffsetDateTime, + since: Timestamp, fields: HashMap, } @@ -215,10 +241,7 @@ fn parse_definition(bytes: &str) -> miette::Result> { ))?; }; - let since = match OffsetDateTime::parse( - since, - &time::format_description::well_known::Rfc3339, - ) { + let since = match parse_timestamp(since) { Ok(since) => since, Err(_err) => { return Err(miette::diagnostic!( diff --git a/examples/changelog.plrecs b/examples/changelog.plrecs index 5a68530..c2514ec 100644 --- a/examples/changelog.plrecs +++ b/examples/changelog.plrecs @@ -1,6 +1,11 @@ - -changelog "2025-01-29 21:17:50+01:00" { +changelog "2025-01-29" { title "Added parsing of plaixt definitions" version "0.1.0" kind "Feature" } + +changelog "2025-01-30 09:10:59+01:00" { + title "Added parsing of plaixt records" + version "0.1.0" + kind "Feature" +}