From 77d3f45d67623126b8923e03473c2ea8076eff7d Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Wed, 4 Oct 2023 08:19:11 +0200 Subject: [PATCH 01/23] Update deps --- Cargo.lock | 377 ++++++++++++++++++++++++++++++++++++++++------------- Cargo.toml | 8 +- 2 files changed, 289 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index caff2f6..3c1c170 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,244 +1,437 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "atty" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.19", + "libc", + "winapi", ] [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "clap" -version = "2.33.0" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "colored" -version = "1.9.0" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "is-terminal", + "lazy_static", + "windows-sys", +] + +[[package]] +name = "errno" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", ] [[package]] name = "heck" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.3", + "rustix", + "windows-sys", ] [[package]] name = "itoa" -version = "0.4.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "json_diff" version = "0.1.2" dependencies = [ - "colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "colored", + "maplit", + "serde_json", + "structopt", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.65" +version = "0.2.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "linux-raw-sys" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "proc-macro-error" -version = "0.2.6" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "version_check", ] [[package]] name = "proc-macro2" -version = "1.0.6" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustix" +version = "0.38.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.2" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "serde" -version = "1.0.102" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.5" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "lazy_static", + "structopt-derive", ] [[package]] name = "structopt-derive" -version = "0.3.5" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] name = "syn" -version = "1.0.8" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "unicode-segmentation" -version = "1.6.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.6" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] -name = "unicode-xid" -version = "0.2.0" +name = "vec_map" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] -name = "vec_map" -version = "0.8.1" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[metadata] -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "433e7ac7d511768127ed85b0c4947f47a254131e37864b2dc13f52aa32cd37e5" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" -"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" -"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" -"checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" -"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index a124a1b..cd68c3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ path = "src/main.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde_json = "1.0.41" -maplit = "1.0.2" -colored = "1.9.0" -structopt = "0.3.5" +serde_json = "1.0" +maplit = "1.0" +colored = "2.0" +structopt = "0.3" From f634b5cc0a6fd1bc3e268f9803a0e4f7efe537c7 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Wed, 4 Oct 2023 08:23:49 +0200 Subject: [PATCH 02/23] Reformat and make truncation length optional arg for the function --- src/ds/key_node.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index 78e2c4d..335c5a6 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -2,7 +2,7 @@ use colored::*; use serde_json::Value; use std::collections::HashMap; -#[derive(Debug, PartialEq)] // TODO check: do we need PartiaEq ? +#[derive(Debug, PartialEq)] pub enum KeyNode { Nil, Value(Value, Value), @@ -22,7 +22,13 @@ fn truncate(s: &str, max_chars: usize) -> String { } impl KeyNode { - pub fn absolute_keys(&self, keys: &mut Vec, key_from_root: Option) { + pub fn absolute_keys( + &self, + keys: &mut Vec, + key_from_root: Option, + max_display_length: Option, + ) { + let max_display_length = max_display_length.unwrap_or(20); let val_key = |key: Option| { key.map(|mut s| { s.push_str(" ->"); @@ -36,18 +42,22 @@ impl KeyNode { KeyNode::Value(a, b) => keys.push(format!( "{} [ {} :: {} ]", val_key(key_from_root), - truncate(a.to_string().as_str(), 20).blue().bold(), - truncate(b.to_string().as_str(), 20).cyan().bold() + truncate(a.to_string().as_str(), max_display_length) + .blue() + .bold(), + truncate(b.to_string().as_str(), max_display_length) + .cyan() + .bold() )), KeyNode::Node(map) => { for (key, value) in map { value.absolute_keys( keys, Some(format!("{} {}", val_key(key_from_root.clone()), key)), + Some(max_display_length), ) } } } } } - From 9a8c03d0a2a782e5a2c8fe14d40d680ba07afa18 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Wed, 4 Oct 2023 08:31:58 +0200 Subject: [PATCH 03/23] Smaller code/internal cleanups Fix compilation --- src/ds/key_node.rs | 6 +++--- src/main.rs | 11 ++++++----- src/process.rs | 46 ++++++++++++++++++++++++++++++---------------- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index 335c5a6..59fae44 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -16,7 +16,7 @@ fn truncate(s: &str, max_chars: usize) -> String { let shorter = &s[..idx]; let snip = "//SNIP//"; let new_s = format!("{}{}", shorter, snip); - String::from(new_s) + new_s } } } @@ -34,9 +34,9 @@ impl KeyNode { s.push_str(" ->"); s }) - .unwrap_or(String::new()) + .unwrap_or_default() }; - let nil_key = |key: Option| key.unwrap_or(String::new()); + let nil_key = |key: Option| key.unwrap_or_default(); match self { KeyNode::Nil => keys.push(nil_key(key_from_root)), KeyNode::Value(a, b) => keys.push(format!( diff --git a/src/main.rs b/src/main.rs index 5acf214..e80e6d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -102,13 +102,13 @@ pub fn display_output(result: Mismatch) -> Result<(), std::io::Error> { let stdout = io::stdout(); let mut handle = io::BufWriter::new(stdout.lock()); - Ok(if no_mismatch == result { + if no_mismatch == result { writeln!(handle, "\n{}", Message::NoMismatch)?; } else { match result.keys_in_both { KeyNode::Node(_) => { let mut keys = Vec::new(); - result.keys_in_both.absolute_keys(&mut keys, None); + result.keys_in_both.absolute_keys(&mut keys, None, None); writeln!(handle, "\n{} ({}):", Message::Mismatch, keys.len())?; for key in keys { writeln!(handle, "{}", key)?; @@ -120,7 +120,7 @@ pub fn display_output(result: Mismatch) -> Result<(), std::io::Error> { match result.left_only_keys { KeyNode::Node(_) => { let mut keys = Vec::new(); - result.left_only_keys.absolute_keys(&mut keys, None); + result.left_only_keys.absolute_keys(&mut keys, None, None); writeln!(handle, "\n{} ({}):", Message::LeftExtra, keys.len())?; for key in keys { writeln!(handle, "{}", key.red().bold())?; @@ -132,7 +132,7 @@ pub fn display_output(result: Mismatch) -> Result<(), std::io::Error> { match result.right_only_keys { KeyNode::Node(_) => { let mut keys = Vec::new(); - result.right_only_keys.absolute_keys(&mut keys, None); + result.right_only_keys.absolute_keys(&mut keys, None, None); writeln!(handle, "\n{} ({}):", Message::RightExtra, keys.len())?; for key in keys { writeln!(handle, "{}", key.green().bold())?; @@ -141,5 +141,6 @@ pub fn display_output(result: Mismatch) -> Result<(), std::io::Error> { KeyNode::Value(_, _) => (), KeyNode::Nil => (), } - }) + }; + Ok(()) } diff --git a/src/process.rs b/src/process.rs index c34e627..b11e1ec 100644 --- a/src/process.rs +++ b/src/process.rs @@ -23,11 +23,12 @@ pub fn compare_jsons(a: &str, b: &str) -> Result { pub fn match_json(value1: &Value, value2: &Value) -> Mismatch { match (value1, value2) { (Value::Object(a), Value::Object(b)) => { - let (left_only_keys, right_only_keys, intersection_keys) = intersect_maps(&a, &b); + let diff = intersect_maps(a, b); + let mut left_only_keys = get_map_of_keys(diff.left_only); + let mut right_only_keys = get_map_of_keys(diff.right_only); + let intersection_keys = diff.intersection; let mut unequal_keys = KeyNode::Nil; - let mut left_only_keys = get_map_of_keys(left_only_keys); - let mut right_only_keys = get_map_of_keys(right_only_keys); if let Some(intersection_keys) = intersection_keys { for key in intersection_keys { @@ -35,7 +36,7 @@ pub fn match_json(value1: &Value, value2: &Value) -> Mismatch { left_only_keys: l, right_only_keys: r, keys_in_both: u, - } = match_json(&a.get(&key).unwrap(), &b.get(&key).unwrap()); + } = match_json(a.get(&key).unwrap(), b.get(&key).unwrap()); left_only_keys = insert_child_key_map(left_only_keys, l, &key); right_only_keys = insert_child_key_map(right_only_keys, r, &key); unequal_keys = insert_child_key_map(unequal_keys, u, &key); @@ -85,14 +86,27 @@ fn insert_child_key_map(parent: KeyNode, child: KeyNode, key: &String) -> KeyNod } } -fn intersect_maps( - a: &Map, - b: &Map, -) -> ( - Option>, - Option>, - Option>, -) { +struct MapDifference { + left_only: Option>, + right_only: Option>, + intersection: Option>, +} + +impl MapDifference { + pub fn new( + left_only: Option>, + right_only: Option>, + intersection: Option>, + ) -> Self { + Self { + right_only, + left_only, + intersection, + } + } +} + +fn intersect_maps(a: &Map, b: &Map) -> MapDifference { let mut intersection = HashSet::new(); let mut left = HashSet::new(); let mut right = HashSet::new(); @@ -108,14 +122,14 @@ fn intersect_maps( right.insert(String::from(b_key)); } } - let left = if left.len() == 0 { None } else { Some(left) }; - let right = if right.len() == 0 { None } else { Some(right) }; - let intersection = if intersection.len() == 0 { + let left = if left.is_empty() { None } else { Some(left) }; + let right = if right.is_empty() { None } else { Some(right) }; + let intersection = if intersection.is_empty() { None } else { Some(intersection) }; - (left, right, intersection) + MapDifference::new(left, right, intersection) } #[cfg(test)] From 8bea37acfd18885000146dfb633ee565871c290c Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Wed, 4 Oct 2023 08:53:39 +0200 Subject: [PATCH 04/23] Add more convenient method of getting the absolute keys without external vector initialization --- src/ds/key_node.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index 59fae44..772a171 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -22,6 +22,12 @@ fn truncate(s: &str, max_chars: usize) -> String { } impl KeyNode { + pub fn absolute_keys_to_vec(&self, max_display_length: Option) -> Vec { + let mut vec = Vec::new(); + self.absolute_keys(&mut vec, None, max_display_length); + vec + } + pub fn absolute_keys( &self, keys: &mut Vec, @@ -36,9 +42,8 @@ impl KeyNode { }) .unwrap_or_default() }; - let nil_key = |key: Option| key.unwrap_or_default(); match self { - KeyNode::Nil => keys.push(nil_key(key_from_root)), + KeyNode::Nil => keys.push(key_from_root.unwrap_or_default()), KeyNode::Value(a, b) => keys.push(format!( "{} [ {} :: {} ]", val_key(key_from_root), From f0cbf497021eef961a5d68a5a7931d4a168f80f2 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Wed, 4 Oct 2023 23:04:18 +0200 Subject: [PATCH 05/23] Add convenience API and use more modern clap package in arg parsing --- Cargo.lock | 242 +++++++++++++++++++-------------------------- Cargo.toml | 4 +- src/constants.rs | 49 ++++----- src/ds/mismatch.rs | 21 ++++ src/main.rs | 160 ++++++++---------------------- src/process.rs | 18 ++-- 6 files changed, 193 insertions(+), 301 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c1c170..885b15e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,30 +3,52 @@ version = 3 [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "utf8parse", ] [[package]] -name = "bitflags" -version = "1.3.2" +name = "anstyle-query" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] [[package]] name = "bitflags" @@ -45,19 +67,50 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "4.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "colored" version = "2.0.4" @@ -92,21 +145,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -120,7 +161,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi", "rustix", "windows-sys", ] @@ -135,10 +176,12 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" name = "json_diff" version = "0.1.2" dependencies = [ + "clap", "colored", "maplit", "serde_json", - "structopt", + "thiserror", + "vg_errortools", ] [[package]] @@ -165,30 +208,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.67" @@ -213,7 +232,7 @@ version = "0.38.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" dependencies = [ - "bitflags 2.4.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -243,7 +262,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn", ] [[package]] @@ -259,39 +278,15 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -299,23 +294,23 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.37" +name = "thiserror" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "thiserror-impl", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "thiserror-impl" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ - "unicode-width", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -325,51 +320,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.11" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] -name = "vec_map" -version = "0.8.2" +name = "vg_errortools" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "8f0d7932688493f8aac7d65e824820b6506fe68ae7450bf44ac7299b1841a4a6" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "thiserror", ] -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index cd68c3b..89dc5d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,9 @@ path = "src/main.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +thiserror = "1.0" +vg_errortools = "0.1" serde_json = "1.0" maplit = "1.0" colored = "2.0" -structopt = "0.3" +clap = {version = "4.4", features = ["derive"]} diff --git a/src/constants.rs b/src/constants.rs index 1074046..15cb8a8 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,38 +1,31 @@ -use colored::*; -use std::fmt; +use std::fmt::{Display, Formatter}; +use thiserror::Error; +use vg_errortools::FatIOError; -// PartialEq is added for the sake of Test case that uses assert_eq -#[derive(Debug, PartialEq)] -pub enum Message { - BadOption, - SOURCE1, - SOURCE2, - JSON1, - JSON2, - UnknownError, - NoMismatch, +#[derive(Debug, Error)] +pub enum Error { + #[error("Error opening file: {0}")] + IOError(#[from] FatIOError), + #[error("Error parsing first json: {0}")] + JSON(#[from] serde_json::Error), +} + +#[derive(Debug)] +pub enum DiffType { RootMismatch, LeftExtra, RightExtra, Mismatch, } -impl fmt::Display for Message { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let message = match self { - Message::BadOption => "Invalid option.", - Message::SOURCE1 => "Could not read source1.", - Message::SOURCE2 => "Could not read source2.", - Message::JSON1 => "Could not parse source1.", - Message::JSON2 => "Could not parse source2.", - Message::UnknownError => "", - Message::NoMismatch => "No mismatch was found.", - Message::RootMismatch => "Mismatch at root.", - Message::LeftExtra => "Extra on left", - Message::RightExtra => "Extra on right", - Message::Mismatch => "Mismatched", +impl Display for DiffType { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let msg = match self { + DiffType::RootMismatch => "Mismatch at root.", + DiffType::LeftExtra => "Extra on left", + DiffType::RightExtra => "Extra on right", + DiffType::Mismatch => "Mismatched", }; - - write!(f, "{}", message.bold()) + write!(f, "{}", msg) } } diff --git a/src/ds/mismatch.rs b/src/ds/mismatch.rs index 649739f..3dd7a98 100644 --- a/src/ds/mismatch.rs +++ b/src/ds/mismatch.rs @@ -1,3 +1,4 @@ +use crate::constants::DiffType; use crate::ds::key_node::KeyNode; #[derive(Debug, PartialEq)] @@ -15,4 +16,24 @@ impl Mismatch { keys_in_both: u, } } + + pub fn all_diffs(&self) -> Vec<(DiffType, String)> { + let both = self + .keys_in_both + .absolute_keys_to_vec(None) + .into_iter() + .map(|k| (DiffType::Mismatch, k)); + let left = self + .left_only_keys + .absolute_keys_to_vec(None) + .into_iter() + .map(|k| (DiffType::LeftExtra, k)); + let right = self + .right_only_keys + .absolute_keys_to_vec(None) + .into_iter() + .map(|k| (DiffType::RightExtra, k)); + + both.chain(left).chain(right).collect() + } } diff --git a/src/main.rs b/src/main.rs index e80e6d6..1a7b1f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,146 +1,64 @@ -use std::{ - fmt, fs, - io::{self, Write}, - process as proc, - str::FromStr, -}; - -use colored::*; -use structopt::StructOpt; +use clap::Parser; +use clap::Subcommand; +use json_diff::constants::Error; use json_diff::{ - constants::Message, ds::{key_node::KeyNode, mismatch::Mismatch}, process::compare_jsons, }; -const HELP: &str = r#" -Example: -json_diff f source1.json source2.json -json_diff d '{...}' '{...}' - -Option: -f : read input from json files -d : read input from command line"#; - -#[derive(Debug)] -struct AppError { - message: Message, -} -impl fmt::Display for AppError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.message) - } -} - -enum InputReadMode { - D, - F, -} -impl FromStr for InputReadMode { - type Err = AppError; - fn from_str(s: &str) -> Result { - match s { - "d" => Ok(InputReadMode::D), - "f" => Ok(InputReadMode::F), - _ => Err(Self::Err { - message: Message::BadOption, - }), - } - } +#[derive(Subcommand, Clone)] +/// Input selection +enum Mode { + /// File input + #[clap(short_flag = 'f')] + File { file_1: String, file_2: String }, + /// Read from CLI + #[clap(short_flag = 'd')] + Direct { json_1: String, json_2: String }, } -#[derive(StructOpt)] -#[structopt(about = HELP)] -struct Cli { - read_mode: InputReadMode, - source1: String, - source2: String, +#[derive(Parser)] +struct Args { + #[command(subcommand)] + cmd: Mode, } -fn main() { - let args = Cli::from_args(); - - let (data1, data2) = match args.read_mode { - InputReadMode::D => (args.source1, args.source2), - InputReadMode::F => { - if let Ok(d1) = fs::read_to_string(args.source1) { - if let Ok(d2) = fs::read_to_string(args.source2) { - (d1, d2) - } else { - error_exit(Message::SOURCE2); - } - } else { - error_exit(Message::SOURCE1); - } +fn main() -> Result<(), Error> { + let args = Args::parse(); + let (json_1, json_2) = match args.cmd { + Mode::Direct { json_2, json_1 } => (json_1, json_2), + Mode::File { file_2, file_1 } => { + let d1 = vg_errortools::fat_io_wrap_std(file_1, &std::fs::read_to_string)?; + let d2 = vg_errortools::fat_io_wrap_std(file_2, &std::fs::read_to_string)?; + (d1, d2) } }; - let mismatch = match compare_jsons(&data1, &data2) { - Ok(mismatch) => mismatch, - Err(err) => { - eprintln!("{}", err); - proc::exit(1) - } - }; - match display_output(mismatch) { - Ok(_) => (), - Err(err) => eprintln!("{}", err), - }; -} -fn error_exit(message: Message) -> ! { - eprintln!("{}", message); - proc::exit(1); + let mismatch = compare_jsons(&json_1, &json_2)?; + + let comparison_result = check_diffs(mismatch)?; + if !comparison_result { + std::process::exit(1); + } + Ok(()) } -pub fn display_output(result: Mismatch) -> Result<(), std::io::Error> { +pub fn check_diffs(result: Mismatch) -> Result { let no_mismatch = Mismatch { left_only_keys: KeyNode::Nil, right_only_keys: KeyNode::Nil, keys_in_both: KeyNode::Nil, }; - let stdout = io::stdout(); - let mut handle = io::BufWriter::new(stdout.lock()); if no_mismatch == result { - writeln!(handle, "\n{}", Message::NoMismatch)?; + println!("No mismatch"); + Ok(true) } else { - match result.keys_in_both { - KeyNode::Node(_) => { - let mut keys = Vec::new(); - result.keys_in_both.absolute_keys(&mut keys, None, None); - writeln!(handle, "\n{} ({}):", Message::Mismatch, keys.len())?; - for key in keys { - writeln!(handle, "{}", key)?; - } - } - KeyNode::Value(_, _) => writeln!(handle, "{}", Message::RootMismatch)?, - KeyNode::Nil => (), - } - match result.left_only_keys { - KeyNode::Node(_) => { - let mut keys = Vec::new(); - result.left_only_keys.absolute_keys(&mut keys, None, None); - writeln!(handle, "\n{} ({}):", Message::LeftExtra, keys.len())?; - for key in keys { - writeln!(handle, "{}", key.red().bold())?; - } - } - KeyNode::Value(_, _) => (), - KeyNode::Nil => (), - } - match result.right_only_keys { - KeyNode::Node(_) => { - let mut keys = Vec::new(); - result.right_only_keys.absolute_keys(&mut keys, None, None); - writeln!(handle, "\n{} ({}):", Message::RightExtra, keys.len())?; - for key in keys { - writeln!(handle, "{}", key.green().bold())?; - } - } - KeyNode::Value(_, _) => (), - KeyNode::Nil => (), + let mismatches = result.all_diffs(); + for (d_type, key) in mismatches { + println!("{d_type}: {key}"); } - }; - Ok(()) + Ok(false) + } } diff --git a/src/process.rs b/src/process.rs index b11e1ec..4b26d78 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,22 +1,16 @@ use std::collections::HashMap; use std::collections::HashSet; +use crate::constants::Error; use serde_json::Map; use serde_json::Value; -use crate::constants::Message; use crate::ds::key_node::KeyNode; use crate::ds::mismatch::Mismatch; -pub fn compare_jsons(a: &str, b: &str) -> Result { - let value1 = match serde_json::from_str(a) { - Ok(val1) => val1, - Err(_) => return Err(Message::JSON1), - }; - let value2 = match serde_json::from_str(b) { - Ok(val2) => val2, - Err(_) => return Err(Message::JSON2), - }; +pub fn compare_jsons(a: &str, b: &str) -> Result { + let value1 = serde_json::from_str(a)?; + let value2 = serde_json::from_str(b)?; Ok(match_json(&value1, &value2)) } @@ -268,7 +262,7 @@ mod tests { match compare_jsons(invalid_json1, valid_json2) { Ok(_) => panic!("This shouldn't be an Ok"), Err(err) => { - assert_eq!(Message::JSON1, err); + matches!(err, Error::JSON(_)); } }; } @@ -280,7 +274,7 @@ mod tests { match compare_jsons(valid_json1, invalid_json2) { Ok(_) => panic!("This shouldn't be an Ok"), Err(err) => { - assert_eq!(Message::JSON2, err); + matches!(err, Error::JSON(_)); } }; } From 0c8ac8f6b6bfa5c8285b4f384a653c9c82986f85 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Wed, 4 Oct 2023 23:37:20 +0200 Subject: [PATCH 06/23] Remove colored output --- Cargo.toml | 1 - src/ds/key_node.rs | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 89dc5d1..166ada2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,5 +27,4 @@ thiserror = "1.0" vg_errortools = "0.1" serde_json = "1.0" maplit = "1.0" -colored = "2.0" clap = {version = "4.4", features = ["derive"]} diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index 772a171..6ee7b64 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -1,4 +1,3 @@ -use colored::*; use serde_json::Value; use std::collections::HashMap; @@ -47,12 +46,8 @@ impl KeyNode { KeyNode::Value(a, b) => keys.push(format!( "{} [ {} :: {} ]", val_key(key_from_root), - truncate(a.to_string().as_str(), max_display_length) - .blue() - .bold(), + truncate(a.to_string().as_str(), max_display_length), truncate(b.to_string().as_str(), max_display_length) - .cyan() - .bold() )), KeyNode::Node(map) => { for (key, value) in map { From 19a288fcab9bd848f375ff08403008099ceb0f16 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Wed, 4 Oct 2023 23:37:27 +0200 Subject: [PATCH 07/23] Remove colored output --- Cargo.lock | 96 ------------------------------------------------------ 1 file changed, 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 885b15e..dc772d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,21 +50,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - [[package]] name = "clap" version = "4.4.6" @@ -111,61 +96,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" -[[package]] -name = "colored" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" -dependencies = [ - "is-terminal", - "lazy_static", - "windows-sys", -] - -[[package]] -name = "errno" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys", -] - [[package]] name = "itoa" version = "1.0.9" @@ -177,31 +113,12 @@ name = "json_diff" version = "0.1.2" dependencies = [ "clap", - "colored", "maplit", "serde_json", "thiserror", "vg_errortools", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.148" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" - -[[package]] -name = "linux-raw-sys" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" - [[package]] name = "maplit" version = "1.0.2" @@ -226,19 +143,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rustix" -version = "0.38.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "ryu" version = "1.0.15" From 25675ec4889ee6ae21d7caea87601d510a928334 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Thu, 5 Oct 2023 20:20:55 +0200 Subject: [PATCH 08/23] Improve data structures for library access --- src/constants.rs | 31 --------------------- src/ds/key_node.rs | 12 ++++---- src/ds/mismatch.rs | 4 +-- src/enums.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/main.rs | 2 +- src/process.rs | 2 +- 7 files changed, 79 insertions(+), 42 deletions(-) delete mode 100644 src/constants.rs create mode 100644 src/enums.rs diff --git a/src/constants.rs b/src/constants.rs deleted file mode 100644 index 15cb8a8..0000000 --- a/src/constants.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::fmt::{Display, Formatter}; -use thiserror::Error; -use vg_errortools::FatIOError; - -#[derive(Debug, Error)] -pub enum Error { - #[error("Error opening file: {0}")] - IOError(#[from] FatIOError), - #[error("Error parsing first json: {0}")] - JSON(#[from] serde_json::Error), -} - -#[derive(Debug)] -pub enum DiffType { - RootMismatch, - LeftExtra, - RightExtra, - Mismatch, -} - -impl Display for DiffType { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let msg = match self { - DiffType::RootMismatch => "Mismatch at root.", - DiffType::LeftExtra => "Extra on left", - DiffType::RightExtra => "Extra on right", - DiffType::Mismatch => "Mismatched", - }; - write!(f, "{}", msg) - } -} diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index 6ee7b64..f89a3c8 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -1,3 +1,4 @@ +use crate::enums::ValueType; use serde_json::Value; use std::collections::HashMap; @@ -21,7 +22,7 @@ fn truncate(s: &str, max_chars: usize) -> String { } impl KeyNode { - pub fn absolute_keys_to_vec(&self, max_display_length: Option) -> Vec { + pub fn absolute_keys_to_vec(&self, max_display_length: Option) -> Vec { let mut vec = Vec::new(); self.absolute_keys(&mut vec, None, max_display_length); vec @@ -29,7 +30,7 @@ impl KeyNode { pub fn absolute_keys( &self, - keys: &mut Vec, + keys: &mut Vec, key_from_root: Option, max_display_length: Option, ) { @@ -42,12 +43,11 @@ impl KeyNode { .unwrap_or_default() }; match self { - KeyNode::Nil => keys.push(key_from_root.unwrap_or_default()), - KeyNode::Value(a, b) => keys.push(format!( - "{} [ {} :: {} ]", + KeyNode::Nil => keys.push(ValueType::new_key(key_from_root.unwrap_or_default())), + KeyNode::Value(a, b) => keys.push(ValueType::new_value( val_key(key_from_root), truncate(a.to_string().as_str(), max_display_length), - truncate(b.to_string().as_str(), max_display_length) + truncate(b.to_string().as_str(), max_display_length), )), KeyNode::Node(map) => { for (key, value) in map { diff --git a/src/ds/mismatch.rs b/src/ds/mismatch.rs index 3dd7a98..225bf18 100644 --- a/src/ds/mismatch.rs +++ b/src/ds/mismatch.rs @@ -1,5 +1,5 @@ -use crate::constants::DiffType; use crate::ds::key_node::KeyNode; +use crate::enums::{DiffType, ValueType}; #[derive(Debug, PartialEq)] pub struct Mismatch { @@ -17,7 +17,7 @@ impl Mismatch { } } - pub fn all_diffs(&self) -> Vec<(DiffType, String)> { + pub fn all_diffs(&self) -> Vec<(DiffType, ValueType)> { let both = self .keys_in_both .absolute_keys_to_vec(None) diff --git a/src/enums.rs b/src/enums.rs new file mode 100644 index 0000000..1fb0dce --- /dev/null +++ b/src/enums.rs @@ -0,0 +1,68 @@ +use std::fmt::{Display, Formatter}; +use thiserror::Error; +use vg_errortools::FatIOError; + +#[derive(Debug, Error)] +pub enum Error { + #[error("Error opening file: {0}")] + IOError(#[from] FatIOError), + #[error("Error parsing first json: {0}")] + JSON(#[from] serde_json::Error), +} + +#[derive(Debug)] +pub enum DiffType { + RootMismatch, + LeftExtra, + RightExtra, + Mismatch, +} + +impl Display for DiffType { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let msg = match self { + DiffType::RootMismatch => "Mismatch at root.", + DiffType::LeftExtra => "Extra on left", + DiffType::RightExtra => "Extra on right", + DiffType::Mismatch => "Mismatched", + }; + write!(f, "{}", msg) + } +} + +pub enum ValueType { + Key(String), + Value { + key: String, + value_left: String, + value_right: String, + }, +} + +impl ValueType { + pub fn new_value(key: String, value_left: String, value_right: String) -> Self { + Self::Value { + value_right, + value_left, + key, + } + } + pub fn new_key(key: String) -> Self { + Self::Key(key) + } +} + +impl Display for ValueType { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ValueType::Key(key) => write!(f, "{key}"), + ValueType::Value { + value_left, + key, + value_right, + } => { + write!(f, "{key} [ {value_left} :: {value_right} ]") + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 339800d..626d033 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,3 @@ -pub mod constants; pub mod ds; +pub mod enums; pub mod process; diff --git a/src/main.rs b/src/main.rs index 1a7b1f7..25ef4b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use clap::Parser; use clap::Subcommand; -use json_diff::constants::Error; +use json_diff::enums::Error; use json_diff::{ ds::{key_node::KeyNode, mismatch::Mismatch}, process::compare_jsons, diff --git a/src/process.rs b/src/process.rs index 4b26d78..c6e86cf 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::collections::HashSet; -use crate::constants::Error; +use crate::enums::Error; use serde_json::Map; use serde_json::Value; From 59edca5b212df2f36edb1c79510c329118b7d34f Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Thu, 5 Oct 2023 20:47:43 +0200 Subject: [PATCH 09/23] Improve data structures for library access --- src/enums.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/enums.rs b/src/enums.rs index 1fb0dce..8deb5c3 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -50,6 +50,13 @@ impl ValueType { pub fn new_key(key: String) -> Self { Self::Key(key) } + + pub fn get_key(&self) -> &str { + match self { + ValueType::Value { key, .. } => key.as_str(), + ValueType::Key(key) => key.as_str(), + } + } } impl Display for ValueType { From 55fc1e4d3ada8dea17103526957ab1fc0a720991 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Thu, 5 Oct 2023 23:23:39 +0200 Subject: [PATCH 10/23] Make the truncation available in CLI --- src/ds/key_node.rs | 2 +- src/ds/mismatch.rs | 10 +++++++--- src/main.rs | 4 ++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index f89a3c8..b2b051c 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -34,7 +34,7 @@ impl KeyNode { key_from_root: Option, max_display_length: Option, ) { - let max_display_length = max_display_length.unwrap_or(20); + let max_display_length = max_display_length.unwrap_or(4000); let val_key = |key: Option| { key.map(|mut s| { s.push_str(" ->"); diff --git a/src/ds/mismatch.rs b/src/ds/mismatch.rs index 225bf18..8ee887a 100644 --- a/src/ds/mismatch.rs +++ b/src/ds/mismatch.rs @@ -18,19 +18,23 @@ impl Mismatch { } pub fn all_diffs(&self) -> Vec<(DiffType, ValueType)> { + self.all_diffs_trunc(None) + } + + pub fn all_diffs_trunc(&self, truncation_length: Option) -> Vec<(DiffType, ValueType)> { let both = self .keys_in_both - .absolute_keys_to_vec(None) + .absolute_keys_to_vec(truncation_length) .into_iter() .map(|k| (DiffType::Mismatch, k)); let left = self .left_only_keys - .absolute_keys_to_vec(None) + .absolute_keys_to_vec(truncation_length) .into_iter() .map(|k| (DiffType::LeftExtra, k)); let right = self .right_only_keys - .absolute_keys_to_vec(None) + .absolute_keys_to_vec(truncation_length) .into_iter() .map(|k| (DiffType::RightExtra, k)); diff --git a/src/main.rs b/src/main.rs index 25ef4b2..1ff7af1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,10 @@ enum Mode { struct Args { #[command(subcommand)] cmd: Mode, + + #[clap(short, long, default_value_t = 20)] + /// truncate keys with more chars then this parameter + truncation_length: usize, } fn main() -> Result<(), Error> { From 2413fdfbab8a210131f362578e6b637a577b56d3 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Thu, 5 Oct 2023 23:26:41 +0200 Subject: [PATCH 11/23] Bump version to 0.2.0 --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc772d6..2796848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,7 +110,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "json_diff" -version = "0.1.2" +version = "0.2.0" dependencies = [ "clap", "maplit", diff --git a/Cargo.toml b/Cargo.toml index 166ada2..ef5a3b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "json_diff" -version = "0.1.2" +version = "0.2.0" authors = ["ksceriath"] -edition = "2018" +edition = "2021" license = "Unlicense" description = "A small diff tool utility for comparing jsons" readme = "README.md" From d81d4bfaf3611bcfebe50ce9dbac7d43f0d7b83c Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Fri, 6 Oct 2023 22:08:04 +0200 Subject: [PATCH 12/23] Fix issue with empty strings being propagated as diff --- Cargo.toml | 2 +- src/ds/key_node.rs | 6 +++++- src/ds/mismatch.rs | 19 +++++++++++++++++++ src/main.rs | 6 +----- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef5a3b7..e7f39b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json_diff" -version = "0.2.0" +version = "0.2.1" authors = ["ksceriath"] edition = "2021" license = "Unlicense" diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index b2b051c..8e004a9 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -43,7 +43,11 @@ impl KeyNode { .unwrap_or_default() }; match self { - KeyNode::Nil => keys.push(ValueType::new_key(key_from_root.unwrap_or_default())), + KeyNode::Nil => { + if let Some(key) = key_from_root { + keys.push(ValueType::new_key(key)) + } + } KeyNode::Value(a, b) => keys.push(ValueType::new_value( val_key(key_from_root), truncate(a.to_string().as_str(), max_display_length), diff --git a/src/ds/mismatch.rs b/src/ds/mismatch.rs index 8ee887a..2e71c5f 100644 --- a/src/ds/mismatch.rs +++ b/src/ds/mismatch.rs @@ -17,6 +17,14 @@ impl Mismatch { } } + pub fn empty() -> Self { + Mismatch { + left_only_keys: KeyNode::Nil, + keys_in_both: KeyNode::Nil, + right_only_keys: KeyNode::Nil, + } + } + pub fn all_diffs(&self) -> Vec<(DiffType, ValueType)> { self.all_diffs_trunc(None) } @@ -41,3 +49,14 @@ impl Mismatch { both.chain(left).chain(right).collect() } } + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn empty_diffs() { + let empty = Mismatch::empty(); + let all_diffs = empty.all_diffs(); + assert!(all_diffs.is_empty()); + } +} diff --git a/src/main.rs b/src/main.rs index 1ff7af1..7715d44 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,11 +49,7 @@ fn main() -> Result<(), Error> { } pub fn check_diffs(result: Mismatch) -> Result { - let no_mismatch = Mismatch { - left_only_keys: KeyNode::Nil, - right_only_keys: KeyNode::Nil, - keys_in_both: KeyNode::Nil, - }; + let no_mismatch = Mismatch::empty(); if no_mismatch == result { println!("No mismatch"); From 7d96bafed5bd12f063e37d4d84774f421f496545 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Fri, 6 Oct 2023 22:09:26 +0200 Subject: [PATCH 13/23] Cleanup main.rs --- Cargo.lock | 2 +- src/main.rs | 21 ++++++--------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2796848..31be554 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,7 +110,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "json_diff" -version = "0.2.0" +version = "0.2.1" dependencies = [ "clap", "maplit", diff --git a/src/main.rs b/src/main.rs index 7715d44..56abcb5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,10 +2,7 @@ use clap::Parser; use clap::Subcommand; use json_diff::enums::Error; -use json_diff::{ - ds::{key_node::KeyNode, mismatch::Mismatch}, - process::compare_jsons, -}; +use json_diff::{ds::mismatch::Mismatch, process::compare_jsons}; #[derive(Subcommand, Clone)] /// Input selection @@ -49,16 +46,10 @@ fn main() -> Result<(), Error> { } pub fn check_diffs(result: Mismatch) -> Result { - let no_mismatch = Mismatch::empty(); - - if no_mismatch == result { - println!("No mismatch"); - Ok(true) - } else { - let mismatches = result.all_diffs(); - for (d_type, key) in mismatches { - println!("{d_type}: {key}"); - } - Ok(false) + let mismatches = result.all_diffs(); + let is_good = mismatches.is_empty(); + for (d_type, key) in mismatches { + println!("{d_type}: {key}"); } + Ok(is_good) } From 3b60e7c17bedd29eb7bd7645c08a21a4d90bebb4 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Fri, 6 Oct 2023 22:10:36 +0200 Subject: [PATCH 14/23] bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e7f39b8..84c65c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json_diff" -version = "0.2.1" +version = "0.2.0-rc2" authors = ["ksceriath"] edition = "2021" license = "Unlicense" From ff53f6bfbce0bb83bfd858245dba9ea708f9401c Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Fri, 6 Oct 2023 22:22:28 +0200 Subject: [PATCH 15/23] bump lockfile --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 31be554..23bf733 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,7 +110,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "json_diff" -version = "0.2.1" +version = "0.2.0-rc2" dependencies = [ "clap", "maplit", From 055c05a87ecdc66c687f793c4898535b4755ac28 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Mon, 9 Oct 2023 08:59:33 +0200 Subject: [PATCH 16/23] Fork to new package for publishing of new hvc version --- Cargo.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 84c65c7..df32059 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [package] -name = "json_diff" -version = "0.2.0-rc2" -authors = ["ksceriath"] +name = "json_diff_ng" +version = "0.2.0" +authors = ["ksceriath", "ChrisRega"] edition = "2021" license = "Unlicense" -description = "A small diff tool utility for comparing jsons" +description = "A small diff tool utility for comparing jsons. Forked from ksceriath but improved for usage as a library." readme = "README.md" -homepage = "https://github.com/ksceriath/json-diff" -repository = "https://github.com/ksceriath/json-diff" +homepage = "https://github.com/ChrisRega/json-diff" +repository = "https://github.com/ChrisRega/json-diff" keywords = ["cli", "diff", "json"] categories = ["command-line-utilities"] From 8bd74d1cbce87e70a1ef5e2cc842c49b164dd44b Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Mon, 9 Oct 2023 09:03:55 +0200 Subject: [PATCH 17/23] Update gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 53eaa21..bb421d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target **/*.rs.bk +.idea +Cargo.lock From b88550470c05cb79f423838276345ead2f7beef8 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Mon, 9 Oct 2023 09:05:01 +0200 Subject: [PATCH 18/23] Remove Cargo.lock --- Cargo.lock | 305 ----------------------------------------------------- 1 file changed, 305 deletions(-) delete mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 23bf733..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,305 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anstream" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" - -[[package]] -name = "anstyle-parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" -dependencies = [ - "anstyle", - "windows-sys", -] - -[[package]] -name = "clap" -version = "4.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "json_diff" -version = "0.2.0-rc2" -dependencies = [ - "clap", - "maplit", - "serde_json", - "thiserror", - "vg_errortools", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "proc-macro2" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "2.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "vg_errortools" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0d7932688493f8aac7d65e824820b6506fe68ae7450bf44ac7299b1841a4a6" -dependencies = [ - "thiserror", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" From 425d4143d7be8bbc5f003198cdeae341db8dfe9e Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Tue, 10 Oct 2023 23:07:35 +0200 Subject: [PATCH 19/23] Add array support --- Cargo.toml | 2 +- README.md | 4 +- src/ds/key_node.rs | 10 ++++ src/enums.rs | 2 +- src/process.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index df32059..b6f93f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json_diff_ng" -version = "0.2.0" +version = "0.3.0-rc1" authors = ["ksceriath", "ChrisRega"] edition = "2021" license = "Unlicense" diff --git a/README.md b/README.md index 0cb5852..de60bb1 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Only missing or unequal keys are printed in output to reduce the verbosity. Usage Example: -`$ json_diff f source1.json source2.json` -`$ json_diff d '{...}' '{...}'` +`$ json_diff file source1.json source2.json` +`$ json_diff direct '{...}' '{...}'` Option: diff --git a/src/ds/key_node.rs b/src/ds/key_node.rs index 8e004a9..dd07987 100644 --- a/src/ds/key_node.rs +++ b/src/ds/key_node.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; pub enum KeyNode { Nil, Value(Value, Value), + Array(Vec<(usize, KeyNode)>), Node(HashMap), } @@ -62,6 +63,15 @@ impl KeyNode { ) } } + KeyNode::Array(vec) => { + for (idx, value) in vec { + value.absolute_keys( + keys, + Some(format!("[l: {}] {}", idx, val_key(key_from_root.clone()))), + Some(max_display_length), + ) + } + } } } } diff --git a/src/enums.rs b/src/enums.rs index 8deb5c3..da15cc7 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -68,7 +68,7 @@ impl Display for ValueType { key, value_right, } => { - write!(f, "{key} [ {value_left} :: {value_right} ]") + write!(f, "{key} {{ {value_left} != {value_right} }}") } } } diff --git a/src/process.rs b/src/process.rs index c6e86cf..b1100a4 100644 --- a/src/process.rs +++ b/src/process.rs @@ -13,6 +13,17 @@ pub fn compare_jsons(a: &str, b: &str) -> Result { let value2 = serde_json::from_str(b)?; Ok(match_json(&value1, &value2)) } +fn values_to_node(vec: Vec<(usize, &Value)>) -> KeyNode { + if vec.is_empty() { + KeyNode::Nil + } else { + KeyNode::Node( + vec.into_iter() + .map(|(id, val)| (format!("[l: {id}] - {}", val.to_string()), KeyNode::Nil)) + .collect(), + ) + } +} pub fn match_json(value1: &Value, value2: &Value) -> Mismatch { match (value1, value2) { @@ -38,6 +49,52 @@ pub fn match_json(value1: &Value, value2: &Value) -> Mismatch { } Mismatch::new(left_only_keys, right_only_keys, unequal_keys) } + // this clearly needs to be improved! myers algorithm or whatever? + (Value::Array(a), Value::Array(b)) => { + let mut mismatch = Vec::new(); + let mut left_only_values = Vec::new(); + let mut right_only_values = Vec::new(); + + let max_len = a.len().max(b.len()); + for idx in 0..max_len { + let a = a.get(idx); + let b = b.get(idx); + match (a, b) { + (Some(a), Some(b)) => { + if a != b { + let Mismatch { + left_only_keys: l, + right_only_keys: r, + keys_in_both: u, + } = match_json(a, b); + for node in [l, r, u] { + if !matches!(node, KeyNode::Nil) { + mismatch.push((idx, node)); + } + } + } + } + (Some(a), None) => { + left_only_values.push((idx, a)); + } + (None, Some(b)) => { + right_only_values.push((idx, b)); + } + (None, None) => { + unreachable!(); + } + } + } + + let left_only_nodes = values_to_node(left_only_values); + let right_only_nodes = values_to_node(right_only_values); + let mismatch = if mismatch.is_empty() { + KeyNode::Nil + } else { + KeyNode::Array(mismatch) + }; + Mismatch::new(left_only_nodes, right_only_nodes, mismatch) + } (a, b) => { if a == b { Mismatch::new(KeyNode::Nil, KeyNode::Nil, KeyNode::Nil) @@ -132,6 +189,63 @@ mod tests { use maplit::hashmap; use serde_json::json; + #[test] + fn test_arrays_simple_diff() { + let data1 = r#"["a","b","c"]"#; + let data2 = r#"["a","b","d"]"#; + let diff = compare_jsons(data1, data2).unwrap(); + assert_eq!(diff.left_only_keys, KeyNode::Nil); + assert_eq!(diff.right_only_keys, KeyNode::Nil); + let diff = diff.keys_in_both.absolute_keys_to_vec(None); + assert_eq!(diff.len(), 1); + assert_eq!( + diff.first().unwrap().to_string(), + r#"[l: 2] -> { "c" != "d" }"# + ); + } + + #[test] + fn test_arrays_extra_left() { + let data1 = r#"["a","b","c"]"#; + let data2 = r#"["a","b"]"#; + let diff = compare_jsons(data1, data2).unwrap(); + + let diffs = diff.left_only_keys.absolute_keys_to_vec(None); + assert_eq!(diffs.len(), 1); + assert_eq!(diffs.first().unwrap().to_string(), r#" [l: 2] - "c""#); + assert_eq!(diff.keys_in_both, KeyNode::Nil); + assert_eq!(diff.right_only_keys, KeyNode::Nil); + } + + #[test] + fn test_arrays_extra_right() { + let data1 = r#"["a","b"]"#; + let data2 = r#"["a","b","c"]"#; + let diff = compare_jsons(data1, data2).unwrap(); + + let diffs = diff.right_only_keys.absolute_keys_to_vec(None); + assert_eq!(diffs.len(), 1); + assert_eq!(diffs.first().unwrap().to_string(), r#" [l: 2] - "c""#); + assert_eq!(diff.keys_in_both, KeyNode::Nil); + assert_eq!(diff.left_only_keys, KeyNode::Nil); + } + + #[test] + fn test_arrays_object_extra() { + let data1 = r#"["a","b"]"#; + let data2 = r#"["a","b", {"c": {"d": "e"} }]"#; + let diff = compare_jsons(data1, data2).unwrap(); + + let diffs = diff.right_only_keys.absolute_keys_to_vec(None); + assert_eq!(diffs.len(), 1); + assert_eq!( + diffs.first().unwrap().to_string(), + r#" [l: 2] - {"c":{"d":"e"}}"# + ); + assert_eq!(diff.keys_in_both, KeyNode::Nil); + assert_eq!(diff.left_only_keys, KeyNode::Nil); + } + #[test] fn nested_diff() { let data1 = r#"{ From 238ad5bd9a4ea59c747c336e9dbb0684c61e5372 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Sat, 28 Oct 2023 22:45:57 +0200 Subject: [PATCH 20/23] Add myers diff for handling arrays --- Cargo.toml | 5 ++- README.md | 4 -- src/process.rs | 115 ++++++++++++++++++++++++++++++++++--------------- 3 files changed, 84 insertions(+), 40 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b6f93f1..6f1200d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "json_diff_ng" -version = "0.3.0-rc1" +version = "0.3.0" authors = ["ksceriath", "ChrisRega"] edition = "2021" license = "Unlicense" -description = "A small diff tool utility for comparing jsons. Forked from ksceriath but improved for usage as a library." +description = "A small diff tool utility for comparing jsons. Forked from ksceriath and improved for usage as a library and with good support for array diffs." readme = "README.md" homepage = "https://github.com/ChrisRega/json-diff" repository = "https://github.com/ChrisRega/json-diff" @@ -28,3 +28,4 @@ vg_errortools = "0.1" serde_json = "1.0" maplit = "1.0" clap = {version = "4.4", features = ["derive"]} +diffs = "0.5" \ No newline at end of file diff --git a/README.md b/README.md index de60bb1..ab54ce8 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,6 @@ Input can be fed as inline strings or through files. For readability, output is neatly differentiated into three categories: keys with different values, and keys not present in either of the objects. Only missing or unequal keys are printed in output to reduce the verbosity. -## Screenshot of diff results - -[![A screenshot of a sample diff with json_diff](https://github.com/ksceriath/json-diff/blob/master/Screenshot.png)](https://github.com/ksceriath/json-diff/blob/master/Screenshot.png) - Usage Example: `$ json_diff file source1.json source2.json` diff --git a/src/process.rs b/src/process.rs index b1100a4..a83b5d7 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,3 +1,4 @@ +use diffs::{myers, Diff, Replace}; use std::collections::HashMap; use std::collections::HashSet; @@ -25,6 +26,40 @@ fn values_to_node(vec: Vec<(usize, &Value)>) -> KeyNode { } } +struct ListDiffHandler<'a> { + replaced: &'a mut Vec<(usize, usize, usize, usize)>, + deletion: &'a mut Vec<(usize, usize)>, + insertion: &'a mut Vec<(usize, usize)>, +} +impl<'a> ListDiffHandler<'a> { + pub fn new( + replaced: &'a mut Vec<(usize, usize, usize, usize)>, + deletion: &'a mut Vec<(usize, usize)>, + insertion: &'a mut Vec<(usize, usize)>, + ) -> Self { + Self { + replaced, + deletion, + insertion, + } + } +} +impl<'a> Diff for ListDiffHandler<'a> { + type Error = (); + fn delete(&mut self, old: usize, len: usize, _new: usize) -> Result<(), ()> { + self.deletion.push((old, len)); + Ok(()) + } + fn insert(&mut self, _o: usize, new: usize, len: usize) -> Result<(), ()> { + self.insertion.push((new, len)); + Ok(()) + } + fn replace(&mut self, old: usize, len: usize, new: usize, new_len: usize) -> Result<(), ()> { + self.replaced.push((old, len, new, new_len)); + Ok(()) + } +} + pub fn match_json(value1: &Value, value2: &Value) -> Mismatch { match (value1, value2) { (Value::Object(a), Value::Object(b)) => { @@ -51,40 +86,33 @@ pub fn match_json(value1: &Value, value2: &Value) -> Mismatch { } // this clearly needs to be improved! myers algorithm or whatever? (Value::Array(a), Value::Array(b)) => { - let mut mismatch = Vec::new(); - let mut left_only_values = Vec::new(); - let mut right_only_values = Vec::new(); - - let max_len = a.len().max(b.len()); - for idx in 0..max_len { - let a = a.get(idx); - let b = b.get(idx); - match (a, b) { - (Some(a), Some(b)) => { - if a != b { - let Mismatch { - left_only_keys: l, - right_only_keys: r, - keys_in_both: u, - } = match_json(a, b); - for node in [l, r, u] { - if !matches!(node, KeyNode::Nil) { - mismatch.push((idx, node)); - } - } - } - } - (Some(a), None) => { - left_only_values.push((idx, a)); - } - (None, Some(b)) => { - right_only_values.push((idx, b)); - } - (None, None) => { - unreachable!(); - } - } - } + let mut replaced = Vec::new(); + let mut deleted = Vec::new(); + let mut inserted = Vec::new(); + + let mut diff = Replace::new(ListDiffHandler::new( + &mut replaced, + &mut deleted, + &mut inserted, + )); + myers::diff(&mut diff, a, 0, a.len(), b, 0, b.len()).unwrap(); + + let mismatch: Vec<_> = replaced + .into_iter() + .flat_map(|(o, ol, n, _nl)| { + (0..ol).map(move |i| (o + i, match_json(&a[o + i], &b[n + i]).keys_in_both)) + }) + .collect(); + + let left_only_values: Vec<_> = deleted + .into_iter() + .flat_map(|(o, ol)| (o..o + ol).map(|i| (i, &a[i]))) + .collect(); + + let right_only_values: Vec<_> = inserted + .into_iter() + .flat_map(|(n, nl)| (n..n + nl).map(|i| (i, &b[i]))) + .collect(); let left_only_nodes = values_to_node(left_only_values); let right_only_nodes = values_to_node(right_only_values); @@ -204,6 +232,25 @@ mod tests { ); } + #[test] + fn test_arrays_more_complex_diff() { + let data1 = r#"["a","b","c"]"#; + let data2 = r#"["a","a","b","d"]"#; + let diff = compare_jsons(data1, data2).unwrap(); + + let changes_diff = diff.keys_in_both.absolute_keys_to_vec(None); + assert_eq!(diff.left_only_keys, KeyNode::Nil); + + assert_eq!(changes_diff.len(), 1); + assert_eq!( + changes_diff.first().unwrap().to_string(), + r#"[l: 2] -> { "c" != "d" }"# + ); + let insertions = diff.right_only_keys.absolute_keys_to_vec(None); + assert_eq!(insertions.len(), 1); + assert_eq!(insertions.first().unwrap().to_string(), r#" [l: 0] - "a""#); + } + #[test] fn test_arrays_extra_left() { let data1 = r#"["a","b","c"]"#; From 057c0ca7e93440663ace945285437955aa09b609 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Fri, 10 Nov 2023 22:32:09 +0100 Subject: [PATCH 21/23] Fix some problematic case for myers diff --- src/process.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/process.rs b/src/process.rs index a83b5d7..4730be6 100644 --- a/src/process.rs +++ b/src/process.rs @@ -99,8 +99,18 @@ pub fn match_json(value1: &Value, value2: &Value) -> Mismatch { let mismatch: Vec<_> = replaced .into_iter() - .flat_map(|(o, ol, n, _nl)| { - (0..ol).map(move |i| (o + i, match_json(&a[o + i], &b[n + i]).keys_in_both)) + .flat_map(|(o, ol, n, nl)| { + let max_length = ol.max(nl); + (0..max_length).map(move |i| { + ( + o + i, + match_json( + a.get(o + i).unwrap_or(&Value::Null), + b.get(n + i).unwrap_or(&Value::Null), + ) + .keys_in_both, + ) + }) }) .collect(); @@ -277,6 +287,22 @@ mod tests { assert_eq!(diff.left_only_keys, KeyNode::Nil); } + #[test] + fn long_insertion_modification() { + let data1 = r#"["a","b","a"]"#; + let data2 = r#"["a","c","c","c","a"]"#; + let diff = compare_jsons(data1, data2).unwrap(); + let diffs = diff.keys_in_both.absolute_keys_to_vec(None); + // 1. is b!=c, second is a!=c, third is missing in data1 but c in data2 + assert_eq!(diffs.len(), 3); + assert_eq!( + diffs.last().unwrap().to_string(), + r#"[l: 3] -> { null != "c" }"# + ); + assert_eq!(diff.right_only_keys, KeyNode::Nil); + assert_eq!(diff.left_only_keys, KeyNode::Nil); + } + #[test] fn test_arrays_object_extra() { let data1 = r#"["a","b"]"#; From 1d7ea797d6cc5039ded8f87f82de66ce9fffa9c4 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Fri, 10 Nov 2023 22:32:37 +0100 Subject: [PATCH 22/23] Bump version to 0.3.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6f1200d..d76fcfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json_diff_ng" -version = "0.3.0" +version = "0.3.1" authors = ["ksceriath", "ChrisRega"] edition = "2021" license = "Unlicense" From 6ab8672fa44ef872dd211a0ac6baa1f686d50aa3 Mon Sep 17 00:00:00 2001 From: Christopher Regali Date: Fri, 10 Nov 2023 22:33:00 +0100 Subject: [PATCH 23/23] Fixup README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ab54ce8..ec10cbf 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ Usage Example: Option: -f : read input from json files -d : read input from command line +file : read input from json files +direct : read input from command line ### Installation