diff --git a/Cargo.lock b/Cargo.lock index 3fa3cac..aeb47d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,48 +10,38 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] [[package]] name = "anstream" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] @@ -62,24 +52,24 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "assert_cmd" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d6b683edf8d1119fe420a94f8a7e389239666aa72e65495d91c00462510151" +checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" dependencies = [ "anstyle", "bstr", @@ -123,23 +113,28 @@ 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 = "bstr" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", - "once_cell", "regex-automata", "serde", ] [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytemuck" @@ -155,9 +150,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -167,9 +165,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.2.7" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +checksum = "7c8d502cbaec4595d2e7d5f61e318f05417bd2b66fdc3809498f0d3fdf0bea27" dependencies = [ "clap_builder", "clap_derive", @@ -178,34 +176,33 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.7" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +checksum = "5891c7bc0edb3e1c2204fc5e94009affabeb1821c9e5fdc3959536c5c0bb984d" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.15", + "syn", ] [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "color_quant" @@ -251,9 +248,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", @@ -264,9 +261,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] @@ -291,19 +288,19 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -318,15 +315,15 @@ dependencies = [ [[package]] name = "exr" -version = "1.6.3" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd2162b720141a91a054640662d3edce3d50a944a50ffca5313cd951abb35b4" +checksum = "d1e481eb11a482815d3e9d618db8c42a93207134662873809335a92327440c18" dependencies = [ "bit_field", "flume", "half", "lebe", - "miniz_oxide 0.6.2", + "miniz_oxide", "rayon-core", "smallvec", "zune-inflate", @@ -334,12 +331,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "fdeflate" @@ -352,12 +346,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -393,9 +387,9 @@ checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -416,11 +410,11 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr", "fnv", "log", @@ -433,7 +427,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "ignore", "walkdir", ] @@ -455,18 +449,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "ignore" @@ -487,9 +472,9 @@ dependencies = [ [[package]] name = "image" -version = "0.24.6" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", @@ -504,38 +489,6 @@ dependencies = [ "tiff", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "is-terminal" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" -dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys 0.48.0", -] - [[package]] name = "itertools" version = "0.10.5" @@ -556,9 +509,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -569,7 +522,7 @@ version = "0.3.0" dependencies = [ "assert_cmd", "assert_fs", - "bitflags", + "bitflags 1.3.2", "clap", "image", "lazy_static", @@ -590,21 +543,21 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.143" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -612,37 +565,25 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "76fc44e2588d5b436dbc3c6cf62aef290f90dab6235744a93dfe1cc18f451e2c" [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -685,60 +626,60 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "png" -version = "0.17.8" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -777,9 +718,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -795,9 +736,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -860,44 +801,49 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.8.1" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick", "memchr", + "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rustix" -version = "0.37.19" +version = "0.38.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "ed6248e1caa625eb708e266e06159f135e8c26f2bb7ceb72dc4b2766d0340964" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -911,27 +857,41 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.162" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" +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 = "simd-adler32" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "spin" @@ -950,20 +910,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" dependencies = [ "proc-macro2", "quote", @@ -972,15 +921,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", "redox_syscall", "rustix", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1001,9 +950,9 @@ dependencies = [ [[package]] name = "tiff" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471" +checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" dependencies = [ "flate2", "jpeg-decoder", @@ -1012,9 +961,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "utf8parse" @@ -1049,9 +998,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1059,24 +1008,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1084,22 +1033,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "weezl" @@ -1138,137 +1087,71 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "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.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "zune-inflate" diff --git a/README.md b/README.md index af27d57..ca4a4a5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ # Knossos -Knossos is a Rust library and CLI for generating mazes with some basic routines for rendering and saving mazes to files. +Knossos is a Rust library and CLI for maze generation, complete with fundamental functions for rendering and saving mazes to files. ## Reference @@ -36,11 +36,11 @@ The library supports the following generation algorithms: Knossos supports the following output types: -* **ASCII** Using the ASCII output, you can simply print a maze to the console or write it to a file to see what it looks like +* **ASCII** With the ASCII output option, you can effortlessly display a maze on the console or save it to a file to visualize its appearance. -* **Game map** If you're interested in writing your own game with pseudo 3D graphics or just testing your implementation of the ray casting algorithm, you can convert a maze into a game map. Currently, this formatter supports one configuration option: it's a `span` value describing any passage — distance between two opposite walls. +* **Game map** If you are looking to create your own game featuring pseudo 3D graphics or testing your ray casting algorithm implementation, you can transform a maze into a game map using this formatter. It offers various configuration options, including the `span` value for specifying the distance between opposing walls, the characters `wall` and `passage` for map construction, and the ability to randomly place start `S` and goal `G` points along the borders. -* **Image** Using the Image output, you can render a maze to PNG or JPG (just use the corresponding filename extension). This type of output is highly customizable: it allows you to specify custom margin, wall and passage width, and even background and foreground colors +* **Image** Utilizing the Image output feature, you have the capability to render a maze into PNG or JPG formats (simply utilize the appropriate filename extension). This output type offers extensive customization options, enabling you to define custom margins, wall and passage widths, as well as background and foreground colors. ## Installation Run the following Cargo command in your project directory: @@ -109,16 +109,23 @@ cargo +nightly bench Finished bench [optimized] target(s) in 0.51s Running unittests src/lib.rs (target/release/deps/knossos-43150be123983d04) -running 22 tests +running 29 tests +test maze::algorithms::prim::tests::default_call ... ignored test maze::builder::tests::build ... ignored test maze::errors::save_error::tests::display ... ignored test maze::errors::transit_error::tests::display ... ignored -test maze::formatters::ascii::tests::format_narrow ... ignored test maze::formatters::ascii::tests::format_broad ... ignored -test maze::formatters::game_map::tests::format ... ignored -test maze::formatters::game_map::tests::new_call_default_params ... ignored +test maze::formatters::ascii::tests::format_narrow ... ignored +test maze::formatters::game_map::tests::default_call ... ignored +test maze::formatters::game_map::tests::format_with_no_start_and_goal ... ignored +test maze::formatters::game_map::tests::format_with_start_and_goal ... ignored +test maze::formatters::game_map::tests::goal_change ... ignored +test maze::formatters::game_map::tests::new_call ... ignored test maze::formatters::game_map::tests::passage_change ... ignored +test maze::formatters::game_map::tests::possible_start_and_goal_positions ... ignored +test maze::formatters::game_map::tests::possible_start_and_goal_positions_when_map_is_empty ... ignored test maze::formatters::game_map::tests::span_change ... ignored +test maze::formatters::game_map::tests::start_change ... ignored test maze::formatters::game_map::tests::wall_change ... ignored test maze::formatters::image::tests::format ... ignored test maze::formatters::image::tests::new_call_default_params ... ignored @@ -133,60 +140,60 @@ test utils::arena::tests::connect_two_none_node ... ignored test utils::arena::tests::unconnected_nodes ... ignored test utils::color::tests::display_color ... ignored -test result: ok. 0 passed; 0 failed; 22 ignored; 0 measured; 0 filtered out; finished in 0.00s +test result: ok. 0 passed; 0 failed; 29 ignored; 0 measured; 0 filtered out; finished in 0.00s - Running unittests src/main.rs (target/release/deps/knossos-c42e4506ba8fe599) + Running unittests src/main.rs (target/release/deps/knossos-d8bfa62e62b46d44) running 1 test test tests::verify_cli ... ignored test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s - Running benches/algorithms.rs (target/release/deps/algorithms-99993a694f1f462a) + Running benches/algorithms.rs (target/release/deps/algorithms-e8ead48e0698db1d) running 26 tests -test algorithms::aldous_broder::generate_100_x_100 ... bench: 25,114,116 ns/iter (+/- 8,976,086) -test algorithms::aldous_broder::generate_10_x_10 ... bench: 82,836 ns/iter (+/- 7,641) -test algorithms::binary_tree::generate_100_x_100 ... bench: 518,780 ns/iter (+/- 4,661) -test algorithms::binary_tree::generate_10_x_10 ... bench: 5,278 ns/iter (+/- 44) -test algorithms::eller::generate_100_x_100 ... bench: 2,924,531 ns/iter (+/- 1,151,159) -test algorithms::eller::generate_10_x_10 ... bench: 26,874 ns/iter (+/- 922) -test algorithms::growing_tree_method_middle::generate_100_x_100 ... bench: 2,060,609 ns/iter (+/- 46,684) -test algorithms::growing_tree_method_middle::generate_10_x_10 ... bench: 20,162 ns/iter (+/- 154) -test algorithms::growing_tree_method_newest::generate_100_x_100 ... bench: 1,834,971 ns/iter (+/- 18,044) -test algorithms::growing_tree_method_newest::generate_10_x_10 ... bench: 19,742 ns/iter (+/- 5,935) -test algorithms::growing_tree_method_oldest::generate_100_x_100 ... bench: 2,059,533 ns/iter (+/- 118,326) -test algorithms::growing_tree_method_oldest::generate_10_x_10 ... bench: 20,145 ns/iter (+/- 1,032) -test algorithms::growing_tree_method_random::generate_100_x_100 ... bench: 2,553,812 ns/iter (+/- 390,277) -test algorithms::growing_tree_method_random::generate_10_x_10 ... bench: 24,224 ns/iter (+/- 6,544) -test algorithms::hunt_and_kill::generate_100_x_100 ... bench: 1,060,523 ns/iter (+/- 83,817) -test algorithms::hunt_and_kill::generate_10_x_10 ... bench: 9,249 ns/iter (+/- 301) -test algorithms::kruskal::generate_100_x_100 ... bench: 38,615,035 ns/iter (+/- 23,011,185) -test algorithms::kruskal::generate_10_x_10 ... bench: 19,223 ns/iter (+/- 909) -test algorithms::prim::generate_100_x_100 ... bench: 5,987,027 ns/iter (+/- 2,530,387) -test algorithms::prim::generate_10_x_10 ... bench: 21,962 ns/iter (+/- 8,735) -test algorithms::recursive_backtracking::generate_100_x_100 ... bench: 1,199,184 ns/iter (+/- 146,586) -test algorithms::recursive_backtracking::generate_10_x_10 ... bench: 11,472 ns/iter (+/- 2,661) -test algorithms::recursive_division::generate_100_x_100 ... bench: 349,725 ns/iter (+/- 19,278) -test algorithms::recursive_division::generate_10_x_10 ... bench: 3,511 ns/iter (+/- 57) -test algorithms::sidewinder::generate_100_x_100 ... bench: 254,377 ns/iter (+/- 24,068) -test algorithms::sidewinder::generate_10_x_10 ... bench: 2,526 ns/iter (+/- 17) - -test result: ok. 0 passed; 0 failed; 0 ignored; 26 measured; 0 filtered out; finished in 71.73s - - Running benches/formatters.rs (target/release/deps/formatters-1b577342650eb048) +test algorithms::aldous_broder::generate_100_x_100 ... bench: 27,608,666 ns/iter (+/- 9,378,586) +test algorithms::aldous_broder::generate_10_x_10 ... bench: 90,247 ns/iter (+/- 4,901) +test algorithms::binary_tree::generate_100_x_100 ... bench: 518,312 ns/iter (+/- 28,780) +test algorithms::binary_tree::generate_10_x_10 ... bench: 5,126 ns/iter (+/- 318) +test algorithms::eller::generate_100_x_100 ... bench: 2,195,923 ns/iter (+/- 172,412) +test algorithms::eller::generate_10_x_10 ... bench: 22,002 ns/iter (+/- 508) +test algorithms::growing_tree_method_middle::generate_100_x_100 ... bench: 1,942,837 ns/iter (+/- 69,464) +test algorithms::growing_tree_method_middle::generate_10_x_10 ... bench: 18,608 ns/iter (+/- 385) +test algorithms::growing_tree_method_newest::generate_100_x_100 ... bench: 1,721,368 ns/iter (+/- 51,877) +test algorithms::growing_tree_method_newest::generate_10_x_10 ... bench: 17,912 ns/iter (+/- 931) +test algorithms::growing_tree_method_oldest::generate_100_x_100 ... bench: 1,959,410 ns/iter (+/- 106,218) +test algorithms::growing_tree_method_oldest::generate_10_x_10 ... bench: 18,575 ns/iter (+/- 614) +test algorithms::growing_tree_method_random::generate_100_x_100 ... bench: 2,621,709 ns/iter (+/- 146,396) +test algorithms::growing_tree_method_random::generate_10_x_10 ... bench: 22,979 ns/iter (+/- 507) +test algorithms::hunt_and_kill::generate_100_x_100 ... bench: 913,686 ns/iter (+/- 29,865) +test algorithms::hunt_and_kill::generate_10_x_10 ... bench: 8,736 ns/iter (+/- 140) +test algorithms::kruskal::generate_100_x_100 ... bench: 47,468,245 ns/iter (+/- 5,990,785) +test algorithms::kruskal::generate_10_x_10 ... bench: 12,918 ns/iter (+/- 765) +test algorithms::prim::generate_100_x_100 ... bench: 3,038,950 ns/iter (+/- 245,608) +test algorithms::prim::generate_10_x_10 ... bench: 13,750 ns/iter (+/- 667) +test algorithms::recursive_backtracking::generate_100_x_100 ... bench: 1,017,889 ns/iter (+/- 52,493) +test algorithms::recursive_backtracking::generate_10_x_10 ... bench: 10,304 ns/iter (+/- 488) +test algorithms::recursive_division::generate_100_x_100 ... bench: 353,212 ns/iter (+/- 9,616) +test algorithms::recursive_division::generate_10_x_10 ... bench: 3,551 ns/iter (+/- 83) +test algorithms::sidewinder::generate_100_x_100 ... bench: 267,238 ns/iter (+/- 10,063) +test algorithms::sidewinder::generate_10_x_10 ... bench: 2,756 ns/iter (+/- 112) + +test result: ok. 0 passed; 0 failed; 0 ignored; 26 measured; 0 filtered out; finished in 82.88s + + Running benches/formatters.rs (target/release/deps/formatters-a575860cb997bf40) running 8 tests -test formatters::ascii_narrow::format_100_x_100 ... bench: 1,457,895 ns/iter (+/- 6,362) -test formatters::ascii_narrow::format_10_x_10 ... bench: 85,277 ns/iter (+/- 19,651) -test formatters::ascii_broad::format_100_x_100 ... bench: 1,344,412 ns/iter (+/- 5,683) -test formatters::ascii_broad::format_10_x_10 ... bench: 83,734 ns/iter (+/- 1,928) -test formatters::game_map::format_100_x_100 ... bench: 7,905,384 ns/iter (+/- 104,229) -test formatters::game_map::format_10_x_10 ... bench: 149,456 ns/iter (+/- 3,197) -test formatters::image::format_10_x_10 ... bench: 40,956,263 ns/iter (+/- 3,166,280) -test formatters::image::format_50_x_50 ... bench: 864,432,205 ns/iter (+/- 2,515,914) - -test result: ok. 0 passed; 0 failed; 0 ignored; 8 measured; 0 filtered out; finished in 278.25s +test formatters::ascii_broad::format_100_x_100 ... bench: 1,275,793 ns/iter (+/- 56,448) +test formatters::ascii_broad::format_10_x_10 ... bench: 173,265 ns/iter (+/- 18,587) +test formatters::ascii_narrow::format_100_x_100 ... bench: 1,338,637 ns/iter (+/- 103,429) +test formatters::ascii_narrow::format_10_x_10 ... bench: 173,031 ns/iter (+/- 27,930) +test formatters::game_map::format_100_x_100 ... bench: 3,776,375 ns/iter (+/- 243,290) +test formatters::game_map::format_10_x_10 ... bench: 199,187 ns/iter (+/- 20,521) +test formatters::image::format_10_x_10 ... bench: 8,341,370 ns/iter (+/- 349,585) +test formatters::image::format_50_x_50 ... bench: 191,061,562 ns/iter (+/- 2,174,934) + +test result: ok. 0 passed; 0 failed; 0 ignored; 8 measured; 0 filtered out; finished in 77.40s ``` ## CLI @@ -206,26 +213,25 @@ knossos generate -W 5 -H 5 ascii --output-type=broad --output-path=maze.txt + + + + + + | | | +---+---+---+---+---+ - ``` ```bash -knossos generate -W 5 -H 5 game-map --span 2 --output-path=maze.txt -################ -#........#.....# -#........#.....# -#######..#..#..# -#........#..#..# -#........#..#..# -#..#######..#### -#........#.....# -#........#.....# -#######..#..#..# -#.....#..#..#..# -#.....#..#..#..# -#..#..#..####..# +knossos generate -W 5 -H 5 game-map --span 2 --with-start-goal --output-path=maze.txt +#######S######## #..#...........# #..#...........# +#..#..#######..# +#..#........#..# +#..#........#..# +G..##########..# +#..#........#..# +#..#........#..# +#..#..####..#..# +#.....#.....#..# +#.....#.....#..# +#######..####..# +#..............# +#..............# ################ ``` diff --git a/examples/mazes.rs b/examples/mazes.rs index 1011d10..8e6fe85 100644 --- a/examples/mazes.rs +++ b/examples/mazes.rs @@ -137,8 +137,11 @@ fn main() { println!("{}", &maze); maze.save("maze.txt", AsciiBroad).unwrap(); - maze.save("maze_game_map.txt", GameMap::new().span(3)) - .unwrap(); + maze.save( + "maze_game_map.txt", + GameMap::new().span(3).with_start_goal(), + ) + .unwrap(); maze.save("maze.png", Image::new().wall(15).passage(20)) .unwrap(); } diff --git a/src/main.rs b/src/main.rs index 25f4c67..4b0b8e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -110,6 +110,10 @@ enum OutputCommands { /// ASCII character for a wall #[arg(long, default_value_t = '#')] wall: char, + + /// With start "S" and goal "G" points randomly spawned on the borders + #[arg(long, default_value_t = false)] + with_start_goal: bool, }, /// Save to PNG or JPG file Image { @@ -191,11 +195,22 @@ fn main() -> Result<(), maze::MazeSaveError> { span, passage, wall, + with_start_goal, } => { - result = maze.save( - output_path.as_str(), - maze::GameMap::new().span(span).passage(passage).wall(wall), - ); + result = match with_start_goal { + true => maze.save( + output_path.as_str(), + maze::GameMap::new() + .span(span) + .passage(passage) + .wall(wall) + .with_start_goal(), + ), + false => maze.save( + output_path.as_str(), + maze::GameMap::new().span(span).passage(passage).wall(wall), + ), + }; } OutputCommands::Image { output_path, diff --git a/src/maze/algorithms/prim.rs b/src/maze/algorithms/prim.rs index 6c7654a..5a47a2b 100644 --- a/src/maze/algorithms/prim.rs +++ b/src/maze/algorithms/prim.rs @@ -145,3 +145,15 @@ fn direction(x: usize, y: usize, nx: usize, ny: usize) -> Option { unreachable!("The x and y coordinates are never equal to nx and ny") } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn default_call() { + let algo = Prim::default(); + let v: Vec = vec![]; + assert_eq!(v, algo.frontiers); + } +} diff --git a/src/maze/formatters/game_map.rs b/src/maze/formatters/game_map.rs index e53a573..a28cb85 100644 --- a/src/maze/formatters/game_map.rs +++ b/src/maze/formatters/game_map.rs @@ -1,19 +1,36 @@ -use crate::maze::{ - formatters::Formatter, - grid::{Grid, cell::Cell}, +use crate::{ + maze::{ + formatters::Formatter, + grid::{Grid, cell::Cell}, + }, + utils::{types::Coords, rand::RandPositions}, }; use std::fmt::Write; use super::StringWrapper; +pub trait ExtraState {} +pub struct NoStartGoal; +pub struct WithStartGoal { + start: char, + goal: char, +} + +impl ExtraState for NoStartGoal {} +impl ExtraState for WithStartGoal {} + /// A GameMap formatter for a generated maze /// -/// This can be used for generating a game map for pseudo 3D games that use ray casting algorithm -/// for modeling and rendering the map. +/// This formatter is designed for generating game maps suitable for pseudo-3D games utilizing the ray-casting +/// algorithm for map modeling and rendering. +/// +/// By default, it generates a self-contained map without predefined start and exit points. However, it also offers +/// the option to randomly place the start and goal points along the map borders, ensuring a viable path between the +/// two points. /// -/// # Example: +/// # Examples: /// -/// The span value is 2. +/// A standard map with a span set to 2, and no designated start or goal characters. /// ```no_test /// ############# /// #........#..# @@ -29,62 +46,174 @@ use super::StringWrapper; /// #...........# /// ############# /// ``` -pub struct GameMap { +/// +/// An alternative map with a span value of 1 and randomly placed start and goal characters. +/// ```no_test +/// ####### +/// S...#.# +/// ###.#.# +/// #...#.# +/// #.###.# +/// #.....G +/// ####### +/// ``` +pub struct GameMap { + state: Box, + extra: S, +} + +struct GameMapState { span: usize, wall: char, passage: char, } -impl GameMap { - /// Returns a new instance of an [GameMap] formatter with a default settings - pub fn new() -> GameMap { +/// An implementation of a formatter without predefined start and exit points +impl GameMap { + /// Returns a new instance of a [GameMap] formatter with a default settings + pub fn new() -> GameMap { + GameMap { + state: Box::new(GameMapState { + span: 2, + wall: '#', + passage: '.', + }), + extra: NoStartGoal, + } + } + + /// Returns a new instance of a [GameMap] formatter of a new type with an option to randonly spawn the start and goal characters on the borders of a map + pub fn with_start_goal(self) -> GameMap { GameMap { - span: 2, - wall: '#', - passage: '.', + state: self.state, + extra: WithStartGoal { + start: 'S', + goal: 'G', + }, } } /// Sets a span (a distance between two walls) and returns itself pub fn span(mut self, span: usize) -> Self { - self.span = span; + self.state.span = span; self } /// Sets a wall and returns itself pub fn wall(mut self, wall: char) -> Self { - self.wall = wall; + self.state.wall = wall; self } /// Sets a passage and returns itself pub fn passage(mut self, passage: char) -> Self { - self.passage = passage; + self.state.passage = passage; + self + } +} + +/// An implementation of a formatter with the predefined start and goal points randomly placed along the map borders +impl GameMap { + /// Sets a goal charachter and returns itself + pub fn goal(mut self, goal: char) -> Self { + self.extra.goal = goal; + self + } + + /// Sets a start charachter and returns itself + pub fn start(mut self, start: char) -> Self { + self.extra.start = start; self } + + fn get_random_start_and_goal_positions( + &self, + map: &Vec, + cols: usize, + rows: usize, + ) -> (usize, usize) { + let mut positions: Vec = self + .iter_possible_start_and_goal_positions(&map, cols, rows) + .collect(); + + // shuffle possible positions + RandPositions::rand(&mut positions); + + let (srow, scol) = positions[0]; + + let (grow, gcol) = positions + .iter() + .filter(|(nrow, ncol)| *ncol != scol && *nrow != srow) + .nth(0) + .unwrap(); // the smallest grid with a single cell formatted into a map has 3 available positions for a goal + + let start_idx = srow * rows + scol; + let goal_idx = grow * rows + gcol; + (start_idx, goal_idx) + } + + fn iter_possible_start_and_goal_positions( + &self, + map: &Vec, + cols: usize, + rows: usize, + ) -> impl Iterator { + let mut coords = Vec::new(); + + if map.is_empty() { + return coords.into_iter(); + } + + for row in 0..rows { + for col in 0..cols { + if !(row == 0 || row == rows - 1 || col == 0 || col == cols - 1) { + continue; + } + + let adjacent_passages_count = iter_neighbors((row, col), cols, rows) + .filter(move |(ny, nx)| map[ny * rows + nx] == self.state.passage) + .count(); + + if adjacent_passages_count == 0 { + continue; + } + + coords.push((row, col)); + } + } + + coords.into_iter() + } } -impl Default for GameMap { +impl Default for GameMap { fn default() -> Self { Self::new() } } /// An implementation of a formatter -impl Formatter for GameMap { +impl Formatter for GameMap { /// Converts a given grid into the map characters and returns an [StringWrapper] over that image fn format(&self, grid: &Grid) -> StringWrapper { - let mut map = String::new(); + let mut map = vec![]; // Span (width of a passage) + 1 (place for a wall) - let span = self.span + 1; + let span = self.state.span + 1; + + let map_rows = grid.height() * span + 1; + let map_cols = grid.width() * span + 1; - add_horizontal_border(&mut map, grid.width(), span, self.wall); + // Add the north wall + for _ in 0..map_cols { + map.push(self.state.wall); + } - for y in 0..grid.height() * span { - add_wall(&mut map, self.wall); + for y in 0..map_rows - 1 { + // Add the west wall + map.push(self.state.wall); - for x in 0..grid.width() * span { + for x in 0..map_cols - 1 { // X coordinate of a cell in the grid let cx = (x as f64 / span as f64).floor() as usize; // Y coordinate of a cell in the grid @@ -96,19 +225,19 @@ impl Formatter for GameMap { let is_last_col = (x as f64 + 1.0) / span as f64 == cx as f64 + 1.0; match (is_last_row, is_last_col) { - (false, false) => add_passage(&mut map, self.passage), + (false, false) => map.push(self.state.passage), (false, true) => { if grid.is_carved((cx, cy), Cell::EAST) { - add_passage(&mut map, self.passage); + map.push(self.state.passage); } else { - add_wall(&mut map, self.wall); + map.push(self.state.wall); } } (true, false) => { if grid.is_carved((cx, cy), Cell::SOUTH) { - add_passage(&mut map, self.passage); + map.push(self.state.passage); } else { - add_wall(&mut map, self.wall); + map.push(self.state.wall); } } (true, true) => { @@ -116,41 +245,95 @@ impl Formatter for GameMap { && grid.is_carved((cx, cy), Cell::SOUTH) && bottom_right_neighbour_exists(cx, cy, grid) { - add_passage(&mut map, self.passage); + map.push(self.state.passage); } else { - add_wall(&mut map, self.wall); + map.push(self.state.wall); } } } } - - move_to_next_line(&mut map); } - StringWrapper(map) + // Write map to string + let string_map = write_map(&map, map_cols); + + StringWrapper(string_map) } } -fn add_horizontal_border(map: &mut String, width: usize, span: usize, ch: char) { - let mut horizontal_border = String::new(); - let border_len = width * span + 1; - for _ in 0..border_len { - horizontal_border.push(ch); - } +/// An implementation of a formatter +impl Formatter for GameMap { + /// Converts a given grid into the map characters and returns an [StringWrapper] over that image + fn format(&self, grid: &Grid) -> StringWrapper { + let mut map = vec![]; - writeln!(map, "{}", horizontal_border).unwrap(); -} + // Span (width of a passage) + 1 (place for a wall) + let span = self.state.span + 1; -fn add_passage(map: &mut String, ch: char) { - write!(map, "{}", ch).unwrap(); -} + let map_rows = grid.height() * span + 1; + let map_cols = grid.width() * span + 1; -fn add_wall(map: &mut String, ch: char) { - write!(map, "{}", ch).unwrap(); -} + // Add the north wall + for _ in 0..map_cols { + map.push(self.state.wall); + } + + for y in 0..map_rows - 1 { + // Add the west wall + map.push(self.state.wall); + + for x in 0..map_cols - 1 { + // X coordinate of a cell in the grid + let cx = (x as f64 / span as f64).floor() as usize; + // Y coordinate of a cell in the grid + let cy = (y as f64 / span as f64).floor() as usize; + + // Indicates if a row is a last row of a grid cell + let is_last_row = (y as f64 + 1.0) / span as f64 == cy as f64 + 1.0; + // Indicates if a column is a last column of a grid cell + let is_last_col = (x as f64 + 1.0) / span as f64 == cx as f64 + 1.0; + + match (is_last_row, is_last_col) { + (false, false) => map.push(self.state.passage), + (false, true) => { + if grid.is_carved((cx, cy), Cell::EAST) { + map.push(self.state.passage); + } else { + map.push(self.state.wall); + } + } + (true, false) => { + if grid.is_carved((cx, cy), Cell::SOUTH) { + map.push(self.state.passage); + } else { + map.push(self.state.wall); + } + } + (true, true) => { + if grid.is_carved((cx, cy), Cell::EAST) + && grid.is_carved((cx, cy), Cell::SOUTH) + && bottom_right_neighbour_exists(cx, cy, grid) + { + map.push(self.state.passage); + } else { + map.push(self.state.wall); + } + } + } + } + } + + // Get random start and goal points + let (start_idx, goal_idx) = + self.get_random_start_and_goal_positions(&map, map_cols, map_rows); + map[start_idx] = self.extra.start; + map[goal_idx] = self.extra.goal; + + // Write map to string + let string_map = write_map(&map, map_cols); -fn move_to_next_line(map: &mut String) { - writeln!(map).unwrap(); + StringWrapper(string_map) + } } fn bottom_right_neighbour_exists(cx: usize, cy: usize, grid: &Grid) -> bool { @@ -161,36 +344,122 @@ fn bottom_right_neighbour_exists(cx: usize, cy: usize, grid: &Grid) -> bool { grid.is_carved((cx + 1, cy + 1), Cell::WEST) && grid.is_carved((cx + 1, cy + 1), Cell::NORTH) } +fn write_map(map: &Vec, cols: usize) -> String { + let mut ascii_map: String = String::new(); + for i in 0..map.len() { + write!(ascii_map, "{}", map[i]).unwrap(); + if (i + 1) % cols == 0 { + writeln!(ascii_map).unwrap(); + } + } + ascii_map +} + +fn iter_neighbors((row, col): Coords, cols: usize, rows: usize) -> impl Iterator { + let mut adjacent_coords = Vec::new(); + + if row > 0 { + adjacent_coords.push((row - 1, col)); + } + if row < rows - 1 { + adjacent_coords.push((row + 1, col)); + } + if col > 0 { + adjacent_coords.push((row, col - 1)); + } + if col < cols - 1 { + adjacent_coords.push((row, col + 1)); + } + + adjacent_coords.into_iter() +} + #[cfg(test)] mod tests { use super::*; #[test] - fn new_call_default_params() { + fn new_call() { let formatter = GameMap::new(); - assert_eq!(2, formatter.span); + assert_eq!(2, formatter.state.span); + assert_eq!('#', formatter.state.wall); + assert_eq!('.', formatter.state.passage); + } + + #[test] + fn default_call() { + let formatter = GameMap::default(); + assert_eq!(2, formatter.state.span); + assert_eq!('#', formatter.state.wall); + assert_eq!('.', formatter.state.passage); } #[test] fn span_change() { let formatter = GameMap::new().span(10); - assert_eq!(10, formatter.span); + assert_eq!(10, formatter.state.span); } #[test] fn wall_change() { let formatter = GameMap::new().wall('#'); - assert_eq!('#', formatter.wall); + assert_eq!('#', formatter.state.wall); } #[test] fn passage_change() { let formatter = GameMap::new().passage('.'); - assert_eq!('.', formatter.passage); + assert_eq!('.', formatter.state.passage); + } + + #[test] + fn goal_change() { + let formatter = GameMap::new().with_start_goal().goal('2'); + assert_eq!('2', formatter.extra.goal); + } + + #[test] + fn start_change() { + let formatter = GameMap::new().with_start_goal().start('1'); + assert_eq!('1', formatter.extra.start); + } + + #[test] + fn possible_start_and_goal_positions() { + let formatter = GameMap::new().with_start_goal(); + let map = vec![ + '#', '#', '#', '#', '#', '#', '#', '#', '#', + '#', '.', '.', '.', '#', '.', '.', '.', '#', + '#', '#', '#', '.', '#', '.', '#', '.', '#', + '#', '.', '.', '.', '#', '.', '#', '.', '#', + '#', '.', '#', '#', '#', '.', '#', '.', '#', + '#', '.', '.', '.', '.', '.', '#', '.', '#', + '#', '#', '#', '#', '#', '#', '#', '.', '#', + '#', '.', '.', '.', '.', '.', '.', '.', '#', + '#', '#', '#', '#', '#', '#', '#', '#', '#', + ]; + let positions = vec![ + (0, 1), (0, 2), (0, 3), (0, 5), (0, 6), + (0, 7), (1, 0), (1, 8), (2, 8), (3, 0), + (3, 8), (4, 0), (4, 8), (5, 0), (5, 8), + (6, 8), (7, 0), (7, 8), (8, 1), (8, 2), + (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), + ]; + let result = formatter.iter_possible_start_and_goal_positions(&map, 9, 9); + assert_eq!(positions, result.collect::>()); + } + + #[test] + fn possible_start_and_goal_positions_when_map_is_empty() { + let formatter = GameMap::new().with_start_goal(); + let map = vec![]; + let positions: Vec = vec![]; + let result = formatter.iter_possible_start_and_goal_positions(&map, 0, 0); + assert_eq!(positions, result.collect::>()); } #[test] - fn format() { + fn format_with_no_start_and_goal() { let mut expected = String::new(); expected.push_str("#########\n"); expected.push_str("#.#.....#\n"); @@ -202,11 +471,27 @@ mod tests { expected.push_str("#.......#\n"); expected.push_str("#########\n"); - let formatter = GameMap { - span: 1, - passage: '.', - wall: '#', - }; + let formatter = GameMap::new().span(1); + let mut grid = generate_maze(); + let actual = formatter.format(&mut grid).0; + + assert_eq!(actual, expected); + } + + #[test] + fn format_with_start_and_goal() { + let mut expected = String::new(); + expected.push_str("#S#######\n"); + expected.push_str("G.#.....#\n"); + expected.push_str("#.#####.#\n"); + expected.push_str("#.....#.#\n"); + expected.push_str("###.###.#\n"); + expected.push_str("#.......#\n"); + expected.push_str("#.#######\n"); + expected.push_str("#.......#\n"); + expected.push_str("#########\n"); + + let formatter = GameMap::new().span(1).with_start_goal(); let mut grid = generate_maze(); let actual = formatter.format(&mut grid).0; diff --git a/src/maze/grid/mod.rs b/src/maze/grid/mod.rs index 288f86d..35aa753 100644 --- a/src/maze/grid/mod.rs +++ b/src/maze/grid/mod.rs @@ -50,11 +50,6 @@ impl Grid { self.cell_statuses[y * self.width + x] } - pub fn get_cell(&self, coords: Coords) -> &Cell { - let (x, y) = coords; - &self.cells[y * self.width + x] - } - pub fn is_carved(&self, coords: Coords, direction: Cell) -> bool { let (x, y) = coords; self.cells[y * self.width + x].contains(direction) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6886715..cf2766c 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ pub mod types; pub mod arena; pub mod color; +pub mod rand; diff --git a/src/utils/rand.rs b/src/utils/rand.rs new file mode 100644 index 0000000..e80543d --- /dev/null +++ b/src/utils/rand.rs @@ -0,0 +1,20 @@ +use super::types::Coords; + +pub struct RandPositions; + +impl RandPositions { + #[cfg(not(test))] + #[cfg(not(tarpaulin_include))] + pub fn rand<'a>(positions: &'a mut Vec) -> &'a mut Vec { + use rand::seq::SliceRandom; + let mut rng = rand::thread_rng(); + positions.shuffle(&mut rng); + positions + } + + #[cfg(test)] + #[cfg(not(tarpaulin_include))] + pub fn rand<'a>(positions: &'a mut Vec) -> &'a mut Vec { + positions + } +} diff --git a/tests/help.rs b/tests/help.rs index 968ceca..41c9993 100644 --- a/tests/help.rs +++ b/tests/help.rs @@ -43,14 +43,10 @@ const GENERATE_LONG_HELP_STR: &str = "Generates a maze Usage: knossos generate [OPTIONS] Commands: - ascii - Save to a text file with an ASCII representation of a maze - game-map - Save to a text file as an ASCII game map for pseudo 3D games that use ray casting for modeling and rendering the map - image - Save to PNG or JPG file - help - Print this message or the help of the given subcommand(s) + ascii Save to a text file with an ASCII representation of a maze + game-map Save to a text file as an ASCII game map for pseudo 3D games that use ray casting for modeling and rendering the map + image Save to PNG or JPG file + help Print this message or the help of the given subcommand(s) Options: -A, --algorithm @@ -86,20 +82,13 @@ Options: [default: newest] Possible values: - - newest: - Selects the most recently added cell, thus imitating the recurive backtracker - - oldest: - Selects the oldest added cell, thus generating an unchallenging maze with lots of long corridors - - random: - Selects cells at random, thus getting Prim's algorithm behaviour - - middle: - Selects a middle cell from the list of already added, but produces mazes similar to the ones created by the [Oldest](Method::Oldest) method - - newest50-random50: - A combination of the [Newest](Method::Newest) and [Random](Method::Random) methods with 50/50 split - - newest75-random25: - A combination of the [Newest](Method::Newest) and [Random](Method::Random) methods with 75/25 split - - newest25-random75: - A combination of the [Newest](Method::Newest) and [Random](Method::Random) methods with 25/75 split + - newest: Selects the most recently added cell, thus imitating the recurive backtracker + - oldest: Selects the oldest added cell, thus generating an unchallenging maze with lots of long corridors + - random: Selects cells at random, thus getting Prim's algorithm behaviour + - middle: Selects a middle cell from the list of already added, but produces mazes similar to the ones created by the [Oldest](Method::Oldest) method + - newest50-random50: A combination of the [Newest](Method::Newest) and [Random](Method::Random) methods with 50/50 split + - newest75-random25: A combination of the [Newest](Method::Newest) and [Random](Method::Random) methods with 75/25 split + - newest25-random75: A combination of the [Newest](Method::Newest) and [Random](Method::Random) methods with 25/75 split -h, --help Print help (see a summary with '-h') @@ -138,6 +127,7 @@ Options: --span Distance between any two walls [default: 3] --passage ASCII character for a passage [default: .] --wall ASCII character for a wall [default: #] + --with-start-goal With start \"S\" and goal \"G\" points randomly spawned on the borders -h, --help Print help ";