diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000..1e87ec1
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,3 @@
+
+[build]
+rustflags = ["--cfg", "tokio_unstable"]
diff --git a/.gitignore b/.gitignore
index ea8c4bf..7d68e15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
/target
+/vendor
+/Cargo.lock
+.vscode/launch.json
diff --git a/Cargo.lock b/Cargo.lock
deleted file mode 100644
index e84559a..0000000
--- a/Cargo.lock
+++ /dev/null
@@ -1,1379 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "addr2line"
-version = "0.21.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
-dependencies = [
- "gimli",
-]
-
-[[package]]
-name = "adler"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-
-[[package]]
-name = "aho-corasick"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
-
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "backtrace"
-version = "0.3.69"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
-dependencies = [
- "addr2line",
- "cc",
- "cfg-if",
- "libc",
- "miniz_oxide",
- "object",
- "rustc-demangle",
-]
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
-
-[[package]]
-name = "bytes"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
-
-[[package]]
-name = "cairo-rs"
-version = "0.18.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f33613627f0dea6a731b0605101fad59ba4f193a52c96c4687728d822605a8a1"
-dependencies = [
- "bitflags 2.4.1",
- "cairo-sys-rs",
- "glib",
- "libc",
- "once_cell",
- "thiserror",
-]
-
-[[package]]
-name = "cairo-sys-rs"
-version = "0.18.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51"
-dependencies = [
- "glib-sys",
- "libc",
- "system-deps",
-]
-
-[[package]]
-name = "cc"
-version = "1.0.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "cfg-expr"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3"
-dependencies = [
- "smallvec",
- "target-lexicon",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "either"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
-
-[[package]]
-name = "env_logger"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
-dependencies = [
- "humantime",
- "is-terminal",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
-
-[[package]]
-name = "errno"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "field-offset"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
-dependencies = [
- "memoffset",
- "rustc_version",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
-dependencies = [
- "futures-core",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.39",
-]
-
-[[package]]
-name = "futures-task"
-version = "0.3.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
-
-[[package]]
-name = "futures-util"
-version = "0.3.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
-dependencies = [
- "futures-core",
- "futures-macro",
- "futures-task",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "gdk-pixbuf"
-version = "0.18.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "446f32b74d22c33b7b258d4af4ffde53c2bf96ca2e29abdf1a785fe59bd6c82c"
-dependencies = [
- "gdk-pixbuf-sys",
- "gio",
- "glib",
- "libc",
- "once_cell",
-]
-
-[[package]]
-name = "gdk-pixbuf-sys"
-version = "0.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7"
-dependencies = [
- "gio-sys",
- "glib-sys",
- "gobject-sys",
- "libc",
- "system-deps",
-]
-
-[[package]]
-name = "gdk4"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7edb019ad581f8ecf8ea8e4baa6df7c483a95b5a59be3140be6a9c3b0c632af6"
-dependencies = [
- "cairo-rs",
- "gdk-pixbuf",
- "gdk4-sys",
- "gio",
- "glib",
- "libc",
- "pango",
-]
-
-[[package]]
-name = "gdk4-sys"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbab43f332a3cf1df9974da690b5bb0e26720ed09a228178ce52175372dcfef0"
-dependencies = [
- "cairo-sys-rs",
- "gdk-pixbuf-sys",
- "gio-sys",
- "glib-sys",
- "gobject-sys",
- "libc",
- "pango-sys",
- "pkg-config",
- "system-deps",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "gimli"
-version = "0.28.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
-
-[[package]]
-name = "gio"
-version = "0.18.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-util",
- "gio-sys",
- "glib",
- "libc",
- "once_cell",
- "pin-project-lite",
- "smallvec",
- "thiserror",
-]
-
-[[package]]
-name = "gio-sys"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2"
-dependencies = [
- "glib-sys",
- "gobject-sys",
- "libc",
- "system-deps",
- "winapi",
-]
-
-[[package]]
-name = "glib"
-version = "0.18.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "951bbd7fdc5c044ede9f05170f05a3ae9479239c3afdfe2d22d537a3add15c4e"
-dependencies = [
- "bitflags 2.4.1",
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-task",
- "futures-util",
- "gio-sys",
- "glib-macros",
- "glib-sys",
- "gobject-sys",
- "libc",
- "memchr",
- "once_cell",
- "smallvec",
- "thiserror",
-]
-
-[[package]]
-name = "glib-macros"
-version = "0.18.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72793962ceece3863c2965d7f10c8786323b17c7adea75a515809fa20ab799a5"
-dependencies = [
- "heck",
- "proc-macro-crate 2.0.1",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 2.0.39",
-]
-
-[[package]]
-name = "glib-sys"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898"
-dependencies = [
- "libc",
- "system-deps",
-]
-
-[[package]]
-name = "gobject-sys"
-version = "0.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44"
-dependencies = [
- "glib-sys",
- "libc",
- "system-deps",
-]
-
-[[package]]
-name = "graphene-rs"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2228cda1505613a7a956cca69076892cfbda84fc2b7a62b94a41a272c0c401"
-dependencies = [
- "glib",
- "graphene-sys",
- "libc",
-]
-
-[[package]]
-name = "graphene-sys"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc4144cee8fc8788f2a9b73dc5f1d4e1189d1f95305c4cb7bd9c1af1cfa31f59"
-dependencies = [
- "glib-sys",
- "libc",
- "pkg-config",
- "system-deps",
-]
-
-[[package]]
-name = "gsk4"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d958e351d2f210309b32d081c832d7de0aca0b077aa10d88336c6379bd01f7e"
-dependencies = [
- "cairo-rs",
- "gdk4",
- "glib",
- "graphene-rs",
- "gsk4-sys",
- "libc",
- "pango",
-]
-
-[[package]]
-name = "gsk4-sys"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12bd9e3effea989f020e8f1ff3fa3b8c63ba93d43b899c11a118868853a56d55"
-dependencies = [
- "cairo-sys-rs",
- "gdk4-sys",
- "glib-sys",
- "gobject-sys",
- "graphene-sys",
- "libc",
- "pango-sys",
- "system-deps",
-]
-
-[[package]]
-name = "gtk4"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aeb51aa3e9728575a053e1f43543cd9992ac2477e1b186ad824fd4adfb70842"
-dependencies = [
- "cairo-rs",
- "field-offset",
- "futures-channel",
- "gdk-pixbuf",
- "gdk4",
- "gio",
- "glib",
- "graphene-rs",
- "gsk4",
- "gtk4-macros",
- "gtk4-sys",
- "libc",
- "pango",
-]
-
-[[package]]
-name = "gtk4-macros"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d57ec49cf9b657f69a05bca8027cff0a8dfd0c49e812be026fc7311f2163832f"
-dependencies = [
- "anyhow",
- "proc-macro-crate 1.3.1",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "gtk4-sys"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54d8c4aa23638ce9faa2caf7e2a27d4a1295af2155c8e8d28c4d4eeca7a65eb8"
-dependencies = [
- "cairo-sys-rs",
- "gdk-pixbuf-sys",
- "gdk4-sys",
- "gio-sys",
- "glib-sys",
- "gobject-sys",
- "graphene-sys",
- "gsk4-sys",
- "libc",
- "pango-sys",
- "system-deps",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.14.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
-
-[[package]]
-name = "heck"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-
-[[package]]
-name = "hermit-abi"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
-
-[[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
-name = "indexmap"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
-dependencies = [
- "equivalent",
- "hashbrown",
-]
-
-[[package]]
-name = "is-terminal"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
-dependencies = [
- "hermit-abi",
- "rustix",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.150"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
-
-[[package]]
-name = "lock_api"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
-dependencies = [
- "autocfg",
- "scopeguard",
-]
-
-[[package]]
-name = "log"
-version = "0.4.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
-
-[[package]]
-name = "managesieve"
-version = "0.1.1"
-dependencies = [
- "either",
- "nom",
- "serde",
- "thiserror",
-]
-
-[[package]]
-name = "memchr"
-version = "2.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
-
-[[package]]
-name = "memoffset"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
-dependencies = [
- "autocfg",
-]
-
-[[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.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
-dependencies = [
- "adler",
-]
-
-[[package]]
-name = "mio"
-version = "0.8.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
-dependencies = [
- "libc",
- "wasi",
- "windows-sys 0.48.0",
-]
-
-[[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 = "num_cpus"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "object"
-version = "0.32.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
-
-[[package]]
-name = "pango"
-version = "0.18.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4"
-dependencies = [
- "gio",
- "glib",
- "libc",
- "once_cell",
- "pango-sys",
-]
-
-[[package]]
-name = "pango-sys"
-version = "0.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5"
-dependencies = [
- "glib-sys",
- "gobject-sys",
- "libc",
- "system-deps",
-]
-
-[[package]]
-name = "parking_lot"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
-dependencies = [
- "lock_api",
- "parking_lot_core",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.9.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
-dependencies = [
- "cfg-if",
- "libc",
- "redox_syscall",
- "smallvec",
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "pkg-config"
-version = "0.3.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
-
-[[package]]
-name = "proc-macro-crate"
-version = "1.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
-dependencies = [
- "once_cell",
- "toml_edit 0.19.15",
-]
-
-[[package]]
-name = "proc-macro-crate"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a"
-dependencies = [
- "toml_datetime",
- "toml_edit 0.20.2",
-]
-
-[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.70"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.33"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
-name = "regex"
-version = "1.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
-
-[[package]]
-name = "ring"
-version = "0.17.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
-dependencies = [
- "cc",
- "getrandom",
- "libc",
- "spin",
- "untrusted",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
-
-[[package]]
-name = "rustc_version"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
-dependencies = [
- "bitflags 2.4.1",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rustls"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe6b63262c9fcac8659abfaa96cac103d28166d3ff3eaf8f412e19f3ae9e5a48"
-dependencies = [
- "log",
- "ring",
- "rustls-pki-types",
- "rustls-webpki",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "rustls-pki-types"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7673e0aa20ee4937c6aacfc12bb8341cfbf054cdd21df6bec5fd0629fe9339b"
-
-[[package]]
-name = "rustls-webpki"
-version = "0.102.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de2635c8bc2b88d367767c5de8ea1d8db9af3f6219eba28442242d9ab81d1b89"
-dependencies = [
- "ring",
- "rustls-pki-types",
- "untrusted",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-[[package]]
-name = "semver"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
-
-[[package]]
-name = "serde"
-version = "1.0.193"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.193"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.39",
-]
-
-[[package]]
-name = "serde_spanned"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "sieverman"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "env_logger",
- "gtk4",
- "log",
- "managesieve",
- "nom",
- "rustls-pki-types",
- "serde",
- "thiserror",
- "tokio",
- "tokio-rustls",
- "webpki-roots",
-]
-
-[[package]]
-name = "signal-hook-registry"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "slab"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
-
-[[package]]
-name = "socket2"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
-dependencies = [
- "libc",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "spin"
-version = "0.9.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
-
-[[package]]
-name = "subtle"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.39"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "system-deps"
-version = "6.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331"
-dependencies = [
- "cfg-expr",
- "heck",
- "pkg-config",
- "toml",
- "version-compare",
-]
-
-[[package]]
-name = "target-lexicon"
-version = "0.12.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
-
-[[package]]
-name = "termcolor"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.50"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.50"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.39",
-]
-
-[[package]]
-name = "tokio"
-version = "1.35.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c"
-dependencies = [
- "backtrace",
- "bytes",
- "libc",
- "mio",
- "num_cpus",
- "parking_lot",
- "pin-project-lite",
- "signal-hook-registry",
- "socket2",
- "tokio-macros",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "tokio-macros"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.39",
-]
-
-[[package]]
-name = "tokio-rustls"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
-dependencies = [
- "rustls",
- "rustls-pki-types",
- "tokio",
-]
-
-[[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]]
-name = "toml_datetime"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "toml_edit"
-version = "0.19.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
-dependencies = [
- "indexmap",
- "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",
- "serde",
- "serde_spanned",
- "toml_datetime",
- "winnow",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
-
-[[package]]
-name = "untrusted"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
-
-[[package]]
-name = "version-compare"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
-
-[[package]]
-name = "version_check"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "webpki-roots"
-version = "0.26.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0de2cfda980f21be5a7ed2eadb3e6fe074d56022bea2cdeb1a62eb220fc04188"
-dependencies = [
- "rustls-pki-types",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
-dependencies = [
- "windows-targets 0.52.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
-dependencies = [
- "windows_aarch64_gnullvm 0.52.0",
- "windows_aarch64_msvc 0.52.0",
- "windows_i686_gnu 0.52.0",
- "windows_i686_msvc 0.52.0",
- "windows_x86_64_gnu 0.52.0",
- "windows_x86_64_gnullvm 0.52.0",
- "windows_x86_64_msvc 0.52.0",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
-
-[[package]]
-name = "winnow"
-version = "0.5.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
diff --git a/Cargo.toml b/Cargo.toml
index 902cf08..97132c2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,11 +22,16 @@ pki-types = { package = "rustls-pki-types", version = "1.0", features = [
tokio-rustls = { version = "0.25" }
env_logger = "0.10.1"
log = "0.4.20"
-tokio = { version = "1.34.0", features = ["full"] }
+tokio = { version = "1.34.0", features = ["full", "tracing"] }
webpki-roots = "0.26.0"
nom = "7.1.3"
managesieve = { path = "../managesieve" }
anyhow = "1.0"
thiserror = "1.0"
-gtk4 = { version = "0.7.3", features = ["gnome_45"] }
+gtk4 = { version = "0.7", features = ["gnome_45", "blueprint"] }
serde = { version = "1.0.193", features = ["derive"] }
+libadwaita = { version = "0.5.3", features = ["gtk_v4_10", "v1_4"] }
+gtk-blueprint = "0.2"
+phf = "0.11"
+tracing = "0.1"
+console-subscriber = "0.2"
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..61fedea
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("cargo:rerun-if-changed=**/*.blp");
+}
\ No newline at end of file
diff --git a/gui/Sieverman.cmb b/gui/Sieverman.cmb
deleted file mode 100644
index 1305f32..0000000
--- a/gui/Sieverman.cmb
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- (1,None,"sieverman.ui","sieverman.ui",None,None,"Franz Dietrich",None,None,None,None)
-
-
-
- (1,2,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
- (1,3,"GtkBox","baseline-child","0",None,None,None,None,None,None,None,None,None),
- (1,3,"GtkBox","homogeneous","True",None,None,None,None,None,None,None,None,None),
- (1,6,"GtkSpinner","spinning","True",None,None,None,None,None,None,None,None,None),
- (1,7,"GtkLabel","label","Loading",None,None,None,None,None,None,None,None,None),
- (1,10,"GtkLabel","label","Loading…",None,None,None,None,None,None,None,None,None)
-
-
- (1,3,"GtkWidget",1,1,None,None,None,None,None,None),
- (1,3,"GtkWidget",2,2,None,1,None,None,None,None),
- (1,3,"GtkWidget",2,3,None,1,None,None,None,None),
- (1,3,"GtkWidget",2,4,None,1,None,None,None,None),
- (1,3,"GtkWidget",2,5,None,1,None,None,None,None),
- (1,3,"GtkWidget",2,6,None,1,None,None,None,None),
- (1,3,"GtkWidget",2,7,None,1,None,None,None,None),
- (1,3,"GtkWidget",2,8,None,1,None,None,None,None)
-
-
diff --git a/gui/main_window.blp b/gui/main_window.blp
new file mode 100644
index 0000000..5d8b44d
--- /dev/null
+++ b/gui/main_window.blp
@@ -0,0 +1,45 @@
+using Gtk 4.0;
+using Adw 1;
+
+Adw.ApplicationWindow window {
+ default-width: 900;
+ default-height: 500;
+
+ content: Gtk.Box {
+ orientation: vertical;
+
+ Adw.HeaderBar{
+ title-widget: Adw.WindowTitle {
+ title: "Sieverman";
+ };
+
+ Gtk.Button { label: "Neu";}
+ }
+ Gtk.Box {
+ orientation: horizontal;
+
+ vexpand: true;
+ halign: fill;
+
+ Gtk.Label{
+ label: "Log information";
+ hexpand: true;
+ }
+ Gtk.ScrolledWindow server_info {
+ width-request: 100;
+ Adw.PreferencesPage {
+ Adw.PreferencesGroup server_settings{
+ vexpand: true;
+ valign: center;
+ title: "Server Information";
+ description: "The information the server published on connection";
+ }}
+
+ }
+ }
+ Gtk.Statusbar{Gtk.Label{
+ label: "Status";
+ }}
+
+ };
+}
\ No newline at end of file
diff --git a/gui/server_info_row.blp b/gui/server_info_row.blp
new file mode 100644
index 0000000..193fc59
--- /dev/null
+++ b/gui/server_info_row.blp
@@ -0,0 +1,12 @@
+using Gtk 4.0;
+using Adw 1;
+
+
+Adw.ActionRow server_info_row {
+ title: "Server2";
+
+
+ Gtk.Label server_info_row_value{
+ label: "Stalwart";
+ }}
+
\ No newline at end of file
diff --git a/gui/sieverman.ui b/gui/sieverman.ui
deleted file mode 100644
index 5f3a1d6..0000000
--- a/gui/sieverman.ui
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/src/bin/backend/run.rs b/src/bin/backend/run.rs
index 6e511bb..adf3455 100644
--- a/src/bin/backend/run.rs
+++ b/src/bin/backend/run.rs
@@ -1,36 +1,29 @@
-use log::{info, trace};
use sieverman::ConnectionInfo;
+use tracing::info;
use crate::protocol::BackToFront;
pub(crate) async fn run(
to_frontend_tx: tokio::sync::mpsc::Sender,
) -> anyhow::Result<()> {
- trace!("Starting up sieverman…");
+ info!("Starting up sieverman…");
+ info!("Creating connection info");
let info = ConnectionInfo::new("teilgedanken.de", 4190);
- let mut connected = info.connect().await.unwrap();
- info!("connected to the server");
- loop {
- match connected.read_introduction().await {
- Ok(sieverman::IsComplete::Yes(c)) => {
- connected = c;
- break;
- }
- Ok(sieverman::IsComplete::No(c)) => {
- trace!("Incomplete data waiting for some time…");
- connected = c
- }
- Err(e) => return Err(anyhow::anyhow!("something went wrong: {}", e)),
- };
- tokio::time::sleep(std::time::Duration::from_millis(100)).await;
- connected.log_buffer().await;
- }
- trace!("Fully read the introduction:");
- connected.log_buffer().await;
- connected.log_server_settings().await;
+ info!("connecting…");
+ let future_info = info.connect();
+ info!("waiting for the connection to be established");
+ let mut connected = match future_info.await {
+ Ok(v) => v,
+ Err(e) => {
+ info!("Failed to connect: {:?}", e);
+ panic!("Something went wrong");
+ }
+ };
+
+ info!("Fully read the introduction:");
to_frontend_tx
.send(BackToFront::ServerConnected(
- connected.get_server_capabilities(),
+ connected.get_server_capabilities().clone(),
))
.await
.unwrap();
diff --git a/src/bin/gui/main_window.rs b/src/bin/gui/main_window.rs
index cdb5e5c..16f175f 100644
--- a/src/bin/gui/main_window.rs
+++ b/src/bin/gui/main_window.rs
@@ -1,11 +1,14 @@
-use std::{cell::RefCell, fmt::Display, rc::Rc};
+use std::{cell::RefCell, rc::Rc};
+use crate::__COMPILED_BLUEPRINT_MAP__;
use gtk4::{
glib,
- prelude::{ApplicationExt, BoxExt, GtkWindowExt, WidgetExt},
- Application, ApplicationWindow, Builder, Label,
+ prelude::{ApplicationExt, GtkWindowExt},
+ Application,
};
-use log::trace;
+use gtk_blueprint::get_blp;
+use libadwaita::prelude::{PreferencesGroupExt, PreferencesRowExt};
+use tracing::trace;
use crate::protocol::BackToFront;
@@ -25,50 +28,30 @@ fn build_ui(
app: >k4::Application,
from_backend_rx: Rc>>>,
) {
- let action_content_status = gtk4::Box::builder()
- .orientation(gtk4::Orientation::Vertical)
- .spacing(5)
- .build();
- let action = gtk4::ActionBar::new();
- let status = gtk4::Statusbar::new();
- let main_log_server_info = gtk4::Box::builder()
- .orientation(gtk4::Orientation::Horizontal)
- .hexpand(true)
- .vexpand(true)
- .halign(gtk4::Align::Fill)
- .build();
- action_content_status.append(&action);
- action_content_status.append(&main_log_server_info);
- action_content_status.append(&status);
- let log = gtk4::Label::builder().label("Log").hexpand(true).build();
- let server_info_content = gtk4::Label::builder().label("Server Info").build();
- let server_info_container = gtk4::ScrolledWindow::builder()
- .child(&server_info_content)
- .width_request(400)
- .build();
- main_log_server_info.append(&log);
- main_log_server_info.append(&server_info_container);
- let main_window = gtk4::ApplicationWindow::builder()
- .application(app)
- .title("Sieverman")
- .height_request(400)
- .width_request(400)
- .child(&action_content_status)
- .build();
- main_window.present();
-
- let server_info = Rc::new(RefCell::new(server_info_content));
+ let builder = gtk4::Builder::new();
+ builder
+ .add_from_string(get_blp!("gui/main_window.blp"))
+ .expect("Failed to parse blueprint");
+ let main_window = builder
+ .object::("window")
+ .unwrap();
+ let prefrences_group = builder
+ .object::("server_settings")
+ .unwrap();
+ main_window.set_application(Some(app));
let future = {
let mut data_event_receiver = from_backend_rx.take().expect("data_event_reciver");
async move {
while let Some(event) = data_event_receiver.recv().await {
- trace!("data event: {:?}", event);
match event {
- BackToFront::ServerConnected(message) => {
- server_info
- .borrow_mut()
- .set_label(&format!("{:#?}", message));
+ BackToFront::ServerConnected(caps) => {
+ prefrences_group.add(&row_in_settings("Greeting", &caps.implementation));
+ prefrences_group
+ .add(&row_in_settings("Authentication", &caps.sasl.join(",")));
+ prefrences_group
+ .add(&row_in_settings("Starttls", &caps.starttls.to_string()));
+ prefrences_group.add(&row_in_settings("Version", &caps.version));
}
}
}
@@ -78,4 +61,22 @@ fn build_ui(
let c = glib::MainContext::default();
c.spawn_local(future);
main_window.present();
+ trace!("Window is visible");
+}
+
+fn row_in_settings(name: &str, value: &str) -> libadwaita::ActionRow {
+ let builder = gtk4::Builder::new();
+ builder
+ .add_from_string(get_blp!("gui/server_info_row.blp"))
+ .expect("Failed to parse blueprint");
+
+ let row = builder
+ .object::("server_info_row")
+ .unwrap();
+ row.set_title(name);
+ let label = builder
+ .object::("server_info_row_value")
+ .unwrap();
+ label.set_label(value);
+ row
}
diff --git a/src/bin/old/bluep_test.rs b/src/bin/old/bluep_test.rs
new file mode 100644
index 0000000..525f6d3
--- /dev/null
+++ b/src/bin/old/bluep_test.rs
@@ -0,0 +1,48 @@
+use gtk4::prelude::{ApplicationExt, ApplicationExtManual, GtkWindowExt};
+// We're using gtk-builder feature here
+use gtk_blueprint::get_blp;
+use libadwaita::prelude::PreferencesGroupExt;
+
+gtk_blueprint::gen_blp_map!("gui");
+fn main() {
+ gtk4::init().expect("GTK initialization failed");
+ libadwaita::init().expect("Adwaita initialization failed");
+
+ // Create app
+ let application = gtk4::Application::builder()
+ .application_id("de.teilgedanken.sieverman")
+ .build();
+ // Init app window and show it
+ application.connect_activate(|app| {
+ // You also can parse blueprint with Parser::parse
+ // and then use it in gtk4::Builder
+ let builder = gtk4::Builder::new();
+ builder
+ .add_from_string(get_blp!("gui/main_window.blp"))
+ .expect("Failed to parse blueprint");
+
+ let window = builder
+ .object::("window")
+ .unwrap();
+
+ let settings: libadwaita::PreferencesGroup = builder
+ .object("server_settings")
+ .expect("get server settings");
+ for _ in 0..5 {
+ let builder = gtk4::Builder::new();
+ builder
+ .add_from_string(get_blp!("gui/headerbar.blp"))
+ .expect("Failed to parse blueprint");
+ let widget: libadwaita::PreferencesRow = builder
+ .object("server_info_row")
+ .expect("Couldn't get widget");
+ settings.add(&widget);
+ }
+
+ window.set_application(Some(app));
+ window.present();
+ });
+
+ // Run app
+ application.run();
+}
diff --git a/src/bin/nomer1.rs b/src/bin/old/nomer1.rs
similarity index 98%
rename from src/bin/nomer1.rs
rename to src/bin/old/nomer1.rs
index 3107304..c9db9a6 100644
--- a/src/bin/nomer1.rs
+++ b/src/bin/old/nomer1.rs
@@ -1,4 +1,3 @@
-use log::info;
use nom::branch::alt;
use nom::bytes::complete::is_not;
use nom::character::is_space;
@@ -12,6 +11,7 @@ use nom::{character, number};
use sieverman::parser::parse_server_config;
use sieverman::{Methods, ServerSettings};
use std::error::Error;
+use tracing::info;
fn main() -> Result<(), Box> {
env_logger::init();
diff --git a/src/bin/sieverman_versuch1.rs b/src/bin/old/sieverman_versuch1.rs
similarity index 99%
rename from src/bin/sieverman_versuch1.rs
rename to src/bin/old/sieverman_versuch1.rs
index 8b97dd6..afc4f7e 100644
--- a/src/bin/sieverman_versuch1.rs
+++ b/src/bin/old/sieverman_versuch1.rs
@@ -9,7 +9,6 @@
/// that is sensible outside of example code.
use std::sync::Arc;
-use log::{error, info, trace};
use managesieve::{Capability, MSResult, Response};
use nom::{error::ParseError, IResult};
use sieverman::parser::parse_server_config;
@@ -23,6 +22,7 @@ use tokio_rustls::{
rustls::{ClientConfig, KeyLogFile, RootCertStore},
TlsConnector,
};
+use tracing::{error, info, trace};
#[macro_export]
macro_rules! parse_response {
diff --git a/src/bin/protocol/mod.rs b/src/bin/protocol/mod.rs
index b4b1864..18c472f 100644
--- a/src/bin/protocol/mod.rs
+++ b/src/bin/protocol/mod.rs
@@ -1,7 +1,7 @@
-use managesieve::Capability;
+use managesieve::Capabilities;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum BackToFront {
- ServerConnected(Vec),
+ ServerConnected(Capabilities),
}
diff --git a/src/bin/sieverman.rs b/src/bin/sieverman.rs
index b254c34..912f954 100644
--- a/src/bin/sieverman.rs
+++ b/src/bin/sieverman.rs
@@ -1,15 +1,27 @@
mod backend;
mod gui;
pub mod protocol;
-use std::{cell::RefCell, rc::Rc, thread};
+use std::{cell::RefCell, rc::Rc, thread, time::Duration};
use gtk4::{glib, prelude::ApplicationExtManual as _};
+use tracing::{info, trace};
+
+gtk_blueprint::gen_blp_map!("gui");
fn main() -> glib::ExitCode {
- env_logger::init();
+ console_subscriber::ConsoleLayer::builder()
+ // set how long the console will retain data from completed tasks
+ .retention(Duration::from_secs(60))
+ // set the address the server is bound to
+ .server_addr(([127, 0, 0, 1], 6669))
+ .init();
+
gtk4::init().expect("Failed to initialize GTK");
+ libadwaita::init().expect("Adwaita initialization failed");
+
let (to_frontent_tx, from_backend_rx) = tokio::sync::mpsc::channel(5);
let _handle = thread::spawn(move || {
+ info!("Running Backend");
tokio::runtime::Builder::new_current_thread()
.enable_io()
.enable_time()
@@ -21,5 +33,8 @@ fn main() -> glib::ExitCode {
let app = gui::main_window::get_app(Rc::new(RefCell::new(Some(from_backend_rx))));
- app.run()
+ let res = app.run();
+ trace!("End");
+
+ res
}
diff --git a/src/lib.rs b/src/lib.rs
index 7510941..991ed9f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,20 +1,18 @@
-use std::{any, net::SocketAddr, sync::Arc, time::Duration};
+use std::{sync::Arc, time::Duration};
-use log::{error, info, trace};
-use managesieve::Capability;
-use std::net::ToSocketAddrs;
+use managesieve::Capabilities;
use thiserror::Error;
use tokio::{
- io::{split, AsyncBufReadExt, BufReader, ReadHalf, WriteHalf},
+ io::{split, AsyncBufReadExt, BufReader, WriteHalf},
net::TcpStream,
sync::Mutex,
- task::JoinHandle,
};
use tokio_rustls::{
client::TlsStream,
rustls::{ClientConfig, KeyLogFile, RootCertStore},
TlsConnector,
};
+use tracing::{error, info, trace};
pub mod parser;
@@ -32,6 +30,7 @@ impl ConnectionInfo {
}
}
pub async fn connect(self) -> Result {
+ info!("connecting to the server");
trace!("Building Cert Store");
let mut root_store = RootCertStore::empty();
root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
@@ -48,11 +47,11 @@ impl ConnectionInfo {
let domain = pki_types::ServerName::try_from(self.domain.clone())?.to_owned();
trace!("Attach the connector");
let stream = connector.connect(domain, stream).await?;
- let (reader, mut writer) = split(stream);
+ let (reader, writer) = split(stream);
let buffer = Arc::new(Mutex::new(String::new()));
let spawned_buffer = buffer.clone();
- let join_handle = tokio::spawn(async move {
+ let _join_handle = tokio::spawn(async move {
let mut buf = String::new();
let mut reader = BufReader::new(reader);
loop {
@@ -67,13 +66,36 @@ impl ConnectionInfo {
}
buf.clear();
};
+ tokio::time::sleep(Duration::from_millis(50)).await;
}
});
+
+ let caps = loop {
+ let mut buf = buffer.lock().await;
+ trace!("reading new input:\n{}", buf);
+ match managesieve::response_capability(&buf.to_string()) {
+ Ok((rest, caps, resp)) => match resp.tag {
+ managesieve::OkNoBye::Ok => {
+ buf.clear();
+ buf.push_str(rest);
+ info!("Read the introduction");
+ break caps;
+ }
+ managesieve::OkNoBye::No | managesieve::OkNoBye::Bye => {
+ trace!("Connection closed!");
+ //panic!("Invalid Response")
+ }
+ },
+ Err(e) => trace!("(temporary) error: {}", e),
+ }
+ tokio::time::sleep(Duration::from_millis(50)).await;
+ };
+ trace!("Capabilities read: {:#?}", &caps);
Ok(ConnectionConnected {
info: self,
- writer: Arc::new(writer), //server_settings: todo!(),
+ writer: Arc::new(writer),
buffer,
- server_settings: Vec::new(), //join_handle: Arc::new(join_handle),
+ server_settings: caps,
})
}
}
@@ -85,7 +107,7 @@ pub struct ConnectionConnected {
writer: Arc>>,
buffer: Arc>,
//pub join_handle: Arc>,
- server_settings: Vec,
+ server_settings: Capabilities,
}
#[derive(Error, Debug)]
@@ -95,7 +117,7 @@ pub enum ReadError {
#[error("The data the server responded was invalid")]
InvalidResponse(#[source] managesieve::Error),
}
-
+#[derive(Debug)]
pub enum IsComplete {
Yes(T),
No(T),
@@ -103,11 +125,12 @@ pub enum IsComplete {
impl ConnectionConnected {
pub async fn log_buffer(&self) {
- trace!("Buffer is: \n{}", self.buffer.lock().await)
+ info!("Buffer is: \n{}", self.buffer.lock().await)
}
pub async fn log_server_settings(&self) {
- trace!("Serversettings:\n{:?}", self.server_settings)
+ info!("Serversettings:\n{:?}", self.server_settings)
}
+ #[tracing::instrument(name = "gettin the intro")]
pub async fn read_introduction(self) -> Result, anyhow::Error> {
let Self {
info,
@@ -116,12 +139,11 @@ impl ConnectionConnected {
buffer,
server_settings,
} = self;
- tokio::time::sleep(Duration::from_millis(500)).await;
+ tokio::time::sleep(Duration::from_millis(50)).await;
let mut bf = buffer.lock().await;
- let bf_str = bf.clone();
- match managesieve::response_capability(&bf_str) {
+ let response = match managesieve::response_capability(&bf.to_string()) {
Ok((rest, capability, response)) => {
- trace!("{:?}", response);
+ info!("Successfully read the introduction {:?}", response);
bf.clear();
bf.push_str(rest);
drop(bf);
@@ -132,12 +154,15 @@ impl ConnectionConnected {
server_settings: capability,
}))
}
- Err(managesieve::Error::IncompleteResponse) => Ok(IsComplete::No(Self {
- info,
- writer,
- buffer: buffer.clone(),
- server_settings,
- })),
+ Err(managesieve::Error::IncompleteResponse) => {
+ trace!("incomplete introduction");
+ Ok(IsComplete::No(Self {
+ info,
+ writer,
+ buffer: buffer.clone(),
+ server_settings,
+ }))
+ }
Err(managesieve::Error::InvalidResponse) => {
error!("invalid response");
Err(managesieve::Error::InvalidResponse)?
@@ -146,18 +171,20 @@ impl ConnectionConnected {
error!("invalid input");
Err(managesieve::Error::InvalidResponse)?
}
- }
- }
- pub fn get_greeting(&self) -> Option {
- for c in self.server_settings.iter() {
- if let Capability::Implementation(s) = c {
- return Some(s.clone());
+ Err(managesieve::Error::MissingLine(line)) => {
+ error!("a capability line was missing: {:?}", line);
+ Err(managesieve::Error::InvalidResponse)?
}
- }
- None
+ };
+
+ response
}
- pub fn get_server_capabilities(&self) -> Vec {
- self.server_settings.clone()
+
+ pub fn get_greeting(&self) -> String {
+ self.server_settings.implementation.to_string()
+ }
+ pub fn get_server_capabilities(&self) -> &Capabilities {
+ &self.server_settings
}
}
diff --git a/src/parser/server_config.rs b/src/parser/server_config.rs
index 929de54..fe591ee 100644
--- a/src/parser/server_config.rs
+++ b/src/parser/server_config.rs
@@ -1,4 +1,3 @@
-use log::{info, trace};
use nom::{
branch::alt,
bytes::complete::is_not,
@@ -11,6 +10,7 @@ use nom::{
sequence::preceded,
IResult,
};
+use tracing::trace;
use crate::{parser::utils::key_value, Methods, ServerSettings};