From 66d3ab4221cde7bb68cd2abc1968e6cc68093b84 Mon Sep 17 00:00:00 2001 From: xzeldon Date: Sun, 23 Jan 2022 03:50:33 +0300 Subject: [PATCH] refactor: refactoring code, separate crates preparing to create a GUI --- .gitignore | 2 +- Cargo.lock | 196 ++++++--------- Cargo.toml | 29 +-- README.md | 5 +- cli/Cargo.lock | 357 +++++++++++++++++++++++++++ cli/Cargo.toml | 25 ++ {build => cli/build}/assets/icon.ico | Bin {build => cli/build}/assets/icon.rc | 0 {build => cli/build}/build.rs | 0 cli/src/lib.rs | 152 ++++++++++++ {src => cli/src}/main.rs | 10 +- core/Cargo.toml | 11 + core/README.md | 3 + core/src/buffer.rs | 46 ++++ core/src/console.rs | 71 ++++++ core/src/files.rs | 26 ++ core/src/lib.rs | 4 + core/src/meta.rs | 57 +++++ gui/Cargo.toml | 8 + gui/README.md | 3 + gui/src/main.rs | 3 + src/buffertrim.rs | 10 - src/console.rs | 69 ------ src/lib.rs | 205 --------------- 24 files changed, 861 insertions(+), 431 deletions(-) create mode 100644 cli/Cargo.lock create mode 100644 cli/Cargo.toml rename {build => cli/build}/assets/icon.ico (100%) rename {build => cli/build}/assets/icon.rc (100%) rename {build => cli/build}/build.rs (100%) create mode 100644 cli/src/lib.rs rename {src => cli/src}/main.rs (73%) create mode 100644 core/Cargo.toml create mode 100644 core/README.md create mode 100644 core/src/buffer.rs create mode 100644 core/src/console.rs create mode 100644 core/src/files.rs create mode 100644 core/src/lib.rs create mode 100644 core/src/meta.rs create mode 100644 gui/Cargo.toml create mode 100644 gui/README.md create mode 100644 gui/src/main.rs delete mode 100644 src/buffertrim.rs delete mode 100644 src/console.rs delete mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..eb5a316 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -/target +target diff --git a/Cargo.lock b/Cargo.lock index b72800a..f42dccd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,18 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "atty" version = "0.2.14" @@ -31,34 +19,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "blake2b_simd" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cc" -version = "1.0.67" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -66,6 +37,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cli" +version = "1.1.0" +dependencies = [ + "colored", + "core", + "ctrlc", + "dirs", + "embed-resource", + "serde", + "serde_json", + "winapi", +] + [[package]] name = "colored" version = "2.0.0" @@ -78,27 +63,19 @@ dependencies = [ ] [[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "crossbeam-utils" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +name = "core" +version = "0.1.0" dependencies = [ - "autocfg", - "cfg-if", - "lazy_static", + "ctrlc", + "serde", + "winapi", ] [[package]] name = "ctrlc" -version = "3.1.9" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "232295399409a8b7ae41276757b5a1cc21032848d42bff2352261f958b3ca29a" +checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf" dependencies = [ "nix", "winapi", @@ -106,18 +83,18 @@ dependencies = [ [[package]] name = "dirs" -version = "3.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", "redox_users", @@ -126,9 +103,9 @@ dependencies = [ [[package]] name = "embed-resource" -version = "1.6.1" +version = "1.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e03c3dae04b8f252f2866d25e0ec8f2f488efba43bc6e307274b65c4321f94" +checksum = "85505eb239fc952b300f29f0556d2d884082a83566768d980278d8faf38c780d" dependencies = [ "cc", "vswhom", @@ -137,29 +114,33 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" dependencies = [ "cfg-if", "libc", "wasi", ] +[[package]] +name = "gui" +version = "0.1.0" + [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[package]] name = "itoa" -version = "0.4.7" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "lazy_static" @@ -169,102 +150,89 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.93" +version = "0.2.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" +checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] [[package]] name = "nix" -version = "0.20.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", "cfg-if", "libc", + "memoffset", ] [[package]] name = "proc-macro2" -version = "1.0.26" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] -[[package]] -name = "rdr2_screenshot_converter" -version = "1.0.0" -dependencies = [ - "colored", - "ctrlc", - "dirs", - "embed-resource", - "serde", - "serde_json", - "winapi", -] - [[package]] name = "redox_syscall" -version = "0.1.57" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] [[package]] name = "redox_users" -version = "0.3.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom", "redox_syscall", - "rust-argon2", -] - -[[package]] -name = "rust-argon2" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" -dependencies = [ - "base64", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", ] [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "serde" -version = "1.0.125" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +checksum = "2cf9235533494ea2ddcdb794665461814781c53f19d87b76e571a1c35acbad2b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.125" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +checksum = "8dcde03d87d4c973c04be249e7d8f0b35db1c848c487bd43032808e59dd8328d" dependencies = [ "proc-macro2", "quote", @@ -273,9 +241,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" dependencies = [ "itoa", "ryu", @@ -284,9 +252,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -295,9 +263,9 @@ dependencies = [ [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "vswhom" @@ -321,9 +289,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "winapi" @@ -349,9 +317,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winreg" -version = "0.8.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d107f8c6e916235c4c01cabb3e8acf7bea8ef6a63ca2e7fa0527c049badfc48c" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 1184c3d..52ec54d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,24 +1,7 @@ -[package] -name = "rdr2_screenshot_converter" -version = "1.0.0" -authors = ["Timofey Gelazoniya "] -description = "Convert and save screenshots from rdr2 photo mode to JPEG format" -readme = "README.md" -keywords = ["rdr2", "screenshot", "screenshots", "convert", "jpeg"] -license = "MIT" -edition = "2018" -build = "build/build.rs" +[workspace] -[dependencies] -dirs = "3.0.1" -colored = "2.0.0" -serde = { version = "1.0", features = ["derive"] } -ctrlc = { version = "3.0", features = ["termination"] } -serde_json = "1.0" - -[target.'cfg(target_os="windows")'.dependencies.winapi] -version = "0.3" -features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"] - -[build-dependencies] -embed-resource = "1.6" \ No newline at end of file +members = [ + "cli", + "core", + "gui", +] diff --git a/README.md b/README.md index dd81619..d374cba 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Just [download](https://github.com/xzeldon/rdr2_screenshot_converter/releases/do ## Arguments You can define a path for saving screenshots. To do this, open a command prompt, specify the path to the executable file and the path to save the screenshots. ``` -rdr2_screenshot_converter.exe C:\screenshots +cli.exe C:\screenshots ``` This command will save screenshots to ```C:\screenshots``` @@ -20,6 +20,5 @@ All instructions tested on Windows 10 Pro for workstations 19042.928. You need: * [Rust](https://www.rust-lang.org) ``` -rustup override set nightly -cargo build --release +cargo build --release --bin cli ``` diff --git a/cli/Cargo.lock b/cli/Cargo.lock new file mode 100644 index 0000000..b72800a --- /dev/null +++ b/cli/Cargo.lock @@ -0,0 +1,357 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "crossbeam-utils" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "ctrlc" +version = "3.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "232295399409a8b7ae41276757b5a1cc21032848d42bff2352261f958b3ca29a" +dependencies = [ + "nix", + "winapi", +] + +[[package]] +name = "dirs" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "embed-resource" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e03c3dae04b8f252f2866d25e0ec8f2f488efba43bc6e307274b65c4321f94" +dependencies = [ + "cc", + "vswhom", + "winreg", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + +[[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.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" + +[[package]] +name = "nix" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", +] + +[[package]] +name = "proc-macro2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rdr2_screenshot_converter" +version = "1.0.0" +dependencies = [ + "colored", + "ctrlc", + "dirs", + "embed-resource", + "serde", + "serde_json", + "winapi", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom", + "redox_syscall", + "rust-argon2", +] + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "serde" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f5402d3d0e79a069714f7b48e3ecc60be7775a2c049cb839457457a239532" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "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" + +[[package]] +name = "winreg" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d107f8c6e916235c4c01cabb3e8acf7bea8ef6a63ca2e7fa0527c049badfc48c" +dependencies = [ + "winapi", +] diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 0000000..0dd49ce --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,25 @@ +[package] +authors = ["Timofey Gelazoniya "] +build = "build/build.rs" +description = "Convert and save screenshots from rdr2 photo mode to JPEG format" +edition = "2021" +keywords = ["rdr2", "screenshot", "screenshots", "convert", "jpeg"] +license = "MIT" +name = "cli" +readme = "README.md" +version = "1.1.0" + +[dependencies] +colored = "2.0.0" +core = {path = "../core"} +ctrlc = {version = "3.0", features = ["termination"]} +dirs = "4.0.0" +serde = {version = "1.0", features = ["derive"]} +serde_json = "1.0" + +[target.'cfg(target_os="windows")'.dependencies.winapi] +features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"] +version = "0.3" + +[build-dependencies] +embed-resource = "1.6" diff --git a/build/assets/icon.ico b/cli/build/assets/icon.ico similarity index 100% rename from build/assets/icon.ico rename to cli/build/assets/icon.ico diff --git a/build/assets/icon.rc b/cli/build/assets/icon.rc similarity index 100% rename from build/assets/icon.rc rename to cli/build/assets/icon.rc diff --git a/build/build.rs b/cli/build/build.rs similarity index 100% rename from build/build.rs rename to cli/build/build.rs diff --git a/cli/src/lib.rs b/cli/src/lib.rs new file mode 100644 index 0000000..d432886 --- /dev/null +++ b/cli/src/lib.rs @@ -0,0 +1,152 @@ +use colored::*; +use dirs; +use std::{ + fs, io, + path::{Path, PathBuf}, +}; + +use core::files; +use core::{buffer, meta::ImageMetadata}; + +struct Image { + metadata: ImageMetadata, + image_data: Vec, +} + +fn convert_file(path: PathBuf) -> Result { + let file = buffer::read_file(&path).unwrap(); + let buf = buffer::trim(&file); + + let image_data = buffer::parse_buf(&buf, b"JPEG", b"JSON", 12); + let metadata = buffer::parse_buf(&buf, b"JSON", b"TITL", 8); + let parsed_metadata: ImageMetadata = serde_json::from_slice(&metadata).unwrap(); + + Ok(Image { + metadata: parsed_metadata, + image_data, + }) +} + +pub fn run(config: Config) -> Result<(), String> { + let mut profiles = Vec::new(); + let paths = fs::read_dir(config.profile_path).unwrap(); + + for path in paths { + profiles.push(path.unwrap().path()); + } + + if profiles.len() <= 0 { + return Err(format!( + "{}: {} {} \n{}", + "> Error".red().bold(), + "Profile folder not found.".white(), + "You must run the game at least once!".white().bold(), + "> Aborting.".red() + )); + } + + let scrns = files::collect(&profiles).unwrap(); + + if scrns.len() <= 0 { + return Err(format!( + "{}: {} \n{}", + "> Error".red().bold(), + "Screenshot files not found".white(), + "> Aborting.".red() + )); + } + + println!( + "{} {} {} \n{}", + ">".green(), + scrns.len().to_string().green(), + "Screenshots found.".green(), + "> Converting...".green().bold() + ); + + let mut images = Vec::new(); + + for file in &scrns { + let image = convert_file(file.to_path_buf()).unwrap(); + images.push(image); + } + + for image in &images { + match fs::write( + Path::new(&config.export_path).join(image.metadata.uid.to_string() + ".jpg"), + &image.image_data, + ) { + Ok(ok) => ok, + Err(_err) => { + return Err(format!( + "{}: {} \n{}", + "> Error".red().bold(), + "System cannot find or create the specified path", + "> Aborting.".red() + )) + } + } + } + + println!("{}", "> Converting completed!".green()); + println!( + "{} {}", + "> Files saved to".green().bold(), + Path::new(&config.export_path) + .to_string_lossy() + .bright_blue() + ); + + println!("{}", "> Removing old files...".green()); + for path in scrns { + let _remove = fs::remove_file(path).unwrap(); + } + + Ok(()) +} + +pub struct Config { + pub profile_path: PathBuf, + pub export_path: PathBuf, +} + +impl Config { + pub fn new() -> Result { + let home_dir = dirs::home_dir().unwrap(); + let profile_path = Path::new(&home_dir) + .join("Documents") + .join("Rockstar Games") + .join("Red Dead Redemption 2") + .join("Profiles"); + let export_path = Path::new(&home_dir) + .join("Documents") + .join("Rockstar Games") + .join("Red Dead Redemption 2") + .join("Screenshots"); + + let _create_dirs = fs::create_dir_all(&export_path); + + Ok(Config { + profile_path, + export_path, + }) + } + + pub fn set_custom_export_path<'a>( + &'a mut self, + path: &[String], + ) -> Result<&'a mut Config, String> { + if path.len() < 2 { + return Err(format!("{}", "Not enough arguments")); + } + + let path = path[1].clone(); + let custom_export_path = Path::new(&path).to_path_buf(); + // TODO: Folders containing Cyrillic characters and spaces are created incorrectly i. e. anything after a space is ignored + // let _create_dirs = fs::create_dir_all(&custom_export_path); + + self.export_path = custom_export_path; + + Ok(self) + } +} diff --git a/src/main.rs b/cli/src/main.rs similarity index 73% rename from src/main.rs rename to cli/src/main.rs index 4f77bc8..ef87e40 100644 --- a/src/main.rs +++ b/cli/src/main.rs @@ -1,7 +1,5 @@ -mod buffertrim; -mod console; - -use rdr2_screenshot_converter::Config; +use cli::Config; +use core::console; use std::env; fn main() { @@ -15,9 +13,9 @@ fn main() { let _ansi_support = console::enable_ansi_support(); - if let Err(e) = rdr2_screenshot_converter::run(config) { + if let Err(e) = cli::run(config) { eprintln!("{}", e); } let _ctrl_c_handler = console::set_ctrl_c_handler(); -} \ No newline at end of file +} diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 0000000..4fb863a --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,11 @@ +[package] +edition = "2021" +name = "core" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ctrlc = "3.2.1" +serde = {version = "1.0.135", features = ["derive"]} +winapi = {version = "0.3.9", features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"]} diff --git a/core/README.md b/core/README.md new file mode 100644 index 0000000..b5bfc03 --- /dev/null +++ b/core/README.md @@ -0,0 +1,3 @@ +# Core + +A library that provides functionality such as working with buffers, files, and so on. \ No newline at end of file diff --git a/core/src/buffer.rs b/core/src/buffer.rs new file mode 100644 index 0000000..f801353 --- /dev/null +++ b/core/src/buffer.rs @@ -0,0 +1,46 @@ +use std::fs::File; +use std::io; +use std::io::Read; +use std::path::PathBuf; + +pub fn is_not_empty(e: &u8) -> bool { + *e != 0x00 +} + +pub fn trim(buffer: &Vec) -> Vec { + let begin = buffer.iter().position(is_not_empty); + let end = buffer + .iter() + .rev() + .position(is_not_empty) + .map(|j| buffer.len() - j); + let vec = begin + .and_then(|i| end.map(|j| buffer[i..j].iter().cloned().collect())) + .unwrap_or(Vec::new()); + vec +} + +pub fn read_file(path: &PathBuf) -> Result, io::Error> { + let mut data = Vec::new(); + File::open(path)?.read_to_end(&mut data)?; + return Ok(data); +} + +pub fn find_index(buffer: &Vec, index: &[u8]) -> usize { + let index = buffer + .windows(index.len()) + .position(|window| window == index) + .unwrap(); + index +} + +pub fn parse_buf( + buffer: &Vec, + first_index: &[u8], + last_index: &[u8], + offset: usize, +) -> Vec { + let first = find_index(&buffer, first_index); + let last = find_index(&buffer, last_index); + return trim(&buffer[first + offset..last].to_vec()); +} diff --git a/core/src/console.rs b/core/src/console.rs new file mode 100644 index 0000000..16ff957 --- /dev/null +++ b/core/src/console.rs @@ -0,0 +1,71 @@ +#[cfg(windows)] +pub fn enable_ansi_support() -> Result<(), u32> { + // ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76% + + use std::ffi::OsStr; + use std::iter::once; + use std::os::windows::ffi::OsStrExt; + use std::ptr::null_mut; + use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode}; + use winapi::um::errhandlingapi::GetLastError; + use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING}; + use winapi::um::handleapi::INVALID_HANDLE_VALUE; + use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}; + + const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004; + + unsafe { + // ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew + // Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected + let console_out_name: Vec = + OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect(); + let console_handle = CreateFileW( + console_out_name.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, + null_mut(), + OPEN_EXISTING, + 0, + null_mut(), + ); + if console_handle == INVALID_HANDLE_VALUE { + return Err(GetLastError()); + } + + // ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode + let mut console_mode: u32 = 0; + if 0 == GetConsoleMode(console_handle, &mut console_mode) { + return Err(GetLastError()); + } + + // VT processing not already enabled? + if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 { + // https://docs.microsoft.com/en-us/windows/console/setconsolemode + if 0 == SetConsoleMode( + console_handle, + console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING, + ) { + return Err(GetLastError()); + } + } + } + + return Ok(()); +} + +pub fn set_ctrl_c_handler() { + use std::process; + use std::sync; + + let running = sync::Arc::new(sync::atomic::AtomicBool::new(true)); + let r = running.clone(); + + ctrlc::set_handler(move || { + r.store(false, sync::atomic::Ordering::SeqCst); + }) + .expect("Error setting Ctrl-C handler"); + println!("Press Ctrl + C for exit"); + while running.load(sync::atomic::Ordering::SeqCst) {} + println!("Exiting..."); + process::exit(0); +} diff --git a/core/src/files.rs b/core/src/files.rs new file mode 100644 index 0000000..4655731 --- /dev/null +++ b/core/src/files.rs @@ -0,0 +1,26 @@ +use std::path::PathBuf; +use std::{fs, io}; + +pub fn collect(profile_paths: &Vec) -> Result, io::Error> { + let mut prdr3s = Vec::new(); + + for path in profile_paths { + let entries = fs::read_dir(path)? + .map(|res| res.map(|e| e.path())) + .collect::, io::Error>>()?; + + for file in entries { + let stem = file.file_stem().unwrap().to_str().unwrap(); + + if stem.chars().count() >= 5 { + let substr = &stem[0..5]; + + if substr == "PRDR3" { + prdr3s.push(file) + } + } + } + } + + Ok(prdr3s) +} diff --git a/core/src/lib.rs b/core/src/lib.rs new file mode 100644 index 0000000..2a1fa96 --- /dev/null +++ b/core/src/lib.rs @@ -0,0 +1,4 @@ +pub mod buffer; +pub mod console; +pub mod files; +pub mod meta; diff --git a/core/src/meta.rs b/core/src/meta.rs new file mode 100644 index 0000000..9335eb4 --- /dev/null +++ b/core/src/meta.rs @@ -0,0 +1,57 @@ +use serde::{Deserialize, Serialize}; + +#[allow(dead_code)] +#[derive(Serialize, Deserialize)] +pub struct Loc { + x: f64, + y: f64, + z: f64, +} + +#[allow(dead_code)] +#[derive(Serialize, Deserialize)] +pub struct Time { + hour: i32, + minute: i32, + second: i32, + day: i32, + month: i32, + year: i32, +} + +#[allow(dead_code)] +#[derive(Serialize, Deserialize)] + +pub struct Meta { + horse: Option>, +} + +#[allow(dead_code)] +#[derive(Serialize, Deserialize)] + +pub struct ImageMetadata { + pub loc: Loc, + pub regionname: usize, + pub districtname: usize, + pub statename: usize, + pub nm: String, + pub sid: String, + pub crewid: usize, + pub mid: String, + pub mode: String, + pub meme: bool, + pub mug: bool, + pub uid: usize, + pub time: Time, + pub creat: usize, + pub slf: bool, + pub drctr: bool, + pub rsedtr: bool, + pub inphotomode: bool, + pub advanced: bool, + pub width: usize, + pub height: usize, + pub size: usize, + pub sign: usize, + pub meta: Meta, +} diff --git a/gui/Cargo.toml b/gui/Cargo.toml new file mode 100644 index 0000000..1a15883 --- /dev/null +++ b/gui/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "gui" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/gui/README.md b/gui/README.md new file mode 100644 index 0000000..6b5d4b0 --- /dev/null +++ b/gui/README.md @@ -0,0 +1,3 @@ +# Gui + +(WIP) \ No newline at end of file diff --git a/gui/src/main.rs b/gui/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/gui/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/buffertrim.rs b/src/buffertrim.rs deleted file mode 100644 index 9fe96e8..0000000 --- a/src/buffertrim.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn is_not_empty(e: &u8) -> bool { - *e != 0x00 -} - -pub fn trim(buffer: &[u8]) -> Vec { - let begin = buffer.iter().position(is_not_empty); - let end = buffer.iter().rev().position(is_not_empty).map(|j| buffer.len() - j); - let vec = begin.and_then(|i| end.map(|j| buffer[i..j].iter().cloned().collect())).unwrap_or(Vec::new()); - vec -} \ No newline at end of file diff --git a/src/console.rs b/src/console.rs deleted file mode 100644 index 963fbff..0000000 --- a/src/console.rs +++ /dev/null @@ -1,69 +0,0 @@ -#[cfg(windows)] -pub fn enable_ansi_support() -> Result<(), u32> { - // ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76% - - use std::ffi::OsStr; - use std::iter::once; - use std::os::windows::ffi::OsStrExt; - use std::ptr::null_mut; - use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode}; - use winapi::um::errhandlingapi::GetLastError; - use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING}; - use winapi::um::handleapi::INVALID_HANDLE_VALUE; - use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}; - - const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004; - - unsafe { - // ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew - // Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected - let console_out_name: Vec = OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect(); - let console_handle = CreateFileW( - console_out_name.as_ptr(), - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_WRITE, - null_mut(), - OPEN_EXISTING, - 0, - null_mut(), - ); - if console_handle == INVALID_HANDLE_VALUE - { - return Err(GetLastError()); - } - - // ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode - let mut console_mode: u32 = 0; - if 0 == GetConsoleMode(console_handle, &mut console_mode) - { - return Err(GetLastError()); - } - - // VT processing not already enabled? - if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 { - // https://docs.microsoft.com/en-us/windows/console/setconsolemode - if 0 == SetConsoleMode(console_handle, console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING) - { - return Err(GetLastError()); - } - } - } - - return Ok(()); -} - -pub fn set_ctrl_c_handler() { - use std::sync; - use std::process; - - let running = sync::Arc::new(sync::atomic::AtomicBool::new(true)); - let r = running.clone(); - - ctrlc::set_handler(move || { - r.store(false, sync::atomic::Ordering::SeqCst); - }).expect("> Error setting Ctrl-C handler"); - println!("> Press Ctrl + C for exit"); - while running.load(sync::atomic::Ordering::SeqCst) {} - println!("> Exiting..."); - process::exit(0); -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 5839af0..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,205 +0,0 @@ -mod buffertrim; - -use dirs; -use colored::*; -use serde::Deserialize; -use fs::File; -use io::Read; -use std::{fs, io, path::{Path, PathBuf}}; - -pub fn run(config: Config) -> Result<(), String> { - - let mut profiles = Vec::new(); - let paths = fs::read_dir(config.profile_path).unwrap(); - - for path in paths { - profiles.push(path.unwrap().path()); - } - - if profiles.len() <= 0 { - return Err(format!("{}: {} {} \n{}", "> Error".red().bold(), "Profile folder not found.".white(), "You must run the game at least once!".white().bold(), "> Aborting.".red())); - } - - let scrns = grab_scrn_files(&profiles); - - if scrns.len() <= 0 { - return Err(format!("{}: {} \n{}", "> Error".red().bold(), "Screenshot files not found".white(), "> Aborting.".red())); - } - - println!("{} {} {} \n{}", ">".green(), scrns.len().to_string().green(), "Screenshots found.".green(), "> Converting...".green().bold()); - - let mut images = Vec::new(); - - for file in &scrns { - let image = convert_file(file.to_path_buf()).unwrap(); - images.push(image); - } - - for image in &images { - match fs::write(Path::new(&config.export_path).join(image.metadata.uid.to_string() + ".jpg"), &image.image_data) { - Ok(ok) => ok, - Err(_err) => { - return Err(format!("{}: {} \n{}", "> Error".red().bold(), "System cannot find or create the specified path", "> Aborting.".red())) - } - } - } - - println!("{}", "> Converting completed!".green()); - println!("{} {}", "> Files saved to".green().bold(), Path::new(&config.export_path).to_string_lossy().bright_blue()); - - println!("{}", "> Removing old files...".green()); - for path in scrns { - let _remove = fs::remove_file(path).unwrap(); - } - - Ok(()) -} - -pub struct Config { - pub profile_path: PathBuf, - pub export_path: PathBuf, -} - -impl Config { - pub fn new() -> Result { - let home_dir = dirs::home_dir().unwrap(); - let profile_path = Path::new(&home_dir).join("Documents").join("Rockstar Games").join("Red Dead Redemption 2").join("Profiles"); - let export_path = Path::new(&home_dir).join("Documents").join("Rockstar Games").join("Red Dead Redemption 2").join("Screenshots"); - - let _create_dirs = fs::create_dir_all(&export_path); - - Ok(Config {profile_path, export_path}) - } - - pub fn set_custom_export_path<'a>(&'a mut self, path: &[String]) -> Result<&'a mut Config, String> { - if path.len() < 2 { - return Err(format!("{}", "Not enough arguments")); - } - - let path = path[1].clone(); - let custom_export_path = Path::new(&path).to_path_buf(); - // TODO: Folders containing Cyrillic characters and spaces are created incorrectly i. e. anything after a space is ignored - // let _create_dirs = fs::create_dir_all(&custom_export_path); - - self.export_path = custom_export_path; - - Ok(self) - } -} - -fn grab_scrn_files(profile_paths: &[PathBuf]) -> Vec { - let mut prdr3s = Vec::new(); - - for path in profile_paths { - match fs::read_dir(path) { - Err(err) => println!("! {:?}", err.kind()), - Ok(paths) => for path in paths { - let file_path = path.unwrap().path(); - let file_stem = file_path.file_stem().unwrap().to_str().unwrap(); - - if file_stem.chars().count() >= 5 { - let file_stem_substr = &file_stem[0..5]; - - if file_stem_substr == "PRDR3" { - prdr3s.push(file_path) - } - } - } - } - } - prdr3s -} - -fn read_file_buf(path: PathBuf) -> Result, io::Error> { - let mut file = File::open(path)?; - let mut data = Vec::new(); - file.read_to_end(&mut data)?; - - return Ok(data); -} - -fn find_index_in_buf(buffer: &Vec, index: &[u8]) -> usize { - let index = buffer.windows(index.len()).position(|window| window == index).unwrap(); - index -} - -fn grab_image_from_buf(buffer: &Vec) -> Vec { - let first_index = find_index_in_buf(&buffer, b"JPEG"); - let last_index = find_index_in_buf(&buffer, b"JSON"); - let image_data = buffertrim::trim(&buffer[first_index + 12..last_index]); - image_data -} - -fn grab_metadata_from_buf(buffer: &Vec) -> Vec { - let first_index = find_index_in_buf(&buffer, b"JSON"); - let last_index = find_index_in_buf(&buffer, b"TITL"); - let metadata = buffertrim::trim(&buffer[first_index + 8..last_index]); - metadata -} - -#[derive(Deserialize, Debug)] -struct Loc { - x: f64, - y: f64, - z: f64 -} - -#[derive(Deserialize, Debug)] -struct Time { - hour: i32, - minute: i32, - second: i32, - day: i32, - month: i32, - year: i32 -} - -#[derive(Deserialize, Debug)] -struct Meta { - horse: Option> -} - -#[derive(Deserialize, Debug)] -struct ImageMetadata { - loc: Loc, - regionname: usize, - districtname: usize, - statename: usize, - nm: String, - sid: String, - crewid: usize, - mid: String, - mode: String, - meme: bool, - mug: bool, - uid: usize, - time: Time, - creat: usize, - slf: bool, - drctr: bool, - rsedtr: bool, - inphotomode: bool, - advanced: bool, - width: usize, - height: usize, - size: usize, - sign: usize, - meta: Meta -} - -#[derive(Deserialize, Debug)] -struct Image { - metadata: ImageMetadata, - image_data: Vec -} - -fn convert_file(path: PathBuf) -> Result { - let mut file_buf = read_file_buf(path).unwrap(); - file_buf = buffertrim::trim(&file_buf); - - let image_data = grab_image_from_buf(&file_buf); - let metadata = grab_metadata_from_buf(&file_buf); - let parsed_metadata: ImageMetadata = serde_json::from_slice(&metadata).unwrap(); - - Ok(Image { metadata: parsed_metadata, image_data }) -} \ No newline at end of file