diff --git a/Cargo.lock b/Cargo.lock index 2f60fee..9613c30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,6 +151,17 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "kdl" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062c875482ccb676fd40c804a40e3824d4464c18c364547456d1c8e8e951ae47" +dependencies = [ + "miette", + "nom", + "thiserror", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -169,6 +180,7 @@ version = "0.12.2" dependencies = [ "anyhow", "clap", + "kdl", "serde_json", "serde_yaml", "toml", @@ -191,6 +203,45 @@ version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +[[package]] +name = "miette" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" +dependencies = [ + "miette-derive", + "once_cell", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -372,6 +423,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -483,6 +554,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unsafe-libyaml" version = "0.2.11" diff --git a/Cargo.toml b/Cargo.toml index 1cff787..3b68efb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ toml = { version = "0.8.12", features = ["display"] } serde_yaml = "0.9.34" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +kdl = "4.6.0" [profile.release] lto = true diff --git a/lq.rs b/lq.rs index f104cb1..82f3d89 100644 --- a/lq.rs +++ b/lq.rs @@ -12,6 +12,7 @@ enum Input { Yaml, Json, Toml, + Kdl, } #[derive(Copy, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] @@ -187,6 +188,28 @@ impl Args { Ok(serde_json::to_vec(&doc_as)?) } + fn read_kdl(&mut self) -> Result> { + use kdl::KdlDocument; + let mut buf = String::new(); + let kdl_str = if let Some(f) = &self.file { + if !std::path::Path::new(&f).exists() { + Self::try_parse_from(["cmd", "-h"])?; + std::process::exit(2); + } + std::fs::read_to_string(f)? + } else if !stdin().is_terminal() && !cfg!(test) { + debug!("reading from stdin"); + stdin().read_to_string(&mut buf)?; + buf + } else { + Self::try_parse_from(["cmd", "-h"])?; + std::process::exit(2); + }; + let doc: KdlDocument = kdl_str.parse()?; + let doc_as: serde_json::Value = doc.try_into()?; + Ok(serde_json::to_vec(&doc_as)?) + } + fn read_json(&mut self) -> Result> { let json_value: serde_json::Value = if let Some(f) = &self.file { if !std::path::Path::new(&f).exists() { @@ -209,6 +232,7 @@ impl Args { let ser = match self.input { Input::Yaml => self.read_yaml()?, Input::Toml => self.read_toml()?, + Input::Kdl => self.read_kdl()?, Input::Json => self.read_json()?, }; debug!("input decoded as json: {}", String::from_utf8_lossy(&ser));