Add jiff instead of time for time parsing
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
ac76c030c6
commit
51012c19a7
4 changed files with 97 additions and 26 deletions
53
Cargo.lock
generated
53
Cargo.lock
generated
|
|
@ -231,7 +231,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
"serde",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -247,7 +246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -401,6 +400,35 @@ version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
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]]
|
[[package]]
|
||||||
name = "kdl"
|
name = "kdl"
|
||||||
version = "6.3.3"
|
version = "6.3.3"
|
||||||
|
|
@ -715,10 +743,10 @@ dependencies = [
|
||||||
"camino",
|
"camino",
|
||||||
"clap",
|
"clap",
|
||||||
"futures",
|
"futures",
|
||||||
|
"jiff",
|
||||||
"kdl",
|
"kdl",
|
||||||
"miette",
|
"miette",
|
||||||
"owo-colors",
|
"owo-colors",
|
||||||
"time",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -738,6 +766,21 @@ dependencies = [
|
||||||
"time",
|
"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]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
@ -840,7 +883,7 @@ dependencies = [
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1269,7 +1312,7 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ license.workspace = true
|
||||||
camino = { version = "1.1.9", features = ["serde", "serde1"] }
|
camino = { version = "1.1.9", features = ["serde", "serde1"] }
|
||||||
clap = { version = "4.5.27", features = ["derive"] }
|
clap = { version = "4.5.27", features = ["derive"] }
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
|
jiff = "0.1.28"
|
||||||
kdl.workspace = true
|
kdl.workspace = true
|
||||||
miette = { version = "7.4.0", features = ["fancy", "syntect-highlighter"] }
|
miette = { version = "7.4.0", features = ["fancy", "syntect-highlighter"] }
|
||||||
owo-colors = "4.1.0"
|
owo-colors = "4.1.0"
|
||||||
time = { version = "0.3.37", features = ["macros", "parsing", "serde-well-known"] }
|
|
||||||
tokio = { version = "1.43.0", features = ["full"] }
|
tokio = { version = "1.43.0", features = ["full"] }
|
||||||
tokio-stream = { version = "0.1.17", features = ["full"] }
|
tokio-stream = { version = "0.1.17", features = ["full"] }
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,14 @@ use camino::Utf8PathBuf;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
|
use jiff::fmt::temporal::DateTimeParser;
|
||||||
|
use jiff::Timestamp;
|
||||||
use kdl::KdlDocument;
|
use kdl::KdlDocument;
|
||||||
use kdl::KdlValue;
|
use kdl::KdlValue;
|
||||||
use miette::IntoDiagnostic;
|
use miette::IntoDiagnostic;
|
||||||
use miette::LabeledSpan;
|
use miette::LabeledSpan;
|
||||||
use miette::NamedSource;
|
use miette::NamedSource;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use time::OffsetDateTime;
|
|
||||||
use tokio_stream::wrappers::ReadDirStream;
|
use tokio_stream::wrappers::ReadDirStream;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
|
@ -40,10 +41,28 @@ async fn main() -> miette::Result<()> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Record {
|
pub struct Record {
|
||||||
kind: String,
|
kind: String,
|
||||||
at: OffsetDateTime,
|
at: Timestamp,
|
||||||
fields: BTreeMap<String, KdlValue>,
|
fields: BTreeMap<String, KdlValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_timestamp(value: &str) -> miette::Result<Timestamp> {
|
||||||
|
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(
|
fn parse_record(
|
||||||
bytes: &str,
|
bytes: &str,
|
||||||
definitions: &BTreeMap<String, Vec<Definition>>,
|
definitions: &BTreeMap<String, Vec<Definition>>,
|
||||||
|
|
@ -74,8 +93,7 @@ fn parse_record(
|
||||||
))?;
|
))?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(at) = OffsetDateTime::parse(at, &time::format_description::well_known::Rfc3339)
|
let Ok(at) = parse_timestamp(at) else {
|
||||||
else {
|
|
||||||
return Err(miette::diagnostic!(
|
return Err(miette::diagnostic!(
|
||||||
labels = vec![LabeledSpan::new_primary_with_span(None, at_entry.span())],
|
labels = vec![LabeledSpan::new_primary_with_span(None, at_entry.span())],
|
||||||
"This datetime should be a string formatted as RFC3339."
|
"This datetime should be a string formatted as RFC3339."
|
||||||
|
|
@ -100,9 +118,13 @@ fn parse_record(
|
||||||
|
|
||||||
let kind = &matching_def.fields[name.value()];
|
let kind = &matching_def.fields[name.value()];
|
||||||
|
|
||||||
if !kind.is_valid(&val) {
|
if let Err(e) = kind.validate(&val) {
|
||||||
return Err(miette::diagnostic!(
|
Err(miette::diagnostic!(
|
||||||
labels = vec![LabeledSpan::new_primary_with_span(None, name.span())],
|
labels = vec![LabeledSpan::new_primary_with_span(
|
||||||
|
Some(String::from("here")),
|
||||||
|
name.span()
|
||||||
|
)],
|
||||||
|
help = e,
|
||||||
"This field has the wrong kind."
|
"This field has the wrong kind."
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
|
|
@ -143,9 +165,8 @@ async fn load_records(
|
||||||
})
|
})
|
||||||
.flat_map(|val| futures::stream::iter(val.transpose()))
|
.flat_map(|val| futures::stream::iter(val.transpose()))
|
||||||
.and_then(|(name, bytes)| async move {
|
.and_then(|(name, bytes)| async move {
|
||||||
Ok(parse_record(&bytes, definitions).map_err(|e| {
|
parse_record(&bytes, definitions)
|
||||||
e.with_source_code(NamedSource::new(name, bytes).with_language("kdl"))
|
.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>)))
|
.map(|val| val.map(|recs| futures::stream::iter(recs).map(Ok::<_, miette::Report>)))
|
||||||
.try_flatten()
|
.try_flatten()
|
||||||
|
|
@ -161,12 +182,17 @@ pub enum DefinitionKind {
|
||||||
OneOf(Vec<String>),
|
OneOf(Vec<String>),
|
||||||
}
|
}
|
||||||
impl DefinitionKind {
|
impl DefinitionKind {
|
||||||
fn is_valid(&self, val: &KdlValue) -> bool {
|
fn validate(&self, val: &KdlValue) -> Result<(), String> {
|
||||||
match self {
|
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
|
DefinitionKind::OneOf(options) => val
|
||||||
.as_string()
|
.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)]
|
#[derive(Debug)]
|
||||||
pub struct Definition {
|
pub struct Definition {
|
||||||
since: OffsetDateTime,
|
since: Timestamp,
|
||||||
fields: HashMap<String, DefinitionKind>,
|
fields: HashMap<String, DefinitionKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,10 +241,7 @@ fn parse_definition(bytes: &str) -> miette::Result<Vec<Definition>> {
|
||||||
))?;
|
))?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let since = match OffsetDateTime::parse(
|
let since = match parse_timestamp(since) {
|
||||||
since,
|
|
||||||
&time::format_description::well_known::Rfc3339,
|
|
||||||
) {
|
|
||||||
Ok(since) => since,
|
Ok(since) => since,
|
||||||
Err(_err) => {
|
Err(_err) => {
|
||||||
return Err(miette::diagnostic!(
|
return Err(miette::diagnostic!(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
|
changelog "2025-01-29" {
|
||||||
changelog "2025-01-29 21:17:50+01:00" {
|
|
||||||
title "Added parsing of plaixt definitions"
|
title "Added parsing of plaixt definitions"
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
kind "Feature"
|
kind "Feature"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changelog "2025-01-30 09:10:59+01:00" {
|
||||||
|
title "Added parsing of plaixt records"
|
||||||
|
version "0.1.0"
|
||||||
|
kind "Feature"
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue