diff --git a/Cargo.lock b/Cargo.lock index d485ad8..7cf55f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,7 +160,7 @@ dependencies = [ "anyhow", "arrayvec", "log", - "nom 8.0.0", + "nom", "num-rational", "v_frame", ] @@ -174,6 +174,28 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "aws-lc-rs" +version = "1.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "base64" version = "0.22.1" @@ -243,12 +265,24 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.42" @@ -261,12 +295,31 @@ dependencies = [ "windows-link", ] +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "compression-codecs" version = "0.4.33" @@ -307,6 +360,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -455,6 +518,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -518,17 +587,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "eventsource-stream" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" -dependencies = [ - "futures-core", - "nom 7.1.3", - "pin-project-lite", -] - [[package]] name = "exr" version = "1.74.0" @@ -601,21 +659,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -625,6 +668,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-channel" version = "0.3.31" @@ -669,12 +718,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - [[package]] name = "futures-util" version = "0.3.31" @@ -699,8 +742,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -710,9 +755,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -738,7 +785,6 @@ dependencies = [ "image", "indicatif", "reqwest", - "reqwest-eventsource", "serde", "serde_json", "serde_with", @@ -874,22 +920,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.18" @@ -1166,6 +1196,28 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.34" @@ -1250,6 +1302,12 @@ dependencies = [ "imgref", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "maybe-rayon" version = "0.1.1" @@ -1272,12 +1330,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1309,39 +1361,12 @@ dependencies = [ "pxfm", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "nom" version = "8.0.0" @@ -1428,49 +1453,11 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "parking_lot" @@ -1525,12 +1512,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - [[package]] name = "png" version = "0.18.0" @@ -1626,6 +1607,62 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.42" @@ -1771,11 +1808,10 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.24" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" dependencies = [ - "async-compression", "base64", "bytes", "encoding_rs", @@ -1787,21 +1823,21 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", - "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -1813,22 +1849,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "reqwest-eventsource" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632c55746dbb44275691640e7b40c907c16a2dc1a5842aa98aaec90da6ec6bde" -dependencies = [ - "eventsource-stream", - "futures-core", - "futures-timer", - "mime", - "nom 7.1.3", - "pin-project-lite", - "reqwest", - "thiserror 1.0.69", -] - [[package]] name = "rgb" version = "0.8.52" @@ -1849,6 +1869,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustix" version = "1.1.2" @@ -1868,6 +1894,7 @@ version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "aws-lc-rs", "once_cell", "rustls-pki-types", "rustls-webpki", @@ -1875,21 +1902,62 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pki-types" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" dependencies = [ + "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -1907,6 +1975,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.28" @@ -1948,12 +2025,12 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.11.1" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -2012,18 +2089,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.16.1" @@ -2178,7 +2243,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -2309,6 +2374,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.49.0" @@ -2337,16 +2417,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" @@ -2402,13 +2472,18 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ + "async-compression", "bitflags", "bytes", + "futures-core", "futures-util", "http", "http-body", + "http-body-util", "iri-string", "pin-project-lite", + "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", @@ -2549,10 +2624,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] -name = "vcpkg" -version = "0.2.15" +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] [[package]] name = "want" @@ -2669,12 +2748,30 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "weezl" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "windows-core" version = "0.62.2" @@ -2745,6 +2842,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -2772,6 +2878,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -2805,6 +2926,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -2817,6 +2944,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -2829,6 +2962,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2853,6 +2992,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -2865,6 +3010,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -2877,6 +3028,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -2889,6 +3046,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 908a62b..b31abb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,7 @@ edition = "2024" [dependencies] deadqueue = "0.2" -# reqwest-eventsource is incompatible with reqwest 0.13. Only update after the -# a new version of reqwest-eventsource is published. -reqwest = { version = "0.12", features = ["json", "gzip"] } -reqwest-eventsource = "0.6" +reqwest = { version = "0.13", features = ["json", "gzip", "stream"] } serde = { version = "1", features = ["derive"] } serde_json = { version = "1" } serde_with = { version = "3.16", features = ["base64"] } diff --git a/examples/generate-content-stream.rs b/examples/generate-content-stream.rs new file mode 100644 index 0000000..7770fe7 --- /dev/null +++ b/examples/generate-content-stream.rs @@ -0,0 +1,32 @@ +use std::{env, error::Error}; + +use google_genai::prelude::{Content, GeminiClient, GenerateContentRequest, Role}; +use tokio_stream::StreamExt; + +#[tokio::main] +async fn main() -> Result<(), Box> { + tracing_subscriber::fmt().init(); + let _ = dotenvy::dotenv(); + + let api_key = env::var("GEMINI_API_KEY")?; + let gemini_client = GeminiClient::new(api_key); + let prompt = vec![ + Content::builder() + .role(Role::User) + .add_text_part("What is the airspeed of an unladen swallow?") + .build(), + ]; + + let request = GenerateContentRequest::builder().contents(prompt).build(); + let mut response_stream = gemini_client + .stream_generate_content(&request, "gemini-3-pro-preview") + .await?; + + while let Some(content) = response_stream.next().await { + match content { + Ok(response) => println!("Response: {:?}", response.candidates[0].get_text().unwrap()), + Err(err) => eprintln!("Error: {}", err), + } + } + Ok(()) +} diff --git a/examples/sse.rs b/examples/raw_sse.rs similarity index 100% rename from examples/sse.rs rename to examples/raw_sse.rs diff --git a/src/client.rs b/src/client.rs index da86308..aeacaca 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,22 +1,14 @@ -use crate::error::Result as GeminiResult; -use std::sync::Arc; +use crate::dialogue::Message; +use crate::error::{Error as GeminiError, Result as GeminiResult}; +use crate::network::event_source::{EventSource, ServerSentEvent}; +use crate::prelude::*; +use crate::types::{PredictImageRequest, PredictImageResponse, Role}; + use std::vec; use tokio_stream::{Stream, StreamExt}; - -use deadqueue::unlimited::Queue; -use reqwest_eventsource::{Event, EventSource}; +use tokio_util::codec::LinesCodecError; use tracing::error; -use crate::dialogue::Message; -use crate::error::{Error, Result}; -use crate::prelude::Part; -use crate::prelude::{ - Candidate, Content, CountTokensRequest, CountTokensResponse, GenerateContentRequest, - GenerateContentResponse, GenerateContentResponseResult, TextEmbeddingRequest, - TextEmbeddingResponse, -}; -use crate::types::{PredictImageRequest, PredictImageResponse, Role}; - pub static AUTH_SCOPE: &[&str] = &["https://www.googleapis.com/auth/cloud-platform"]; #[derive(Clone, Debug)] @@ -36,126 +28,43 @@ impl GeminiClient { } } - pub async fn generate_content_stream( - &self, - request: &GenerateContentRequest, - model: &str, - ) -> Result>> { - let endpoint_url = format!( - "https://generativelanguage.googleapis.com/v1beta/models/{model}:streamGenerateContent?alt=sse" - ); - let client = self.client.clone(); - let request = request.clone(); - let req = client - .post(&endpoint_url) - .header("x-goog-api-key", &self.api_key) - .json(&request); - - let event_source = EventSource::new(req).unwrap(); - - let mapped = event_source.filter_map(|event| { - let event = match event { - Ok(event) => event, - Err(reqwest_eventsource::Error::StreamEnded) => { - return Some(Err(Error::EventSourceClosedError)); - } - Err(e) => return Some(Err(e.into())), - }; - - let Event::Message(event_message) = event else { - return None; - }; - - let gemini_response: GenerateContentResponse = - match serde_json::from_str(&event_message.data) { - Ok(gemini_response) => gemini_response, - Err(e) => return Some(Err(e.into())), - }; - - let gemini_response = match gemini_response.into_result() { - Ok(gemini_response) => gemini_response, - Err(e) => return Some(Err(e)), - }; - - Some(Ok(gemini_response)) - }); - Ok(mapped) - } - pub async fn stream_generate_content( &self, request: &GenerateContentRequest, model: &str, - ) -> Arc>>> { - let queue = Arc::new(Queue::>>::new()); - - // Clone the queue and other necessary data to move into the async block. - let cloned_queue = queue.clone(); + ) -> GeminiResult>> { let endpoint_url = format!( "https://generativelanguage.googleapis.com/v1beta/models/{model}:streamGenerateContent?alt=sse" ); let client = self.client.clone(); let request = request.clone(); + Ok(client + .post(&endpoint_url) + .header("x-goog-api-key", &self.api_key) + .json(&request) + .send() + .await? + .event_stream() + .filter_map(Self::parse_event)) + } - let api_key = self.api_key.clone(); - // Start a thread to run the request in the background. - tokio::spawn(async move { - let req = client - .post(&endpoint_url) - .header("x-goog-api-key", api_key) - .json(&request); + fn parse_event( + event_result: std::result::Result, + ) -> Option> { + let data = event_result.map_err(Into::::into).ok()?.data?; - let mut event_source = match EventSource::new(req) { - Ok(event_source) => event_source, - Err(e) => { - cloned_queue.push(Some(Err(e.into()))); - return; - } - }; - while let Some(event) = event_source.next().await { - match event { - Ok(event) => { - if let Event::Message(event) = event { - let response: serde_json::error::Result = - serde_json::from_str(&event.data); - - match response { - Ok(response) => { - let result = response.into_result(); - let finished = match &result { - Ok(result) => result.candidates[0].finish_reason.is_some(), - Err(_) => true, - }; - cloned_queue.push(Some(result)); - if finished { - break; - } - } - Err(_) => { - tracing::error!("Error parsing message: {}", event.data); - break; - } - } - } - } - Err(e) => { - tracing::error!("Error in event source: {:?}", e); - break; - } - } - } - cloned_queue.push(None); - }); - - // Return the queue that will receive the responses. - queue + Some( + serde_json::from_str::(&data) + .map_err(Into::into) + .and_then(|resp| resp.into_result()), + ) } pub async fn generate_content( &self, request: &GenerateContentRequest, model: &str, - ) -> Result { + ) -> GeminiResult { let endpoint_url: String = format!( "https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent", ); @@ -175,10 +84,10 @@ impl GeminiClient { if let Ok(gemini_error) = serde_json::from_str::(&txt_json) { - return Err(Error::GeminiError(gemini_error)); + return Err(GeminiError::GeminiError(gemini_error)); } // Fallback if parsing fails, though it should ideally match GeminiApiError - return Err(Error::GenericApiError { + return Err(GeminiError::GenericApiError { status: status.as_u16(), body: txt_json, }); @@ -194,7 +103,11 @@ impl GeminiClient { } /// Prompts a conversation to the model. - pub async fn prompt_conversation(&self, messages: &[Message], model: &str) -> Result { + pub async fn prompt_conversation( + &self, + messages: &[Message], + model: &str, + ) -> GeminiResult { let request = GenerateContentRequest { contents: messages .iter() @@ -216,7 +129,7 @@ impl GeminiClient { match candidates.pop() { Some(text) => Ok(Message::new(Role::Model, &text)), - None => Err(Error::NoCandidatesError), + None => Err(GeminiError::NoCandidatesError), } } @@ -232,7 +145,7 @@ impl GeminiClient { &self, request: &TextEmbeddingRequest, model: &str, - ) -> Result { + ) -> GeminiResult { let endpoint_url = format!("https://generativelanguage.googleapis.com/v1beta/models/{model}:predict"); let resp = self @@ -251,7 +164,7 @@ impl GeminiClient { &self, request: &CountTokensRequest, model: &str, - ) -> Result { + ) -> GeminiResult { let endpoint_url = format!("https://generativelanguage.googleapis.com/v1beta/models/{model}:countTokens"); let resp = self @@ -271,7 +184,7 @@ impl GeminiClient { &self, request: &PredictImageRequest, model: &str, - ) -> Result { + ) -> GeminiResult { let endpoint_url = format!("https://generativelanguage.googleapis.com/v1beta/models/{model}:predict"); @@ -290,9 +203,9 @@ impl GeminiClient { if let Ok(gemini_error) = serde_json::from_str::(&txt_json) { - return Err(Error::GeminiError(gemini_error)); + return Err(GeminiError::GeminiError(gemini_error)); } - return Err(Error::GenericApiError { + return Err(GeminiError::GenericApiError { status: status.as_u16(), body: txt_json, }); diff --git a/src/error.rs b/src/error.rs index fe05b60..09d05cc 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use reqwest_eventsource::CannotCloneRequestError; +use tokio_util::codec::LinesCodecError; use crate::types; @@ -14,8 +14,7 @@ pub enum Error { VertexError(types::VertexApiError), GeminiError(types::GeminiApiError), NoCandidatesError, - CannotCloneRequestError(CannotCloneRequestError), - EventSourceError(Box), + EventSourceError(LinesCodecError), EventSourceClosedError, GenericApiError { status: u16, body: String }, } @@ -35,9 +34,6 @@ impl Display for Error { Error::NoCandidatesError => { write!(f, "No candidates returned for the prompt") } - Error::CannotCloneRequestError(e) => { - write!(f, "Cannot clone request: {e}") - } Error::EventSourceError(e) => { write!(f, "EventSourrce Error: {e}") } @@ -83,14 +79,8 @@ impl From for Error { } } -impl From for Error { - fn from(e: CannotCloneRequestError) -> Self { - Error::CannotCloneRequestError(e) - } -} - -impl From for Error { - fn from(e: reqwest_eventsource::Error) -> Self { - Error::EventSourceError(Box::new(e)) +impl From for Error { + fn from(e: LinesCodecError) -> Self { + Error::EventSourceError(e) } } diff --git a/src/network/event_source.rs b/src/network/event_source.rs index c835f36..eae9932 100644 --- a/src/network/event_source.rs +++ b/src/network/event_source.rs @@ -35,6 +35,12 @@ pub struct ServerSentEventsCodec { next: ServerSentEvent, } +impl Default for ServerSentEventsCodec { + fn default() -> Self { + Self::new() + } +} + impl ServerSentEventsCodec { pub fn new() -> Self { Self {