From fb8af0832bd535f24c69898bec83ab5724d3fb33 Mon Sep 17 00:00:00 2001 From: jake <77554505+brxken128@users.noreply.github.com> Date: Tue, 10 Oct 2023 03:57:37 +0100 Subject: [PATCH] [ENG-1096] Image Conversions (#1364) * derive `Type` on `*Extension` * update `image`, `webp` and add `rspc::Error` support to the `sd-images` crate * rename function for verbosity * cleanup clippy allows and use scaling fn for svg conversions * remove dead comment * specify `generic` image extensions and add fn to enumerate all compatible extensions * re-exports and inline hot provided method * another inline on a provided method * `formatter` -> `handler` and return an explicit error if the extension isn't supported, and add `convert_image()` * `get_ext()` inlined helper fn * add mutation for conversion and query for getting all supported extensions * fix `svg` scaling and generation * update bindings * rm old const * temporary test for all exts * verbosity and no manual drop * remove dbg test * big enum and remove `cur` extension as `image` doesn't support it * add huge extension enum * hopefully get path from file path id and location id * main merge fix * chore: update toml and lockfile * security: update webp * comment entire crypto crate for build times * add bincode, huge enum and custom ser/de * Revert "comment entire crypto crate for build times" This reverts commit 458addaad60fe845c476402f21404f40330e706b. * lockfile * theoretically working ser/de * add svg scaling * fix pdf matching bug and use options * move image scaling fn * major consts overhaul with good ser/de * disable heif checking for now due to new trait api * make the generic handler truly generic * fix pdf types * fix pdf scaling so that it's 120dpi A4 paper size by default - height/aspect res are maintained * heavy cleanup * note to myself * bindings & update core to use the scaling fn from the images crate (reducing code dupes) * move vulnerable `aovec` to be a dev dep so it stays out of release builds (it's only used in tests) * remoev exif crate from the core as it's handled in a sep. crate * silence a clippy warning and update lockfile * lower the maximum file size a slight amount * bindings and minor dep bumps * Some improvements --------- Co-authored-by: Ericson Fogo Soares --- Cargo.lock | 834 +++++++++++++++---------- core/Cargo.toml | 5 +- core/src/api/files.rs | 179 +++++- core/src/location/error.rs | 29 +- core/src/location/mod.rs | 21 + core/src/object/fs/delete.rs | 6 +- core/src/object/fs/erase.rs | 55 +- core/src/object/fs/mod.rs | 16 - core/src/object/media/thumbnail/mod.rs | 16 +- core/src/util/db.rs | 10 + core/src/util/error.rs | 25 + crates/file-ext/src/magic.rs | 2 +- crates/images/Cargo.toml | 25 +- crates/images/src/consts.rs | 182 +++++- crates/images/src/error.rs | 55 +- crates/images/src/formatter.rs | 52 -- crates/images/src/generic.rs | 9 - crates/images/src/handler.rs | 67 ++ crates/images/src/heif.rs | 72 ++- crates/images/src/lib.rs | 65 +- crates/images/src/pdf.rs | 14 +- crates/images/src/svg.rs | 32 +- crates/media-metadata/Cargo.toml | 4 +- crates/media-metadata/src/image/mod.rs | 11 + packages/client/src/core.ts | 6 + 25 files changed, 1173 insertions(+), 619 deletions(-) delete mode 100644 crates/images/src/formatter.rs create mode 100644 crates/images/src/handler.rs diff --git a/Cargo.lock b/Cargo.lock index 78c91049f..cbe9c1191 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "aes-gcm" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", "aes 0.8.3", @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", @@ -145,15 +145,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -293,7 +293,7 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.23", + "rustix 0.37.24", "slab", "socket2 0.4.9", "waker-fn", @@ -327,7 +327,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -338,7 +338,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -389,7 +389,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -557,6 +557,25 @@ dependencies = [ "serde", ] +[[package]] +name = "bincode" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" +dependencies = [ + "bincode_derive", + "serde", +] + +[[package]] +name = "bincode_derive" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" +dependencies = [ + "virtue", +] + [[package]] name = "bindgen" version = "0.64.0" @@ -568,7 +587,6 @@ dependencies = [ "clang-sys", "lazy_static", "lazycell", - "log", "peeking_take_while", "proc-macro2", "quote", @@ -576,6 +594,28 @@ dependencies = [ "rustc-hash", "shlex", "syn 1.0.109", +] + +[[package]] +name = "bindgen" +version = "0.68.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" +dependencies = [ + "bitflags 2.4.0", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.38", "which", ] @@ -620,9 +660,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" dependencies = [ "arrayref", "arrayvec", @@ -674,9 +714,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "brotli" -version = "3.3.4" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -685,9 +725,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.4" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" +checksum = "da74e2b81409b1b743f8f0c62cc6254afefb8b8e50bbfe3735550f7aeefa3448" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -709,7 +749,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", - "regex-automata 0.3.8", + "regex-automata 0.3.9", "serde", ] @@ -720,8 +760,8 @@ source = "git+https://github.com/Brendonovich/prisma-engines?branch=new-4.14.0-p dependencies = [ "connection-string", "either", - "enumflags2 0.7.7", - "indoc 2.0.3", + "enumflags2 0.7.8", + "indoc 2.0.4", "lsp-types", "once_cell", "psl-core", @@ -730,15 +770,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytecount" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" +checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" [[package]] name = "bytemuck" @@ -748,9 +788,9 @@ checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -782,7 +822,7 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" dependencies = [ "glib-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -882,7 +922,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7" dependencies = [ - "smallvec 1.11.0", + "smallvec 1.11.1", ] [[package]] @@ -891,7 +931,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" dependencies = [ - "smallvec 1.11.0", + "smallvec 1.11.1", "target-lexicon", ] @@ -927,9 +967,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", @@ -973,9 +1013,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.2" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", @@ -983,9 +1023,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.2" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", @@ -1002,7 +1042,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1029,15 +1069,14 @@ dependencies = [ [[package]] name = "cocoa-foundation" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", "core-foundation", "core-graphics-types", - "foreign-types", "libc", "objc", ] @@ -1090,9 +1129,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -1327,7 +1366,7 @@ dependencies = [ "phf 0.8.0", "proc-macro2", "quote", - "smallvec 1.11.0", + "smallvec 1.11.1", "syn 1.0.109", ] @@ -1338,7 +1377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1353,12 +1392,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f34ba9a9bcb8645379e9de8cb3ecfcf4d1c85ba66d90deb3259206fa5aa193b" +checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" dependencies = [ "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1421,9 +1460,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622178105f911d937a42cdb140730ba4a3ed2becd8ae6ce39c7d28b5d75d4588" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" dependencies = [ "cfg-if", "cpufeatures", @@ -1444,7 +1483,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1468,7 +1507,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1479,7 +1518,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1489,7 +1528,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.0", + "hashbrown 0.14.1", "lock_api", "once_cell", "parking_lot_core 0.9.8", @@ -1524,9 +1563,9 @@ dependencies = [ [[package]] name = "data-url" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5" +checksum = "41b319d1b62ffbd002e057f36bebd1f42b9f97927c9577461d855f3513c4289f" [[package]] name = "datamodel-renderer" @@ -1616,7 +1655,7 @@ version = "0.1.0" source = "git+https://github.com/Brendonovich/prisma-engines?branch=new-4.14.0-pcr#45b026c8b64ed0b60cb03deed5f478c457de645b" dependencies = [ "colored", - "indoc 2.0.3", + "indoc 2.0.4", "pest", ] @@ -1695,7 +1734,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1768,7 +1807,7 @@ dependencies = [ "ed25519", "rand_core 0.6.4", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "zeroize", ] @@ -1836,11 +1875,11 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" +checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" dependencies = [ - "enumflags2_derive 0.7.7", + "enumflags2_derive 0.7.8", "serde", ] @@ -1857,13 +1896,13 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" +checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1874,7 +1913,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -1885,9 +1924,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", @@ -1921,17 +1960,17 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "exr" -version = "1.7.0" +version = "1.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e481eb11a482815d3e9d618db8c42a93207134662873809335a92327440c18" +checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" dependencies = [ "bit_field", - "flume", + "flume 0.11.0", "half", "lebe", "miniz_oxide", "rayon-core", - "smallvec 1.11.0", + "smallvec 1.11.1", "zune-inflate", ] @@ -1980,9 +2019,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fdeflate" @@ -1999,7 +2038,7 @@ version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf650f461ccf130f4eef4927affed703cc387b183bfc4a7dfee86a076c131127" dependencies = [ - "bindgen", + "bindgen 0.64.0", "cc", "libc", "num_cpus", @@ -2070,6 +2109,15 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2087,16 +2135,16 @@ dependencies = [ [[package]] name = "fontdb" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8d8cbea8f21307d7e84bca254772981296f058a1d36b461bf4d83a7499fc9e" +checksum = "020e203f177c0fb250fb19455a252e838d2bbbce1f80f25ecc42402aafa8cd38" dependencies = [ "fontconfig-parser", "log", "memmap2", "slotmap", "tinyvec", - "ttf-parser 0.19.1", + "ttf-parser", ] [[package]] @@ -2195,7 +2243,7 @@ dependencies = [ "futures-core", "pin-project", "slab", - "smallvec 1.11.0", + "smallvec 1.11.1", ] [[package]] @@ -2256,7 +2304,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -2364,7 +2412,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -2381,7 +2429,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -2395,7 +2443,7 @@ dependencies = [ "gobject-sys", "libc", "pkg-config", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -2407,7 +2455,7 @@ dependencies = [ "gdk-sys", "glib-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", "x11", ] @@ -2510,7 +2558,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", "winapi", ] @@ -2530,7 +2578,7 @@ dependencies = [ "gobject-sys", "libc", "once_cell", - "smallvec 1.11.0", + "smallvec 1.11.1", "thiserror", ] @@ -2556,7 +2604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -2571,7 +2619,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ - "aho-corasick 1.0.5", + "aho-corasick 1.1.1", "bstr", "fnv", "log", @@ -2587,7 +2635,7 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ "glib-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -2638,7 +2686,7 @@ dependencies = [ "gobject-sys", "libc", "pango-sys", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -2703,9 +2751,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" [[package]] name = "hashlink" @@ -2757,9 +2805,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -2780,7 +2828,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b" dependencies = [ "digest 0.9.0", - "hmac", + "hmac 0.11.0", +] + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac 0.12.1", ] [[package]] @@ -2793,6 +2850,24 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "hostname" version = "0.3.1" @@ -2812,7 +2887,21 @@ checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.10.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever 0.11.0", "proc-macro2", "quote", "syn 1.0.109", @@ -2998,12 +3087,12 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfc4a06638d2fd0dda83b01126fefd38ef9f04f54d2fc717a938df68b83a68d" +checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" dependencies = [ "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -3100,12 +3189,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.1", "serde", ] @@ -3117,9 +3206,9 @@ checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "indoc" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c785eefb63ebd0e33416dfcb8d6da0bf27ce752843a45632a67bf10d4d4b5c4" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" [[package]] name = "infer" @@ -3225,7 +3314,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.13", + "rustix 0.38.17", "windows-sys 0.48.0", ] @@ -3437,7 +3526,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" dependencies = [ "cssparser", - "html5ever", + "html5ever 0.25.2", + "matches", + "selectors", +] + +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever 0.26.0", + "indexmap 1.9.3", "matches", "selectors", ] @@ -3471,9 +3573,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libdbus-sys" @@ -3521,9 +3623,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", "windows-sys 0.48.0", @@ -3581,9 +3683,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.40.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef7dd7b09e71aac9271c60031d0e558966cdb3253ba0308ab369bb2de80630d0" +checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" dependencies = [ "either", "fnv", @@ -3602,7 +3704,7 @@ dependencies = [ "rand 0.8.5", "rw-stream-sink", "serde", - "smallvec 1.11.0", + "smallvec 1.11.1", "thiserror", "unsigned-varint", "void", @@ -3619,7 +3721,7 @@ dependencies = [ "libp2p-identity", "log", "parking_lot 0.12.1", - "smallvec 1.11.0", + "smallvec 1.11.1", "trust-dns-resolver", ] @@ -3650,35 +3752,36 @@ dependencies = [ "rand 0.8.5", "regex", "serde", - "sha2 0.10.7", - "smallvec 1.11.0", + "sha2 0.10.8", + "smallvec 1.11.1", "unsigned-varint", "void", ] [[package]] name = "libp2p-identity" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686e73aff5e23efbb99bc85340ea6fd8686986aa7b283a881ba182cfca535ca9" +checksum = "f37304f29c82ede408db06aaba60cd2f783a111f46414d3fc4beedac19e0c67b" dependencies = [ "bs58", "ed25519-dalek", + "hkdf 0.12.3", "log", "multihash", "quick-protobuf", "rand 0.8.5", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "zeroize", ] [[package]] name = "libp2p-kad" -version = "0.44.4" +version = "0.44.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc125f83d8f75322c79e4ade74677d299b34aa5c9d9b5251c03ec28c683cb765" +checksum = "41c5c483b1e90e79409711f515c5bea5de9c4d772a245b1ac01a2233fbcb67fe" dependencies = [ "arrayvec", "asynchronous-codec", @@ -3693,10 +3796,11 @@ dependencies = [ "libp2p-swarm", "log", "quick-protobuf", + "quick-protobuf-codec", "rand 0.8.5", "serde", - "sha2 0.10.7", - "smallvec 1.11.0", + "sha2 0.10.8", + "smallvec 1.11.1", "thiserror", "uint", "unsigned-varint", @@ -3717,7 +3821,7 @@ dependencies = [ "libp2p-swarm", "log", "rand 0.8.5", - "smallvec 1.11.0", + "smallvec 1.11.1", "socket2 0.5.4", "tokio", "trust-dns-proto", @@ -3749,9 +3853,9 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.43.3" +version = "0.43.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28016944851bd73526d3c146aabf0fa9bbe27c558f080f9e5447da3a1772c01a" +checksum = "ab94183f8fc2325817835b57946deb44340c99362cd4606c0a5717299b2ba369" dependencies = [ "either", "fnv", @@ -3764,7 +3868,7 @@ dependencies = [ "multistream-select", "once_cell", "rand 0.8.5", - "smallvec 1.11.0", + "smallvec 1.11.1", "tokio", "void", ] @@ -3849,9 +3953,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "litrs" @@ -3969,7 +4073,21 @@ checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" dependencies = [ "log", "phf 0.8.0", - "phf_codegen", + "phf_codegen 0.8.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", "string_cache", "string_cache_codegen", "tendril", @@ -3998,9 +4116,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "maybe-owned" @@ -4016,12 +4134,12 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "mdns-sd" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409ce3f124dd4fe4ff4da840275f320e713dff8a1b65ba511b35f9fc1e656d37" +checksum = "8c0d8bca08bbe8a91cc4a865f682241468c32bac1fcbc63ceafa07f35d67549e" dependencies = [ - "flume", - "if-addrs 0.10.1", + "flume 0.10.14", + "if-addrs 0.10.2", "log", "polling", "socket2 0.4.9", @@ -4029,15 +4147,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.3" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap2" -version = "0.6.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" dependencies = [ "libc", ] @@ -4173,7 +4291,7 @@ dependencies = [ "crossbeam-utils", "dashmap", "skeptic", - "smallvec 1.11.0", + "smallvec 1.11.1", "tagptr", "triomphe", ] @@ -4282,7 +4400,7 @@ dependencies = [ "futures", "log", "pin-project", - "smallvec 1.11.0", + "smallvec 1.11.1", "unsigned-varint", ] @@ -4444,7 +4562,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" dependencies = [ - "smallvec 1.11.0", + "smallvec 1.11.1", ] [[package]] @@ -4795,7 +4913,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -4806,9 +4924,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.3+3.1.2" +version = "300.1.5+3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd2c101a165fff9935e34def4669595ab1c7847943c42be86e21503e482be107" +checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" dependencies = [ "cc", ] @@ -4921,14 +5039,14 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] name = "parking" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" [[package]] name = "parking_lot" @@ -4983,7 +5101,7 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.16", - "smallvec 1.11.0", + "smallvec 1.11.1", "winapi", ] @@ -4996,7 +5114,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall 0.3.5", - "smallvec 1.11.0", + "smallvec 1.11.1", "windows-targets 0.48.5", ] @@ -5007,7 +5125,7 @@ source = "git+https://github.com/Brendonovich/prisma-engines?branch=new-4.14.0-p dependencies = [ "diagnostics", "either", - "enumflags2 0.7.7", + "enumflags2 0.7.8", "indexmap 1.9.3", "schema-ast", ] @@ -5037,11 +5155,11 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pdfium-render" -version = "0.8.8" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f66fc726c464ae97b7bfec0f41b064d9d25669d5064623c57ac2c62e254617a" +checksum = "c68702ddff3fa10274a97e4b46775d628268e1fb2def1fe287d1c3bb817bf142" dependencies = [ - "bindgen", + "bindgen 0.68.1", "bitflags 2.4.0", "bytemuck", "bytes", @@ -5051,7 +5169,7 @@ dependencies = [ "image", "iter_tools", "js-sys", - "libloading 0.8.0", + "libloading 0.8.1", "log", "maybe-owned", "once_cell", @@ -5085,9 +5203,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" dependencies = [ "memchr", "thiserror", @@ -5096,9 +5214,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bee7be22ce7918f641a33f08e3f43388c7656772244e2bbb2477f44cc9021a" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" dependencies = [ "pest", "pest_generator", @@ -5106,26 +5224,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1511785c5e98d79a05e8a6bc34b4ac2168a0e3e92161862030ad84daa223141" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] name = "pest_meta" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -5170,6 +5288,16 @@ dependencies = [ "phf_shared 0.8.0", ] +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + [[package]] name = "phf_generator" version = "0.8.0" @@ -5259,7 +5387,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -5380,6 +5508,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.38", +] + [[package]] name = "prisma-cli" version = "0.1.0" @@ -5540,7 +5678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -5575,9 +5713,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c" dependencies = [ "unicode-ident", ] @@ -5602,7 +5740,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -5622,8 +5760,8 @@ dependencies = [ "bigdecimal", "chrono", "diagnostics", - "enumflags2 0.7.7", - "indoc 2.0.3", + "enumflags2 0.7.8", + "indoc 2.0.4", "itertools 0.10.5", "lsp-types", "once_cell", @@ -5731,7 +5869,7 @@ dependencies = [ "connection-string", "crossbeam-channel", "cuid", - "enumflags2 0.7.7", + "enumflags2 0.7.8", "futures", "indexmap 1.9.3", "itertools 0.10.5", @@ -5830,9 +5968,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13f81c9a9d574310b8351f8666f5a93ac3b0069c45c28ad52c10291389a7cf9" +checksum = "2c78e758510582acc40acb90458401172d41f1016f8c9dde89e49677afb7eec1" dependencies = [ "bytes", "rand 0.8.5", @@ -6012,9 +6150,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -6022,14 +6160,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -6090,13 +6226,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.5" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ - "aho-corasick 1.0.5", + "aho-corasick 1.1.1", "memchr", - "regex-automata 0.3.8", + "regex-automata 0.3.9", "regex-syntax 0.7.5", ] @@ -6111,11 +6247,11 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ - "aho-corasick 1.0.5", + "aho-corasick 1.1.1", "memchr", "regex-syntax 0.7.5", ] @@ -6167,9 +6303,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.20" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ "base64 0.21.4", "bytes", @@ -6192,6 +6328,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -6214,9 +6351,9 @@ dependencies = [ [[package]] name = "resvg" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6554f47c38eca56827eea7f285c2a3018b4e12e0e195cc105833c008be338f1" +checksum = "cc7980f653f9a7db31acff916a262c3b78c562919263edea29bf41a056e20497" dependencies = [ "gif", "jpeg-decoder", @@ -6311,9 +6448,9 @@ dependencies = [ [[package]] name = "roxmltree" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f595a457b6b8c6cda66a48503e92ee8d19342f905948f29c383200ec9eb1d8" +checksum = "862340e351ce1b271a378ec53f304a5558f7db87f3769dc655a8f6ecbb68b302" dependencies = [ "xmlparser", ] @@ -6366,7 +6503,7 @@ dependencies = [ "hashlink", "libsqlite3-sys", "memchr", - "smallvec 1.11.0", + "smallvec 1.11.1", ] [[package]] @@ -6401,9 +6538,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.37.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" dependencies = [ "bitflags 1.3.2", "errno", @@ -6415,14 +6552,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.13" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.7", + "linux-raw-sys 0.4.8", "windows-sys 0.48.0", ] @@ -6440,9 +6577,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.5" +version = "0.101.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a27e3b59326c16e23d30aeb7a36a24cc0d29e71d68ff611cdfb4a01d013bed" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" dependencies = [ "ring", "untrusted", @@ -6456,17 +6593,17 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rustybuzz" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162bdf42e261bee271b3957691018634488084ef577dddeb6420a9684cab2a6a" +checksum = "71cd15fef9112a1f94ac64b58d1e4628192631ad6af4dc69997f995459c874e7" dependencies = [ "bitflags 1.3.2", "bytemuck", - "smallvec 1.11.0", - "ttf-parser 0.18.1", + "smallvec 1.11.1", + "ttf-parser", "unicode-bidi-mirroring", "unicode-ccc", - "unicode-general-category", + "unicode-properties", "unicode-script", ] @@ -6538,7 +6675,7 @@ version = "0.1.0" source = "git+https://github.com/Brendonovich/prisma-engines?branch=new-4.14.0-pcr#45b026c8b64ed0b60cb03deed5f478c457de645b" dependencies = [ "chrono", - "enumflags2 0.7.7", + "enumflags2 0.7.8", "psl", "quaint", "serde", @@ -6556,7 +6693,7 @@ source = "git+https://github.com/Brendonovich/prisma-engines?branch=new-4.14.0-p dependencies = [ "async-trait", "chrono", - "enumflags2 0.7.7", + "enumflags2 0.7.8", "json-rpc-api-build", "jsonrpc-core", "psl", @@ -6601,7 +6738,7 @@ dependencies = [ "anyhow", "clap", "hex", - "indoc 2.0.3", + "indoc 2.0.4", "sd-crypto", "tokio", ] @@ -6619,9 +6756,9 @@ dependencies = [ "blake3", "bytes", "chrono", - "ctor 0.2.4", + "ctor 0.2.5", "dashmap", - "enumflags2 0.7.7", + "enumflags2 0.7.8", "flate2", "futures", "futures-concurrency", @@ -6634,7 +6771,6 @@ dependencies = [ "include_dir", "int-enum", "itertools 0.11.0", - "kamadak-exif", "mini-moka", "normpath", "notify", @@ -6811,14 +6947,19 @@ dependencies = [ name = "sd-images" version = "0.0.0" dependencies = [ + "bincode", "image", "libheif-rs", "libheif-sys", "once_cell", "pdfium-render", "resvg", + "rspc", + "serde", + "specta", "thiserror", "tracing 0.2.0", + "webp", ] [[package]] @@ -6875,7 +7016,7 @@ version = "0.1.0" dependencies = [ "arc-swap", "ed25519-dalek", - "flume", + "flume 0.10.14", "hex", "if-watch", "libp2p", @@ -6961,7 +7102,7 @@ checksum = "e1da5c423b8783185fd3fecd1c8796c267d2c089d894ce5a93c280a5d3f780a2" dependencies = [ "aes 0.7.5", "block-modes", - "hkdf", + "hkdf 0.11.0", "lazy_static", "num", "rand 0.8.5", @@ -7009,18 +7150,18 @@ dependencies = [ "log", "matches", "phf 0.8.0", - "phf_codegen", + "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", - "smallvec 1.11.0", + "smallvec 1.11.1", "thin-slice", ] [[package]] name = "semver" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" dependencies = [ "serde", ] @@ -7070,16 +7211,16 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", "itoa 1.0.9", "ryu", "serde", @@ -7103,7 +7244,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -7137,7 +7278,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.0", + "indexmap 2.0.2", "serde", "serde_json", "serde_with_macros", @@ -7153,7 +7294,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -7190,9 +7331,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -7214,9 +7355,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -7235,9 +7376,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -7350,9 +7491,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" @@ -7507,8 +7648,8 @@ dependencies = [ "connection-string", "datamodel-renderer", "either", - "enumflags2 0.7.7", - "indoc 2.0.3", + "enumflags2 0.7.8", + "indoc 2.0.4", "once_cell", "prisma-value", "psl", @@ -7537,9 +7678,9 @@ dependencies = [ "async-trait", "bigdecimal", "either", - "enumflags2 0.7.7", + "enumflags2 0.7.8", "indexmap 1.9.3", - "indoc 2.0.3", + "indoc 2.0.4", "once_cell", "prisma-value", "psl", @@ -7652,7 +7793,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -7663,9 +7804,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "svgtypes" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed4b0611e7f3277f68c0fa18e385d9e2d26923691379690039548f867cef02a7" +checksum = "d71499ff2d42f59d26edb21369a308ede691421f79ebc0f001e2b1fd3a7c9e52" dependencies = [ "kurbo", "siphasher", @@ -7695,9 +7836,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.32" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -7773,14 +7914,14 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.1.1" +version = "6.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" +checksum = "94af52f9402f94aac4948a2518b43359be8d9ce6cd9efc1c4de3b2f7b7e897d6" dependencies = [ "cfg-expr 0.15.5", "heck 0.4.1", "pkg-config", - "toml 0.7.8", + "toml 0.8.2", "version-compare 0.1.1", ] @@ -7792,9 +7933,9 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tao" -version = "0.16.2" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6d198e01085564cea63e976ad1566c1ba2c2e4cc79578e35d9f05521505e31" +checksum = "b768eb5cf657b045d03304b1f60ecb54eac8b520f393c4f4240a94111a1caa17" dependencies = [ "bitflags 1.3.2", "cairo-rs", @@ -7929,12 +8070,13 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b" +checksum = "defbfc551bd38ab997e5f8e458f87396d2559d05ce32095076ad6c30f7fc5f9c" dependencies = [ "anyhow", "cargo_toml", + "dirs-next", "heck 0.4.1", "json-patch", "semver", @@ -7942,13 +8084,14 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", + "walkdir", ] [[package]] name = "tauri-codegen" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a" +checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb" dependencies = [ "base64 0.21.4", "brotli", @@ -7962,7 +8105,7 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "tauri-utils", "thiserror", "time", @@ -7972,9 +8115,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7" +checksum = "613740228de92d9196b795ac455091d3a5fbdac2654abb8bb07d010b62ab43af" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -8031,7 +8174,7 @@ version = "1.0.2" source = "git+https://github.com/oscartbeaumont/tauri-specta?rev=c964bef228a90a66effc18cefcba6859c45a8e08#c964bef228a90a66effc18cefcba6859c45a8e08" dependencies = [ "heck 0.4.1", - "indoc 2.0.3", + "indoc 2.0.4", "serde", "serde_json", "specta", @@ -8041,19 +8184,20 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fc02bb6072bb397e1d473c6f76c953cda48b4a2d0cce605df284aa74a12e84" +checksum = "34d55e185904a84a419308d523c2c6891d5e2dbcee740c4997eb42e75a7b0f46" dependencies = [ "brotli", "ctor 0.1.26", "dunce", "glob", "heck 0.4.1", - "html5ever", + "html5ever 0.26.0", "infer", "json-patch", - "kuchiki", + "kuchikiki", + "log", "memchr", "phf 0.10.1", "proc-macro2", @@ -8095,9 +8239,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", - "fastrand 2.0.0", + "fastrand 2.0.1", "redox_syscall 0.3.5", - "rustix 0.38.13", + "rustix 0.38.17", "windows-sys 0.48.0", ] @@ -8114,9 +8258,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] @@ -8129,22 +8273,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -8189,9 +8333,9 @@ checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tiny-skia" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db11798945fa5c3e5490c794ccca7c6de86d3afdd54b4eb324109939c6f37bc" +checksum = "3b72a92a05db376db09fe6d50b7948d106011761c05a6a45e23e17ee9b556222" dependencies = [ "arrayref", "arrayvec", @@ -8204,9 +8348,9 @@ dependencies = [ [[package]] name = "tiny-skia-path" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f60aa35c89ac2687ace1a2556eaaea68e8c0d47408a2e3e7f5c98a489e7281c" +checksum = "6ac3865b9708fc7e1961a65c3a4fa55e984272f33092d3c859929f887fceb647" dependencies = [ "arrayref", "bytemuck", @@ -8255,7 +8399,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -8281,9 +8425,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ "bytes", "futures-core", @@ -8312,7 +8456,19 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] @@ -8330,7 +8486,20 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.2", "serde", "serde_spanned", "toml_datetime", @@ -8432,7 +8601,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -8442,7 +8611,7 @@ source = "git+https://github.com/tokio-rs/tracing?rev=29146260fb4615d271d2e899ad dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", ] [[package]] @@ -8528,7 +8697,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec 1.11.0", + "smallvec 1.11.1", "thread_local", "tracing 0.2.0", "tracing-core 0.2.0", @@ -8546,7 +8715,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec 1.11.0", + "smallvec 1.11.1", "thread_local", "tracing 0.1.37", "tracing-core 0.1.31", @@ -8608,7 +8777,7 @@ dependencies = [ "ipnet", "lazy_static", "rand 0.8.5", - "smallvec 1.11.0", + "smallvec 1.11.1", "socket2 0.4.9", "thiserror", "tinyvec", @@ -8630,7 +8799,7 @@ dependencies = [ "lru-cache", "parking_lot 0.12.1", "resolv-conf", - "smallvec 1.11.0", + "smallvec 1.11.1", "thiserror", "tokio", "tracing 0.1.37", @@ -8645,15 +8814,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "ttf-parser" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633" - -[[package]] -name = "ttf-parser" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a464a4b34948a5f67fddd2b823c62d9d92e44be75058b99939eae6c5b6960b33" +checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" [[package]] name = "tungstenite" @@ -8676,9 +8839,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -8740,17 +8903,11 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" -[[package]] -name = "unicode-general-category" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7" - [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -8761,6 +8918,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0" + [[package]] name = "unicode-script" version = "0.5.5" @@ -8854,7 +9017,7 @@ version = "0.1.0" source = "git+https://github.com/Brendonovich/prisma-engines?branch=new-4.14.0-pcr#45b026c8b64ed0b60cb03deed5f478c457de645b" dependencies = [ "backtrace", - "indoc 2.0.3", + "indoc 2.0.4", "itertools 0.10.5", "quaint", "serde", @@ -8865,9 +9028,9 @@ dependencies = [ [[package]] name = "usvg" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d09ddfb0d93bf84824c09336d32e42f80961a9d1680832eb24fdf249ce11e6" +checksum = "c51daa774fe9ee5efcf7b4fec13019b8119cda764d9a8b5b06df02bb1445c656" dependencies = [ "base64 0.21.4", "log", @@ -8880,9 +9043,9 @@ dependencies = [ [[package]] name = "usvg-parser" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19bf93d230813599927d88557014e0908ecc3531666d47c634c6838bc8db408" +checksum = "45c88a5ffaa338f0e978ecf3d4e00d8f9f493e29bed0752e1a808a1db16afc40" dependencies = [ "data-url", "flate2", @@ -8898,9 +9061,9 @@ dependencies = [ [[package]] name = "usvg-text-layout" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "035044604e89652c0a2959b8b356946997a52649ba6cade45928c2842376feb4" +checksum = "4d2374378cb7a3fb8f33894e0fdb8625e1bbc4f25312db8d91f862130b541593" dependencies = [ "fontdb", "kurbo", @@ -8914,9 +9077,9 @@ dependencies = [ [[package]] name = "usvg-tree" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7939a7e4ed21cadb5d311d6339730681c3e24c3e81d60065be80e485d3fc8b92" +checksum = "6cacb0c5edeaf3e80e5afcf5b0d4004cc1d36318befc9a7c6606507e5d0f4062" dependencies = [ "rctree", "strict-num", @@ -8994,6 +9157,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "virtue" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" + [[package]] name = "void" version = "1.0.2" @@ -9022,9 +9191,9 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" @@ -9084,7 +9253,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -9118,7 +9287,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9183,7 +9352,7 @@ dependencies = [ "pango-sys", "pkg-config", "soup2-sys", - "system-deps 6.1.1", + "system-deps 6.1.2", ] [[package]] @@ -9242,13 +9411,14 @@ checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" [[package]] name = "which" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "libc", + "home", "once_cell", + "rustix 0.38.17", ] [[package]] @@ -9275,9 +9445,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -9639,9 +9809,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" dependencies = [ "memchr", ] @@ -9682,7 +9852,7 @@ dependencies = [ "gio", "glib", "gtk", - "html5ever", + "html5ever 0.25.2", "http", "kuchiki", "libc", @@ -9692,7 +9862,7 @@ dependencies = [ "once_cell", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "soup2", "tao", "thiserror", @@ -9762,9 +9932,9 @@ dependencies = [ [[package]] name = "xmlparser" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" [[package]] name = "xmlwriter" diff --git a/core/Cargo.toml b/core/Cargo.toml index 99a6cefa4..03cce1515 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -28,7 +28,7 @@ sd-crypto = { path = "../crates/crypto", features = [ "keymanager", ] } -sd-images = { path = "../crates/images" } +sd-images = { path = "../crates/images", features = ["rspc", "serde", "specta"] } sd-file-ext = { path = "../crates/file-ext" } sd-sync = { path = "../crates/sync" } sd-p2p = { path = "../crates/p2p", features = ["specta", "serde"] } @@ -52,7 +52,6 @@ tokio = { workspace = true, features = [ "time", "process", ] } -kamadak-exif = "0.5.5" base64 = "0.21.4" serde = { version = "1.0", features = ["derive"] } chrono = { version = "0.4.30", features = ["serde"] } @@ -99,7 +98,6 @@ futures-concurrency = "7.4.3" async-channel = "1.9" tokio-util = { version = "0.7.8", features = ["io"] } slotmap = "1.0.6" -aovec = "1.1.0" flate2 = "1.0.27" tar = "0.4.40" tempfile = "^3.8.0" @@ -117,3 +115,4 @@ version = "0.1.5" [dev-dependencies] tracing-test = "^0.2.4" +aovec = "1.1.0" diff --git a/core/src/api/files.rs b/core/src/api/files.rs index 933b71a6f..a292bc367 100644 --- a/core/src/api/files.rs +++ b/core/src/api/files.rs @@ -7,7 +7,7 @@ use crate::{ file_path_helper::{ file_path_to_isolate, file_path_to_isolate_with_id, FilePathError, IsolatedFilePathData, }, - find_location, LocationError, + get_location_path_from_location_id, LocationError, }, object::{ fs::{ @@ -26,11 +26,14 @@ use crate::{ }; use sd_file_ext::{extensions::ImageExtension, kind::ObjectKind}; +use sd_images::ConvertableExtension; use sd_media_metadata::MediaMetadata; use std::{ + ffi::OsString, path::{Path, PathBuf}, str::FromStr, + sync::Arc, }; use chrono::Utc; @@ -39,7 +42,7 @@ use regex::Regex; use rspc::{alpha::AlphaRouter, ErrorCode}; use serde::Deserialize; use specta::Type; -use tokio::{fs, io}; +use tokio::{fs, io, task::spawn_blocking}; use tracing::{error, warn}; use super::{Ctx, R}; @@ -132,13 +135,8 @@ pub(crate) fn mount() -> AlphaRouter { .map_err(LocationError::MissingField)?; let location_id = isolated_path.location_id(); - let location_path = find_location(&library, location_id) - .select(location::select!({ path })) - .exec() - .await? - .ok_or(LocationError::IdNotFound(location_id))? - .path - .ok_or(LocationError::MissingPath(location_id))?; + let location_path = + get_location_path_from_location_id(&library.db, location_id).await?; Ok(Path::new(&location_path) .join(&isolated_path) @@ -264,13 +262,10 @@ pub(crate) fn mount() -> AlphaRouter { )) .await?; - let location_path = maybe_missing( - maybe_location - .ok_or(LocationError::IdNotFound(args.location_id))? - .path, - "location.path", - ) - .map_err(LocationError::from)?; + let location_path = maybe_location + .ok_or(LocationError::IdNotFound(args.location_id))? + .path + .ok_or(LocationError::MissingPath(args.location_id))?; let file_path = maybe_file_path.ok_or(LocationError::FilePath( FilePathError::IdNotFound(args.file_path_ids[0]), @@ -317,6 +312,140 @@ pub(crate) fn mount() -> AlphaRouter { } }) }) + .procedure("convertImage", { + #[derive(Type, Deserialize)] + struct ConvertImageArgs { + location_id: location::id::Type, + file_path_id: file_path::id::Type, + delete_src: bool, // if set, we delete the src image after + desired_extension: ConvertableExtension, + quality_percentage: Option, // 1% - 125% + } + R.with2(library()) + .mutation(|(_, library), args: ConvertImageArgs| async move { + // TODO:(fogodev) I think this will have to be a Job due to possibly being too much CPU Bound for rspc + + let location_path = + get_location_path_from_location_id(&library.db, args.location_id).await?; + + let isolated_path = IsolatedFilePathData::try_from( + library + .db + .file_path() + .find_unique(file_path::id::equals(args.file_path_id)) + .select(file_path_to_isolate::select()) + .exec() + .await? + .ok_or(LocationError::FilePath(FilePathError::IdNotFound( + args.file_path_id, + )))?, + )?; + + let path = Path::new(&location_path).join(&isolated_path); + + if let Err(e) = fs::metadata(&path).await { + if e.kind() == io::ErrorKind::NotFound { + return Err(LocationError::FilePath(FilePathError::NotFound( + path.into_boxed_path(), + )) + .into()); + } else { + return Err(FileIOError::from(( + path, + e, + "Got an error trying to read metadata from image to convert", + )) + .into()); + } + } + + args.quality_percentage.map(|x| x.clamp(1, 125)); + + let path = Arc::new(path); + + let output_extension = + Arc::new(OsString::from(args.desired_extension.to_string())); + + // TODO(fogodev): Refactor this if Rust get async scoped spawns someday + let inner_path = Arc::clone(&path); + let inner_output_extension = Arc::clone(&output_extension); + let image = spawn_blocking(move || { + sd_images::convert_image(inner_path.as_ref(), &inner_output_extension).map( + |mut image| { + if let Some(quality_percentage) = args.quality_percentage { + image = image.resize( + image.width() + * (quality_percentage as f32 / 100_f32) as u32, + image.height() + * (quality_percentage as f32 / 100_f32) as u32, + image::imageops::FilterType::Triangle, + ); + } + image + }, + ) + }) + .await + .map_err(|e| { + error!("{e:#?}"); + rspc::Error::new( + ErrorCode::InternalServerError, + "Had an internal problem converting image".to_string(), + ) + })??; + + let output_path = path.with_extension(output_extension.as_ref()); + + if fs::metadata(&output_path) + .await + .map(|_| true) + .map_err(|e| { + FileIOError::from( + ( + &output_path, + e, + "Got an error trying to check if the desired converted file already exists" + ) + ) + })? { + return Err(rspc::Error::new( + ErrorCode::Conflict, + "There is already a file with same name and extension in this directory" + .to_string(), + )); + } else { + fs::write(&output_path, image.as_bytes()) + .await + .map_err(|e| { + FileIOError::from(( + output_path, + e, + "There was an error while writing the image to the output path", + )) + })?; + } + + if args.delete_src { + fs::remove_file(path.as_ref()).await.map_err(|e| { + // Let's also invalidate the query here, because we succeeded in converting the file + invalidate_query!(library, "search.paths"); + + FileIOError::from(( + path.as_ref(), + e, + "There was an error while deleting the source image", + )) + })?; + } + + invalidate_query!(library, "search.paths"); + + Ok(()) + }) + }) + .procedure("getConvertableImageExtensions", { + R.query(|_, _: ()| async move { Ok(sd_images::all_compatible_extensions()) }) + }) .procedure("eraseFiles", { R.with2(library()) .mutation(|(node, library), args: FileEraserJobInit| async move { @@ -541,17 +670,12 @@ pub(crate) fn mount() -> AlphaRouter { } } - R.with2(library()) - .mutation(|(_, library), args: RenameFileArgs| async move { - let location_path = find_location(&library, args.location_id) - .select(location::select!({ path })) - .exec() - .await? - .ok_or(LocationError::IdNotFound(args.location_id))? - .path - .ok_or(LocationError::MissingPath(args.location_id))?; + R.with2(library()).mutation( + |(_, library), RenameFileArgs { location_id, kind }: RenameFileArgs| async move { + let location_path = + get_location_path_from_location_id(&library.db, location_id).await?; - let res = match args.kind { + let res = match kind { RenameKind::One(one) => { RenameFileArgs::rename_one(one, location_path, &library).await } @@ -564,6 +688,7 @@ pub(crate) fn mount() -> AlphaRouter { invalidate_query!(library, "search.objects"); res - }) + }, + ) }) } diff --git a/core/src/location/error.rs b/core/src/location/error.rs index 44fd00c78..2ced86af2 100644 --- a/core/src/location/error.rs +++ b/core/src/location/error.rs @@ -77,31 +77,34 @@ pub enum LocationError { impl From for rspc::Error { fn from(err: LocationError) -> Self { + use LocationError::*; + match err { // Not found errors - LocationError::PathNotFound(_) - | LocationError::UuidNotFound(_) - | LocationError::IdNotFound(_) => { - rspc::Error::with_cause(ErrorCode::NotFound, err.to_string(), err) + PathNotFound(_) + | UuidNotFound(_) + | IdNotFound(_) + | FilePath(FilePathError::IdNotFound(_) | FilePathError::NotFound(_)) => { + Self::with_cause(ErrorCode::NotFound, err.to_string(), err) } // User's fault errors - LocationError::NotDirectory(_) - | LocationError::NestedLocation(_) - | LocationError::LocationAlreadyExists(_) => { - rspc::Error::with_cause(ErrorCode::BadRequest, err.to_string(), err) + NotDirectory(_) | NestedLocation(_) | LocationAlreadyExists(_) => { + Self::with_cause(ErrorCode::BadRequest, err.to_string(), err) } // Custom error message is used to differenciate these errors in the frontend // TODO: A better solution would be for rspc to support sending custom data alongside errors - LocationError::NeedRelink { .. } => { - rspc::Error::with_cause(ErrorCode::Conflict, "NEED_RELINK".to_owned(), err) + NeedRelink { .. } => { + Self::with_cause(ErrorCode::Conflict, "NEED_RELINK".to_owned(), err) } - LocationError::AddLibraryToMetadata(_) => { - rspc::Error::with_cause(ErrorCode::Conflict, "ADD_LIBRARY".to_owned(), err) + AddLibraryToMetadata(_) => { + Self::with_cause(ErrorCode::Conflict, "ADD_LIBRARY".to_owned(), err) } - _ => rspc::Error::with_cause(ErrorCode::InternalServerError, err.to_string(), err), + // Internal errors + MissingField(missing_error) => missing_error.into(), + _ => Self::with_cause(ErrorCode::InternalServerError, err.to_string(), err), } } } diff --git a/core/src/location/mod.rs b/core/src/location/mod.rs index ec5df2066..5ef71f68e 100644 --- a/core/src/location/mod.rs +++ b/core/src/location/mod.rs @@ -1005,3 +1005,24 @@ pub async fn update_location_size( Ok(()) } + +pub async fn get_location_path_from_location_id( + db: &PrismaClient, + location_id: file_path::id::Type, +) -> Result { + db.location() + .find_unique(location::id::equals(location_id)) + .exec() + .await + .map_err(Into::into) + .and_then(|maybe_location| { + maybe_location + .ok_or(LocationError::IdNotFound(location_id)) + .and_then(|location| { + location + .path + .map(PathBuf::from) + .ok_or(LocationError::MissingPath(location_id)) + }) + }) +} diff --git a/core/src/object/fs/delete.rs b/core/src/object/fs/delete.rs index 2aa0c338c..59904ab54 100644 --- a/core/src/object/fs/delete.rs +++ b/core/src/object/fs/delete.rs @@ -4,6 +4,7 @@ use crate::{ CurrentStep, JobError, JobInitOutput, JobResult, JobStepOutput, StatefulJob, WorkerContext, }, library::Library, + location::get_location_path_from_location_id, prisma::{file_path, location}, util::{db::maybe_missing, error::FileIOError}, }; @@ -16,7 +17,7 @@ use specta::Type; use tokio::{fs, io}; use tracing::warn; -use super::{get_location_path_from_location_id, get_many_files_datas, FileData}; +use super::{error::FileSystemJobsError, get_many_files_datas, FileData}; #[derive(Serialize, Deserialize, Hash, Type, Debug)] pub struct FileDeleterJobInit { @@ -45,7 +46,8 @@ impl StatefulJob for FileDeleterJobInit { get_location_path_from_location_id(db, init.location_id).await?, &init.file_path_ids, ) - .await?; + .await + .map_err(FileSystemJobsError::from)?; // Must fill in the data, otherwise the job will not run *data = Some(()); diff --git a/core/src/object/fs/erase.rs b/core/src/object/fs/erase.rs index f98ca6b77..62ae114bb 100644 --- a/core/src/object/fs/erase.rs +++ b/core/src/object/fs/erase.rs @@ -5,7 +5,7 @@ use crate::{ StatefulJob, WorkerContext, }, library::Library, - location::file_path_helper::IsolatedFilePathData, + location::{file_path_helper::IsolatedFilePathData, get_location_path_from_location_id}, prisma::{file_path, location}, util::{db::maybe_missing, error::FileIOError}, }; @@ -23,8 +23,8 @@ use tokio::{ use tracing::trace; use super::{ - error::FileSystemJobsError, get_file_data_from_isolated_file_path, - get_location_path_from_location_id, get_many_files_datas, FileData, + error::FileSystemJobsError, get_file_data_from_isolated_file_path, get_many_files_datas, + FileData, }; #[serde_as] @@ -70,7 +70,9 @@ impl StatefulJob for FileEraserJobInit { let init = self; let Library { db, .. } = &*ctx.library; - let location_path = get_location_path_from_location_id(db, init.location_id).await?; + let location_path = get_location_path_from_location_id(db, init.location_id) + .await + .map_err(FileSystemJobsError::from)?; let steps = get_many_files_datas(db, &location_path, &init.file_path_ids).await?; @@ -132,29 +134,34 @@ impl StatefulJob for FileEraserJobInit { Ok((more_steps, new_metadata).into()) } else { - let mut file = OpenOptions::new() - .read(true) - .write(true) - .open(&step.full_path) - .await - .map_err(|e| FileIOError::from((&step.full_path, e)))?; - let file_len = file - .metadata() - .await - .map_err(|e| FileIOError::from((&step.full_path, e)))? - .len(); + { + let mut file = OpenOptions::new() + .read(true) + .write(true) + .open(&step.full_path) + .await + .map_err(|e| FileIOError::from((&step.full_path, e)))?; + let file_len = file + .metadata() + .await + .map_err(|e| FileIOError::from((&step.full_path, e)))? + .len(); - sd_crypto::fs::erase::erase(&mut file, file_len as usize, init.passes).await?; + trace!( + "Overwriting file: {} with {} passes", + step.full_path.display(), + init.passes + ); - file.set_len(0) - .await - .map_err(|e| FileIOError::from((&step.full_path, e)))?; - file.flush() - .await - .map_err(|e| FileIOError::from((&step.full_path, e)))?; - drop(file); + sd_crypto::fs::erase::erase(&mut file, file_len as usize, init.passes).await?; - trace!("Erasing file: {}", step.full_path.display()); + file.set_len(0) + .await + .map_err(|e| FileIOError::from((&step.full_path, e)))?; + file.flush() + .await + .map_err(|e| FileIOError::from((&step.full_path, e)))?; + } fs::remove_file(&step.full_path) .await diff --git a/core/src/object/fs/mod.rs b/core/src/object/fs/mod.rs index 8d55d447e..6f337480d 100644 --- a/core/src/object/fs/mod.rs +++ b/core/src/object/fs/mod.rs @@ -44,22 +44,6 @@ pub struct FileData { pub full_path: PathBuf, } -pub async fn get_location_path_from_location_id( - db: &PrismaClient, - location_id: file_path::id::Type, -) -> Result { - let location = db - .location() - .find_unique(location::id::equals(location_id)) - .exec() - .await? - .ok_or(FileSystemJobsError::Location(LocationError::IdNotFound( - location_id, - )))?; - - Ok(maybe_missing(location.path, "location.path")?.into()) -} - pub async fn get_many_files_datas( db: &PrismaClient, location_path: impl AsRef, diff --git a/core/src/object/media/thumbnail/mod.rs b/core/src/object/media/thumbnail/mod.rs index 6d88a8168..841282e8b 100644 --- a/core/src/object/media/thumbnail/mod.rs +++ b/core/src/object/media/thumbnail/mod.rs @@ -11,7 +11,7 @@ use crate::{ use sd_file_ext::extensions::{ DocumentExtension, Extension, ImageExtension, ALL_DOCUMENT_EXTENSIONS, ALL_IMAGE_EXTENSIONS, }; -use sd_images::format_image; +use sd_images::{format_image, scale_dimensions}; use sd_media_metadata::image::Orientation; #[cfg(feature = "ffmpeg")] @@ -109,14 +109,6 @@ const TAGRET_PX: f32 = 262144_f32; /// and is treated as a percentage (so 30% in this case, or it's the same as multiplying by `0.3`). const TARGET_QUALITY: f32 = 30_f32; -/// This takes in a width and a height, and returns a scaled width and height -/// It is scaled proportionally to the [`TARGET_PX`], so smaller images will be upscaled, -/// and larger images will be downscaled. This approach also maintains the aspect ratio of the image. -fn calculate_factor(w: f32, h: f32) -> (u32, u32) { - let sf = (TAGRET_PX / (w * h)).sqrt(); - ((w * sf).round() as u32, (h * sf).round() as u32) -} - #[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub enum ThumbnailerEntryKind { Image, @@ -140,13 +132,13 @@ pub async fn generate_image_thumbnail>( let img = format_image(&file_path).map_err(|_| ThumbnailerError::Encoding)?; let (w, h) = img.dimensions(); - let (w_scale, h_scale) = calculate_factor(w as f32, h as f32); + let (w_scaled, h_scaled) = scale_dimensions(w as f32, h as f32, TAGRET_PX); // Optionally, resize the existing photo and convert back into DynamicImage let mut img = DynamicImage::ImageRgba8(imageops::resize( &img, - w_scale, - h_scale, + w_scaled as u32, + h_scaled as u32, imageops::FilterType::Triangle, )); diff --git a/core/src/util/db.rs b/core/src/util/db.rs index 80a05b831..03b23391d 100644 --- a/core/src/util/db.rs +++ b/core/src/util/db.rs @@ -69,6 +69,16 @@ pub fn inode_to_db(inode: u64) -> Vec { #[error("Missing field {0}")] pub struct MissingFieldError(&'static str); +impl From for rspc::Error { + fn from(value: MissingFieldError) -> Self { + rspc::Error::with_cause( + rspc::ErrorCode::InternalServerError, + "Missing crucial data in the database".to_string(), + value, + ) + } +} + pub trait OptionalField: Sized { type Out; diff --git a/core/src/util/error.rs b/core/src/util/error.rs index 7fb39d9bb..081b61be8 100644 --- a/core/src/util/error.rs +++ b/core/src/util/error.rs @@ -8,6 +8,7 @@ pub struct FileIOError { pub path: Box, #[source] pub source: io::Error, + pub maybe_context: Option<&'static str>, } impl> From<(P, io::Error)> for FileIOError { @@ -15,10 +16,34 @@ impl> From<(P, io::Error)> for FileIOError { Self { path: path.as_ref().into(), source, + maybe_context: None, } } } +impl> From<(P, io::Error, &'static str)> for FileIOError { + fn from((path, source, context): (P, io::Error, &'static str)) -> Self { + Self { + path: path.as_ref().into(), + source, + maybe_context: Some(context), + } + } +} + +impl From for rspc::Error { + fn from(value: FileIOError) -> Self { + Self::with_cause( + rspc::ErrorCode::InternalServerError, + value + .maybe_context + .unwrap_or("Error accessing file system") + .to_string(), + value, + ) + } +} + #[derive(Debug, Error)] #[error("received a non UTF-8 path: ", .0.to_string_lossy())] pub struct NonUtf8PathError(pub Box); diff --git a/crates/file-ext/src/magic.rs b/crates/file-ext/src/magic.rs index 3122af2af..19b8704f4 100644 --- a/crates/file-ext/src/magic.rs +++ b/crates/file-ext/src/magic.rs @@ -107,7 +107,7 @@ macro_rules! extension_category_enum { $($(#[$variant_attr:meta])* $variant:ident $(= $( [$($magic_bytes:tt),*] $(+ $offset:literal)? )|+ )? ,)* } ) => { - #[derive(Debug, ::serde::Serialize, ::serde::Deserialize, ::strum::Display, Clone, Copy, PartialEq, Eq)] + #[derive(Debug, ::serde::Serialize, ::serde::Deserialize, ::strum::Display, ::specta::Type, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] $(#[$enum_attr])* diff --git a/crates/images/Cargo.toml b/crates/images/Cargo.toml index 049452df5..920ac3f9f 100644 --- a/crates/images/Cargo.toml +++ b/crates/images/Cargo.toml @@ -2,8 +2,8 @@ name = "sd-images" version = "0.0.0" authors = [ - "Jake Robinson ", - "Vítor Vasconcellos ", + "Jake Robinson ", + "Vítor Vasconcellos ", ] license = { workspace = true } repository = { workspace = true } @@ -14,12 +14,25 @@ heif = ["dep:libheif-rs", "dep:libheif-sys"] [dependencies] image = "0.24.7" -thiserror = "1.0.48" +webp = { version = "0.2.6", optional = true } +thiserror = "1.0.49" +resvg = "0.36.0" +rspc = { workspace = true, optional = true } # error conversion +specta = { workspace = true, optional = true } +serde = { workspace = true, optional = true, features = ["derive"] } +bincode = { version = "2.0.0-rc.3", features = [ + "derive", + "alloc", +], optional = true } once_cell = "1.18.0" tracing = { workspace = true } -resvg = "0.35.0" -# both of these added *default* bindgen features in 0.22.0 and 2.0.0+1.16.2 respectively + +# both of these added *default* bindgen features in 0.22.0 and 2.0.0 respectively # this broke builds as we build our own liibheif, so i disabled their default features libheif-rs = { version = "0.22.0", default-features = false, optional = true } libheif-sys = { version = "2.0.0", default-features = false, optional = true } -pdfium-render = { version ="0.8.8", features = ["sync", "image", "thread_safe"] } +pdfium-render = { version = "0.8.8", features = [ + "sync", + "image", + "thread_safe", +] } diff --git a/crates/images/src/consts.rs b/crates/images/src/consts.rs index 6a8e094d5..5636a61e6 100644 --- a/crates/images/src/consts.rs +++ b/crates/images/src/consts.rs @@ -1,31 +1,175 @@ +use std::fmt::Display; + /// The size of 1MiB in bytes const MIB: u64 = 1_048_576; +/// The maximum file size that an image can be in order to have a thumbnail generated. +/// +/// This value is in MiB. +pub const MAXIMUM_FILE_SIZE: u64 = MIB * 192; + +/// These are roughly all extensions supported by the `image` crate, as of `v0.24.7`. +/// +/// We only support images that have both good encoding and decoding support, without external C-based dependencies (e.g. `avif`) +pub const GENERIC_EXTENSIONS: [&str; 16] = [ + "bmp", "dib", "ff", "gif", "ico", "jpg", "jpeg", "png", "pnm", "qoi", "tga", "icb", "vda", + "vst", "tiff", "tif", +]; +pub const SVG_EXTENSIONS: [&str; 2] = ["svg", "svgz"]; +pub const PDF_EXTENSIONS: [&str; 1] = ["pdf"]; #[cfg(feature = "heif")] pub const HEIF_EXTENSIONS: [&str; 7] = ["heif", "heifs", "heic", "heics", "avif", "avci", "avcs"]; -/// The maximum file size that an image can be in order to have a thumbnail generated. -/// -/// This value is in MiB. -#[cfg(feature = "heif")] -pub const HEIF_MAXIMUM_FILE_SIZE: u64 = MIB * 32; - -pub const SVG_EXTENSIONS: [&str; 2] = ["svg", "svgz"]; +// Will be needed for validating HEIF images +// #[cfg(feature = "heif")] +// pub const HEIF_BPS: u8 = 8; /// The maximum file size that an image can be in order to have a thumbnail generated. +/// This is the target pixel count for all SVG images to be rendered at. /// -/// This value is in MiB. -pub const SVG_MAXIMUM_FILE_SIZE: u64 = MIB * 24; - -/// The size that SVG images are rendered at. -pub const SVG_RENDER_SIZE: u32 = 512; - -pub const PDF_EXTENSION: &str = "pdf"; +/// It is 512x512, but if the SVG has a non-1:1 aspect ratio we need to account for that. +pub const SVG_TARGET_PX: f32 = 262_144_f32; /// The size that PDF pages are rendered at. -pub const PDF_RENDER_SIZE: i32 = 1024; - -/// The maximum file size that an image can be in order to have a thumbnail generated. /// -/// This value is in MiB. -pub const GENERIC_MAXIMUM_FILE_SIZE: u64 = MIB * 64; +/// This is 120 DPI at standard A4 printer paper size - the target aspect +/// ratio and height are maintained. +pub const PDF_RENDER_WIDTH: pdfium_render::prelude::Pixels = 992; + +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] +#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] +#[derive(Debug, Clone, Copy)] +pub enum ConvertableExtension { + Bmp, + Dib, + Ff, + Gif, + Ico, + Jpg, + Jpeg, + Png, + Pnm, + Qoi, + Tga, + Icb, + Vda, + Vst, + Tiff, + Tif, + Heif, + Heifs, + Heic, + Heics, + Avif, + Avci, + Avcs, + Svg, + Svgz, + Pdf, +} + +impl Display for ConvertableExtension { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{self:?}") + } +} + +impl TryFrom for ConvertableExtension { + type Error = crate::Error; + + fn try_from(value: String) -> Result { + let v = value.to_lowercase(); + match v.as_str() { + "bmp" => Ok(Self::Bmp), + "dib" => Ok(Self::Dib), + "ff" => Ok(Self::Ff), + "gif" => Ok(Self::Gif), + "ico" => Ok(Self::Ico), + "jpg" => Ok(Self::Jpg), + "jpeg" => Ok(Self::Jpeg), + "png" => Ok(Self::Png), + "pnm" => Ok(Self::Pnm), + "qoi" => Ok(Self::Qoi), + "tga" => Ok(Self::Tga), + "icb" => Ok(Self::Icb), + "vda" => Ok(Self::Vda), + "vst" => Ok(Self::Vst), + "tiff" => Ok(Self::Tiff), + "tif" => Ok(Self::Tif), + "heif" => Ok(Self::Heif), + "heifs" => Ok(Self::Heifs), + "heic" => Ok(Self::Heic), + "heics" => Ok(Self::Heics), + "avif" => Ok(Self::Avif), + "avci" => Ok(Self::Avci), + "avcs" => Ok(Self::Avcs), + "svg" => Ok(Self::Svg), + "svgz" => Ok(Self::Svgz), + "pdf" => Ok(Self::Pdf), + _ => Err(crate::Error::Unsupported), + } + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for ConvertableExtension { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +#[cfg(feature = "serde")] +struct ExtensionVisitor; + +#[cfg(feature = "serde")] +impl<'de> serde::de::Visitor<'de> for ExtensionVisitor { + type Value = ConvertableExtension; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("A valid extension string`") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Self::Value::try_from(v.to_string()).map_err(|e| E::custom(format!("unknown variant: {e}"))) + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for ConvertableExtension { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_str(ExtensionVisitor) + } +} + +#[inline] +#[must_use] +pub fn all_compatible_extensions() -> Vec { + #[cfg(feature = "heif")] + let res = GENERIC_EXTENSIONS + .into_iter() + .chain(HEIF_EXTENSIONS) + .chain(SVG_EXTENSIONS) + .chain(PDF_EXTENSIONS) + .map(String::from) + .collect(); + + #[cfg(not(feature = "heif"))] + let res = GENERIC_EXTENSIONS + .into_iter() + .chain(SVG_EXTENSIONS) + .chain(PDF_EXTENSIONS) + .map(String::from) + .collect(); + + res +} diff --git a/crates/images/src/error.rs b/crates/images/src/error.rs index 48629657c..2bd9dd06c 100644 --- a/crates/images/src/error.rs +++ b/crates/images/src/error.rs @@ -1,26 +1,12 @@ -use std::num::TryFromIntError; +use std::{num::TryFromIntError, path::Path}; pub type Result = std::result::Result; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("error with pdfium: {0}")] - Pdfium(#[from] pdfium_render::prelude::PdfiumError), - #[error("failed to load pdfium library")] - PdfiumBinding, - #[cfg(feature = "heif")] - #[error("error with libheif: {0}")] - LibHeif(#[from] libheif_rs::HeifError), - #[error("error with usvg: {0}")] - USvg(#[from] resvg::usvg::Error), - #[error("failed to allocate `Pixbuf` while converting an SVG")] - Pixbuf, - #[error("error while loading the image (via the `image` crate): {0}")] - Image(#[from] image::ImageError), - #[error("there was an i/o error: {0}")] - Io(#[from] std::io::Error), - #[error("there was an error while converting the image to an `RgbImage`")] - RgbImageConversion, + #[error("there was an i/o at path '{}' error: {0}", .1.display())] + Io(std::io::Error, Box), + #[error("the image provided is unsupported")] Unsupported, #[error("the image provided is too large (over 20MiB)")] @@ -29,12 +15,35 @@ pub enum Error { InvalidBitDepth, #[error("invalid path provided (non UTF-8)")] InvalidPath, - #[error("the image has an invalid length to be RGB")] + #[error("the length of an input stream was invalid")] InvalidLength, - #[error("invalid path provided (it had no file extension)")] - NoExtension, - #[error("error while converting from raw")] - RawConversion, + + // these errors are either: reliant on external (C dependencies), or are extremely niche + // this means they rely on a lot of specific functionality, and therefore have specific errors + #[cfg(feature = "heif")] + #[error("error with libheif: {0}")] + LibHeif(#[from] libheif_rs::HeifError), + #[error("there was an error while converting the image to an `RgbImage`")] + RgbImageConversion, + #[error("error with pdfium: {0}")] + Pdfium(#[from] pdfium_render::prelude::PdfiumError), + #[error("failed to load pdfium library")] + PdfiumBinding, + #[error("error with usvg: {0}")] + USvg(#[from] resvg::usvg::Error), + #[error("failed to allocate `Pixbuf` while converting an SVG")] + Pixbuf, + #[error("error while loading the image (via the `image` crate): {0}")] + Image(#[from] image::ImageError), + // #[error("error while converting from raw")] // not enough rust support for it to be feasible + // RawConversion, #[error("error while parsing integers")] TryFromInt(#[from] TryFromIntError), } + +#[cfg(feature = "rspc")] +impl From for rspc::Error { + fn from(value: Error) -> Self { + Self::new(rspc::ErrorCode::InternalServerError, value.to_string()) + } +} diff --git a/crates/images/src/formatter.rs b/crates/images/src/formatter.rs deleted file mode 100644 index ac439664c..000000000 --- a/crates/images/src/formatter.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::{ - consts, - error::{Error, Result}, - generic::GenericHandler, - pdf::PdfHandler, - svg::SvgHandler, - ImageHandler, -}; -use image::DynamicImage; -use std::{ - ffi::{OsStr, OsString}, - path::Path, -}; - -#[cfg(feature = "heif")] -use crate::heif::HeifHandler; - -pub fn format_image(path: impl AsRef) -> Result { - let ext = path - .as_ref() - .extension() - .map_or_else(|| Err(Error::NoExtension), |e| Ok(e.to_ascii_lowercase()))?; - match_to_handler(&ext).handle_image(path.as_ref()) -} - -#[allow(clippy::useless_let_if_seq)] -fn match_to_handler(ext: &OsStr) -> Box { - let mut handler: Box = Box::new(GenericHandler {}); - - #[cfg(feature = "heif")] - if consts::HEIF_EXTENSIONS - .iter() - .map(OsString::from) - .any(|x| x == ext) - { - handler = Box::new(HeifHandler {}); - } - - if consts::SVG_EXTENSIONS - .iter() - .map(OsString::from) - .any(|x| x == ext) - { - handler = Box::new(SvgHandler {}); - } - - if ext == consts::PDF_EXTENSION { - handler = Box::new(PdfHandler {}); - } - - handler -} diff --git a/crates/images/src/generic.rs b/crates/images/src/generic.rs index 9d401bb54..badd06568 100644 --- a/crates/images/src/generic.rs +++ b/crates/images/src/generic.rs @@ -1,4 +1,3 @@ -use crate::consts::GENERIC_MAXIMUM_FILE_SIZE; pub use crate::error::{Error, Result}; use crate::ImageHandler; use image::DynamicImage; @@ -7,14 +6,6 @@ use std::path::Path; pub struct GenericHandler {} impl ImageHandler for GenericHandler { - fn maximum_size(&self) -> u64 { - GENERIC_MAXIMUM_FILE_SIZE - } - - fn validate_image(&self, _bits_per_pixel: u8, _length: usize) -> Result<()> { - Ok(()) - } - fn handle_image(&self, path: &Path) -> Result { let data = self.get_data(path)?; // this also makes sure the file isn't above the maximum size Ok(image::load_from_memory(&data)?) diff --git a/crates/images/src/handler.rs b/crates/images/src/handler.rs new file mode 100644 index 000000000..135ed2e72 --- /dev/null +++ b/crates/images/src/handler.rs @@ -0,0 +1,67 @@ +use crate::{ + consts, + error::{Error, Result}, + generic::GenericHandler, + pdf::PdfHandler, + svg::SvgHandler, + ImageHandler, +}; +use image::DynamicImage; +use std::{ + ffi::{OsStr, OsString}, + path::Path, +}; + +#[cfg(feature = "heif")] +use crate::heif::HeifHandler; + +pub fn format_image(path: impl AsRef) -> Result { + let path = path.as_ref(); + match_to_handler(path.extension())?.handle_image(path) +} + +pub fn convert_image(path: impl AsRef, desired_ext: &OsStr) -> Result { + let path = path.as_ref(); + match_to_handler(path.extension())?.convert_image(match_to_handler(Some(desired_ext))?, path) +} + +#[allow(clippy::useless_let_if_seq)] +fn match_to_handler(ext: Option<&OsStr>) -> Result> { + let ext = ext.map(OsStr::to_ascii_lowercase).unwrap_or_default(); + let mut handler: Option> = None; + + if consts::GENERIC_EXTENSIONS + .iter() + .map(OsString::from) + .any(|x| x == ext) + { + handler = Some(Box::new(GenericHandler {})); + } + + #[cfg(feature = "heif")] + if consts::HEIF_EXTENSIONS + .iter() + .map(OsString::from) + .any(|x| x == ext) + { + handler = Some(Box::new(HeifHandler {})); + } + + if consts::SVG_EXTENSIONS + .iter() + .map(OsString::from) + .any(|x| x == ext) + { + handler = Some(Box::new(SvgHandler {})); + } + + if consts::PDF_EXTENSIONS + .iter() + .map(OsString::from) + .any(|x| x == ext) + { + handler = Some(Box::new(PdfHandler {})); + } + + handler.ok_or(Error::Unsupported) +} diff --git a/crates/images/src/heif.rs b/crates/images/src/heif.rs index d48ca63ac..b3ba47ace 100644 --- a/crates/images/src/heif.rs +++ b/crates/images/src/heif.rs @@ -1,5 +1,4 @@ pub use crate::consts::HEIF_EXTENSIONS; -use crate::consts::HEIF_MAXIMUM_FILE_SIZE; pub use crate::error::{Error, Result}; use crate::ImageHandler; use image::DynamicImage; @@ -14,19 +13,15 @@ static HEIF: Lazy = Lazy::new(LibHeif::new); pub struct HeifHandler {} impl ImageHandler for HeifHandler { - fn maximum_size(&self) -> u64 { - HEIF_MAXIMUM_FILE_SIZE - } + // fn validate_image(&self, bits_per_pixel: u8, length: usize) -> Result<()> { + // if bits_per_pixel != 8 { + // return Err(Error::InvalidBitDepth); + // } else if length % 3 != 0 || length % 4 != 0 { + // return Err(Error::InvalidLength); + // } - fn validate_image(&self, bits_per_pixel: u8, length: usize) -> Result<()> { - if bits_per_pixel != 8 { - return Err(Error::InvalidBitDepth); - } else if length % 3 != 0 || length % 4 != 0 { - return Err(Error::InvalidLength); - } - - Ok(()) - } + // Ok(()) + // } fn handle_image(&self, path: &Path) -> Result { let img = { @@ -38,7 +33,7 @@ impl ImageHandler for HeifHandler { let planes = img.planes(); if let Some(i) = planes.interleaved { - self.validate_image(i.bits_per_pixel, i.data.len())?; + // self.validate_image(i.bits_per_pixel, i.data.len())?; let mut reader = Cursor::new(i.data); let mut sequence = vec![]; @@ -49,9 +44,15 @@ impl ImageHandler for HeifHandler { (0..img.height()).try_for_each(|x| { let x: usize = x.try_into()?; let start: u64 = (i.stride * x).try_into()?; - reader.seek(SeekFrom::Start(start))?; + reader + .seek(SeekFrom::Start(start)) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))?; + (0..img.width()).try_for_each(|_| { - reader.read_exact(&mut buffer)?; + reader + .read_exact(&mut buffer) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))?; + sequence.extend_from_slice(&buffer); Ok::<(), Error>(()) })?; @@ -68,20 +69,18 @@ impl ImageHandler for HeifHandler { // This was hand-crafted using my best judgement, and I think it should work. // I'm sure we'll get a GH issue opened regarding it if not - brxken128 - self.validate_image(r.bits_per_pixel, r.data.len())?; - self.validate_image(g.bits_per_pixel, g.data.len())?; - self.validate_image(b.bits_per_pixel, b.data.len())?; + // self.validate_image(r.bits_per_pixel, r.data.len())?; + // self.validate_image(g.bits_per_pixel, g.data.len())?; + // self.validate_image(b.bits_per_pixel, b.data.len())?; let mut red = Cursor::new(r.data); let mut green = Cursor::new(g.data); let mut blue = Cursor::new(b.data); - let (mut alpha, has_alpha) = if let Some(a) = planes.a { - self.validate_image(a.bits_per_pixel, a.data.len())?; - (Cursor::new(a.data), true) - } else { - (Cursor::new([].as_ref()), false) - }; + let (mut alpha, has_alpha) = planes.a.map_or_else( + || (Cursor::new([].as_ref()), false), + |a| (Cursor::new(a.data), true), + ); let mut sequence = vec![]; let mut buffer: [u8; 4] = [0u8; 4]; @@ -91,15 +90,28 @@ impl ImageHandler for HeifHandler { (0..img.height()).try_for_each(|x| { let x: usize = x.try_into()?; let start: u64 = (r.stride * x).try_into()?; - red.seek(SeekFrom::Start(start))?; + + red.seek(SeekFrom::Start(start)) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))?; + (0..img.width()).try_for_each(|_| { - red.read_exact(&mut buffer[0..1])?; - green.read_exact(&mut buffer[1..2])?; - blue.read_exact(&mut buffer[2..3])?; + red.read_exact(&mut buffer[0..1]) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))?; + + green + .read_exact(&mut buffer[1..2]) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))?; + + blue.read_exact(&mut buffer[2..3]) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))?; + sequence.extend_from_slice(&buffer[..3]); if has_alpha { - alpha.read_exact(&mut buffer[3..4])?; + alpha + .read_exact(&mut buffer[3..4]) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))?; + sequence.extend_from_slice(&buffer[3..4]); } Ok::<(), Error>(()) diff --git a/crates/images/src/lib.rs b/crates/images/src/lib.rs index 2cb06268f..bef0ad284 100644 --- a/crates/images/src/lib.rs +++ b/crates/images/src/lib.rs @@ -20,42 +20,73 @@ #![forbid(unsafe_code)] #![allow(clippy::missing_errors_doc, clippy::module_name_repetitions)] +use std::{fs, path::Path}; + mod consts; mod error; -mod formatter; mod generic; +mod handler; #[cfg(feature = "heif")] mod heif; mod pdf; mod svg; +use consts::MAXIMUM_FILE_SIZE; + +// Re-exports +pub use consts::{all_compatible_extensions, ConvertableExtension}; pub use error::{Error, Result}; -pub use formatter::format_image; +pub use handler::{convert_image, format_image}; pub use image::DynamicImage; -use std::{fs, io::Read, path::Path}; pub trait ImageHandler { - fn maximum_size(&self) -> u64 - where - Self: Sized; // thanks vtables - + #[inline] fn get_data(&self, path: &Path) -> Result> where Self: Sized, { - let mut file = fs::File::open(path)?; - if file.metadata()?.len() > self.maximum_size() { - Err(Error::TooLarge) + self.validate_image(path)?; + + fs::read(path).map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path())) + } + + fn validate_image(&self, path: &Path) -> Result<()> + where + Self: Sized, + { + if fs::metadata(path) + .map_err(|e| Error::Io(e, path.to_path_buf().into_boxed_path()))? + .len() <= MAXIMUM_FILE_SIZE + { + Ok(()) } else { - let mut data = vec![]; - file.read_to_end(&mut data)?; - Ok(data) + Err(Error::TooLarge) } } - fn validate_image(&self, bits_per_pixel: u8, length: usize) -> Result<()> - where - Self: Sized; - fn handle_image(&self, path: &Path) -> Result; + + #[inline] + fn convert_image( + &self, + opposing_handler: Box, + path: &Path, + ) -> Result { + opposing_handler.handle_image(path) + } +} + +/// This takes in a width and a height, and returns a scaled width and height +/// It is scaled proportionally to the [`TARGET_PX`], so smaller images will be upscaled, +/// and larger images will be downscaled. This approach also maintains the aspect ratio of the image. +#[allow( + clippy::as_conversions, + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss +)] +#[must_use] +pub fn scale_dimensions(w: f32, h: f32, target_px: f32) -> (f32, f32) { + let sf = (target_px / (w * h)).sqrt(); + ((w * sf).round(), (h * sf).round()) } diff --git a/crates/images/src/pdf.rs b/crates/images/src/pdf.rs index 0586ab408..a6173a5e0 100644 --- a/crates/images/src/pdf.rs +++ b/crates/images/src/pdf.rs @@ -4,7 +4,7 @@ use std::{ path::{Path, PathBuf}, }; -use crate::{consts::PDF_RENDER_SIZE, Error::PdfiumBinding, ImageHandler, Result}; +use crate::{consts::PDF_RENDER_WIDTH, Error::PdfiumBinding, ImageHandler, Result}; use image::DynamicImage; use once_cell::sync::Lazy; use pdfium_render::prelude::{PdfPageRenderRotation, PdfRenderConfig, Pdfium}; @@ -61,21 +61,11 @@ static PDFIUM: Lazy> = Lazy::new(|| { pub struct PdfHandler {} impl ImageHandler for PdfHandler { - fn maximum_size(&self) -> u64 { - // Pdfium will only load the portions of the document it actually needs into memory. - u64::MAX - } - - fn validate_image(&self, _bits_per_pixel: u8, _length: usize) -> Result<()> { - Ok(()) - } - fn handle_image(&self, path: &Path) -> Result { let pdfium = PDFIUM.as_ref().ok_or(PdfiumBinding)?; let render_config = PdfRenderConfig::new() - .set_target_width(PDF_RENDER_SIZE) - .set_maximum_height(PDF_RENDER_SIZE) + .set_target_width(PDF_RENDER_WIDTH) .rotate_if_landscape(PdfPageRenderRotation::Degrees90, true); Ok(pdfium diff --git a/crates/images/src/svg.rs b/crates/images/src/svg.rs index 975a20d5f..32db7c608 100644 --- a/crates/images/src/svg.rs +++ b/crates/images/src/svg.rs @@ -1,9 +1,6 @@ use std::path::Path; -use crate::{ - consts::{SVG_MAXIMUM_FILE_SIZE, SVG_RENDER_SIZE}, - Error, ImageHandler, Result, -}; +use crate::{consts::SVG_TARGET_PX, scale_dimensions, Error, ImageHandler, Result}; use image::DynamicImage; use resvg::{ tiny_skia::{self}, @@ -11,17 +8,16 @@ use resvg::{ }; use usvg::{fontdb, TreeParsing, TreeTextToPath}; +#[derive(PartialEq, Eq)] pub struct SvgHandler {} impl ImageHandler for SvgHandler { - fn maximum_size(&self) -> u64 { - SVG_MAXIMUM_FILE_SIZE - } - - fn validate_image(&self, _bits_per_pixel: u8, _length: usize) -> Result<()> { - Ok(()) - } - + #[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::as_conversions, + clippy::cast_precision_loss + )] fn handle_image(&self, path: &Path) -> Result { let data = self.get_data(path)?; let rtree = usvg::Tree::from_data(&data, &usvg::Options::default()).map(|mut tree| { @@ -31,23 +27,21 @@ impl ImageHandler for SvgHandler { resvg::Tree::from_usvg(&tree) })?; + let (scaled_w, scaled_h) = + scale_dimensions(rtree.size.width(), rtree.size.height(), SVG_TARGET_PX); + let size = if rtree.size.width() > rtree.size.height() { - rtree.size.to_int_size().scale_to_width(SVG_RENDER_SIZE) // make this a const + rtree.size.to_int_size().scale_to_width(scaled_w as u32) } else { - rtree.size.to_int_size().scale_to_height(SVG_RENDER_SIZE) + rtree.size.to_int_size().scale_to_height(scaled_h as u32) } .ok_or(Error::InvalidLength)?; - #[allow(clippy::cast_precision_loss)] - #[allow(clippy::as_conversions)] let transform = tiny_skia::Transform::from_scale( size.width() as f32 / rtree.size.width(), size.height() as f32 / rtree.size.height(), ); - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] - #[allow(clippy::as_conversions)] let Some(mut pixmap) = tiny_skia::Pixmap::new(size.width(), size.height()) else { return Err(Error::Pixbuf); }; diff --git a/crates/media-metadata/Cargo.toml b/crates/media-metadata/Cargo.toml index c69eccb7c..ff392ef65 100644 --- a/crates/media-metadata/Cargo.toml +++ b/crates/media-metadata/Cargo.toml @@ -6,12 +6,12 @@ edition = "2021" [dependencies] kamadak-exif = "0.5.5" -thiserror = "1.0.48" +thiserror = "1.0.49" image-rs = { package = "image", version = "0.24.7" } serde = { version = "1.0.188", features = ["derive"] } serde_json = { workspace = true } specta = { workspace = true, features = ["chrono"] } -chrono = { version = "0.4.30", features = ["serde"] } +chrono = { version = "0.4.31", features = ["serde"] } rand = "0.8.5" rand_chacha = "0.3.1" diff --git a/crates/media-metadata/src/image/mod.rs b/crates/media-metadata/src/image/mod.rs index 73bb616fa..7ea58f2ea 100644 --- a/crates/media-metadata/src/image/mod.rs +++ b/crates/media-metadata/src/image/mod.rs @@ -122,3 +122,14 @@ impl ImageMetadata { Ok(data) } } + +// TODO(brxken128): more exif spec reading so we can source colour spaces correctly too +// pub enum ImageColorSpace { +// Rgb, +// RgbP, +// SRgb, +// Cmyk, +// DciP3, +// Wiz, +// Biz, +// } diff --git a/packages/client/src/core.ts b/packages/client/src/core.ts index b12978757..831e16f87 100644 --- a/packages/client/src/core.ts +++ b/packages/client/src/core.ts @@ -8,6 +8,7 @@ export type Procedures = { { key: "buildInfo", input: never, result: BuildInfo } | { key: "categories.list", input: LibraryArgs, result: { [key in Category]: number } } | { key: "files.get", input: LibraryArgs, result: { id: number; pub_id: number[]; kind: number | null; key_id: number | null; hidden: boolean | null; favorite: boolean | null; important: boolean | null; note: string | null; date_created: string | null; date_accessed: string | null; file_paths: FilePath[] } | null } | + { key: "files.getConvertableImageExtensions", input: never, result: string[] } | { key: "files.getEphemeralMediaData", input: string, result: MediaMetadata | null } | { key: "files.getMediaData", input: LibraryArgs, result: MediaMetadata } | { key: "files.getPath", input: LibraryArgs, result: string | null } | @@ -45,6 +46,7 @@ export type Procedures = { { key: "backups.backup", input: LibraryArgs, result: string } | { key: "backups.delete", input: string, result: null } | { key: "backups.restore", input: string, result: null } | + { key: "files.convertImage", input: LibraryArgs, result: null } | { key: "files.copyFiles", input: LibraryArgs, result: null } | { key: "files.cutFiles", input: LibraryArgs, result: null } | { key: "files.deleteFiles", input: LibraryArgs, result: null } | @@ -130,6 +132,10 @@ export type ColorProfile = "Normal" | "Custom" | "HDRNoOriginal" | "HDRWithOrigi export type Composite = "Unknown" | "False" | "General" | "Live" +export type ConvertImageArgs = { location_id: number; file_path_id: number; delete_src: boolean; desired_extension: ConvertableExtension; quality_percentage: number | null } + +export type ConvertableExtension = "bmp" | "dib" | "ff" | "gif" | "ico" | "jpg" | "jpeg" | "png" | "pnm" | "qoi" | "tga" | "icb" | "vda" | "vst" | "tiff" | "tif" | "heif" | "heifs" | "heic" | "heics" | "avif" | "avci" | "avcs" | "svg" | "svgz" | "pdf" + export type CreateLibraryArgs = { name: LibraryName } export type CursorOrderItem = { order: SortOrder; data: T }