Initial commit uwu

This commit is contained in:
~erin 2021-12-29 16:04:00 -05:00
commit 03ef223108
No known key found for this signature in database
GPG Key ID: DA70E064A8C70F44
9 changed files with 1549 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

887
Cargo.lock generated Normal file
View File

@ -0,0 +1,887 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"serde",
"time",
"winapi",
]
[[package]]
name = "clap"
version = "3.0.0-rc.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7843ae7a539bef687e018bf9edf7e87728024b29d02b0f8409726be8880ae1a"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"indexmap",
"lazy_static",
"os_str_bytes",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.0.0-rc.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae3cc2f259ea636871f5da15b0ac033f1821d7a5506c3d1bfbdde201f14c803"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "confy"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2913470204e9e8498a0f31f17f90a0de801ae92c8c5ac18c49af4819e6786697"
dependencies = [
"directories",
"serde",
"toml",
]
[[package]]
name = "console"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
dependencies = [
"encode_unicode",
"libc",
"once_cell",
"regex",
"terminal_size",
"unicode-width",
"winapi",
]
[[package]]
name = "crc32fast"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if 1.0.0",
"lazy_static",
]
[[package]]
name = "dialoguer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61579ada4ec0c6031cfac3f86fdba0d195a7ebeb5e36693bd53cb5999a25beeb"
dependencies = [
"console",
"lazy_static",
"tempfile",
"zeroize",
]
[[package]]
name = "directories"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
dependencies = [
"cfg-if 0.1.10",
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "exitcode"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193"
[[package]]
name = "form_urlencoded"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
]
[[package]]
name = "fs2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "itoa"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
[[package]]
name = "lock_api"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "matches"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]]
name = "os_str_bytes"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
dependencies = [
"memchr",
]
[[package]]
name = "paris"
version = "1.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a25b44bc50356452ab4fdcdd6d6b0f70eddc4f9fd16c9ba142f69e74fb195165"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "ppv-lite86"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
[[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",
"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.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
dependencies = [
"getrandom",
"redox_syscall",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "ryu"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha1"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
[[package]]
name = "sled"
version = "0.34.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
dependencies = [
"crc32fast",
"crossbeam-epoch",
"crossbeam-utils",
"fs2",
"fxhash",
"libc",
"log",
"parking_lot",
"zstd",
]
[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if 1.0.0",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "terminal_size"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "textwrap"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
]
[[package]]
name = "tinymark"
version = "0.2.0"
dependencies = [
"bincode",
"chrono",
"clap",
"confy",
"dialoguer",
"exitcode",
"paris",
"serde",
"serde_derive",
"serde_json",
"sled",
"url",
"uuid",
]
[[package]]
name = "tinyvec"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "unicode-bidi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
[[package]]
name = "unicode-normalization"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "url"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
dependencies = [
"form_urlencoded",
"idna",
"matches",
"percent-encoding",
"serde",
]
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"serde",
"sha1",
]
[[package]]
name = "version_check"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[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.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
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 = "zeroize"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619"
[[package]]
name = "zstd"
version = "0.9.1+zstd.1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "538b8347df9257b7fbce37677ef7535c00a3c7bf1f81023cc328ed7fe4b41de8"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "4.1.2+zstd.1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb4cfe2f6e6d35c5d27ecd9d256c4b6f7933c4895654917460ec56c29336cc1"
dependencies = [
"libc",
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "1.6.2+zstd.1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f"
dependencies = [
"cc",
"libc",
]

35
Cargo.toml Normal file
View File

@ -0,0 +1,35 @@
[package]
name = "tinymark"
description = "A tiny bookmark manager"
version = "0.2.0"
edition = "2021"
authors = ["Erin Nova <contact@the-system.eu.org>"]
license = "CNPLv7+"
readme = "README.md"
homepage = "https://git.lavender.software/erin/tinymark"
repository = "https://git.lavender.software/erin/tinymark"
keywords = ["cli", "bookmark", "tiny"]
categories = ["command-line-utilities"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release]
opt-level = "z" # Optimize for size.
lto = true
codegen-units = 1
panic = "abort"
[dependencies]
url = { version = "2.2.2", features = ["serde"] }
uuid = { version = "0.8.2", features = ["v5", "serde"] }
sled = { version = "0.34.7", features = ["compression"] }
bincode = "1.3.3"
paris = { version = "1.5", features = ["macros"] }
serde = { version = "1.0", features = ["derive"] }
clap = { version = "3.0.0-rc.9", features = ["derive"] }
exitcode = "1.1.2"
serde_json = "1.0"
chrono = { version = "0.4", features = ["serde"] }
dialoguer = "0.9.0"
confy = "0.4"
serde_derive = "1.0.132"

36
README.md Normal file
View File

@ -0,0 +1,36 @@
# TinyMark
A tiny bookmark manager.
## About
This is just a small tool I've made for myself to organize my bookmarks in a simple way,
without needing a browser.
It doesn't support icons or much of anything else right now.
A configuration file will be stored in `~/.config/tinymark/tinymark.toml`
By default the database will be stored in `~/.local/share/tinymark`
## Using
List stored bookmarks:
`tinymark list`
Add a bookmark:
`tinymark add https://example.com name`
With optional tags & description:
`tinymark add https://example.com name "test description" tags,separated,by,comma`
Delete a previously added bookmark:
`tinymark delete <link>`
You can export all the stored bookmarks to a JSON file with `tinymark export <file>`
You can then import a previously exported JSON file with `tinymark import <file>`
## JSON
This program can output in JSON format if you supply it with the `--json` argument.
Any command that returns a Bookmark will return a JSON serialized object of it.
Otherwise it will return a 'status' key of value 'success' or 'fail',
along with a 'reason' value with a full-length output.

171
src/commands.rs Normal file
View File

@ -0,0 +1,171 @@
use url::Url;
use std::env::VarError;
use chrono::Utc;
use crate::structures::Bookmark;
use paris::*;
use crate::database;
use serde_json::json;
use std::path::PathBuf;
use std::fs::File;
use std::io::{BufReader, BufWriter};
use dialoguer::{
Select,
theme::ColorfulTheme,
console::Term
};
pub fn edit(json: bool, url: &Option<Url>, path: Option<PathBuf>) {
if json {
println!("{}", json!({
"status": "fail",
"reason": "unsupported command",
}));
std::process::exit(exitcode::DATAERR);
} else {
match url {
Some(link) => {
println!("User selected item :\n{}", link);
},
None => {
match database::get_all(json, path) {
Some(bookmarks) => {
let mut items: Vec<&Url> = Vec::new();
for i in &bookmarks {
items.push(&i.link);
}
let selection = Select::with_theme(&ColorfulTheme::default())
.items(&items)
.default(0)
.interact_on_opt(&Term::stderr()).unwrap();
match selection {
Some(index) => println!("User selected item :\n{}", bookmarks[index]),
None => println!("User did not select anything")
}
},
None => {
if json {
println!("{}", json!({
"status": "fail",
"reason": "an error ocurred in running your command",
}));
} else {
warn!("an error ocurred in running your command");
}
},
}
},
}
}
}
pub fn add(url: &Url, name: &String, description: &Option<String>, tags: &Vec<String>, json: bool, path: Option<PathBuf>) {
let bookmark = Bookmark {
link: url.to_owned(),
label: name.to_string(),
description: description.to_owned(),
tags: tags.to_vec(),
container: None,
created_at: Utc::now(),
};
database::insert_entry(&bookmark, json, path);
if json {
println!("{}", serde_json::to_string(&bookmark).unwrap());
} else {
println!("Added new bookmark!");
println!("{}", bookmark);
};
}
pub fn list(json: bool, path: Option<PathBuf>) {
match database::get_all(json, path) {
Some(bookmarks) => {
for i in bookmarks {
if json {
println!("{}", serde_json::to_string(&i).unwrap());
} else {
println!("{}", i);
}
}
},
None => {
if json {
println!("{}", json!({
"status": "fail",
"reason": "an error ocurred in running your command",
}));
} else {
warn!("an error ocurred in running your command");
}
}
}
}
pub fn env_err(json: bool, e: VarError) {
if json {
println!("{}", json!({
"status": "fail",
"reason": e.to_string(),
}));
} else {
warn!("couldn't read $HOME environment variable: {}", e);
}
}
pub fn export(file_path: PathBuf, json: bool, path: Option<PathBuf>) {
if json {
println!("{}", json!({
"status": "fail",
"reason": "unsupported command",
}));
} else {
let file = match File::create(&file_path) {
Ok(f) => f,
Err(e) => {
warn!("error opening file! {}", e);
std::process::exit(exitcode::DATAERR);
},
};
let writer = BufWriter::new(file);
match database::get_all(json, path) {
Some(bookmarks) => serde_json::to_writer(writer, &bookmarks).unwrap(),
None => std::process::exit(exitcode::IOERR),
}
info!("Succesfully exported bookmarks to {}!", file_path.to_str().unwrap());
}
}
pub fn import(file_path: PathBuf, json: bool) {
match json {
true => {
println!("{}", json!({
"status": "fail",
"reason": "unsupported command",
}));
},
false => {
let file = match File::open(&file_path) {
Ok(f) => f,
Err(e) => {
warn!("error opening file! {}", e);
std::process::exit(exitcode::DATAERR);
}
};
let reader = BufReader::new(file);
let bookmarks: Vec<Bookmark> = match serde_json::from_reader(reader) {
Ok(contents) => contents,
Err(e) => {
warn!("error serializing file! {}", e);
std::process::exit(exitcode::DATAERR);
}
};
info!("succesfully imported bookmarks from {}!", file_path.to_str().unwrap());
},
}
}

220
src/database.rs Normal file
View File

@ -0,0 +1,220 @@
use crate::structures::Bookmark;
use crate::commands::env_err;
use paris::*;
use url::Url;
use std::env;
use serde_json::json;
use std::path::PathBuf;
fn open_database(json: bool, path: Option<PathBuf>) -> Option<sled::Db> {
let db: sled::Db;
let database_path = match path {
Some(path) => path,
None => {
let key = "HOME";
match env::var(key) {
Ok(val) => {
let mut tmp_path = PathBuf::new();
tmp_path.push(val);
tmp_path.push(".local/share/tinymark");
tmp_path
},
Err(e) => {
env_err(json, e);
std::process::exit(exitcode::DATAERR);
},
}
},
};
match sled::open(database_path) {
Ok(database) => db = database,
Err(error) => {
if json {
println!("{}", json!({
"status": "fail",
"reason": error.to_string(),
}));
} else {
error!("error in opening database: {}", error);
}
return None;
},
};
return Some(db);
}
pub fn insert_entry(entry: &Bookmark, json: bool, path: Option<PathBuf>) {
let db = match open_database(json, path) {
Some(database) => database,
None => std::process::exit(exitcode::NOINPUT),
};
let bytes;
match bincode::serialize(&entry) {
Ok(result) => bytes = result,
Err(error) => {
if json {
println!("{}", json!({
"status": "fail",
"reason": error.to_string(),
}));
} else {
error!("failed serializing entry: {}", error);
}
std::process::exit(exitcode::DATAERR);
},
};
match db.insert(entry.link.to_string(), bytes) {
Ok(_) => {
if json {
println!("{}", json!({
"status": "success",
"reason": "inserted entry",
}));
} else {
info!("succesfully inserted entry <i>{}", entry.link);
}
},
Err(error) => {
if json {
println!("{}", json!({
"status": "fail",
"reason": error.to_string(),
}));
} else {
error!("failed to insert entry <i>{}</i>!\n {}", entry.link, error);
}
std::process::exit(exitcode::IOERR);
},
}
db.flush().unwrap();
}
pub fn remove_entry(link: &Url, json: bool, path: Option<PathBuf>) {
let db = match open_database(json, path) {
Some(database) => database,
None => std::process::exit(exitcode::NOINPUT),
};
match db.remove(link.to_string()) {
Ok(_) => info!("succesfully removed entry <i>{}", link),
Err(error) => {
if json {
println!("{}", json!({
"status": "fail",
"reason": error.to_string(),
}));
} else {
error!("failed to remove entry <i>{}</i>!\n {}", link, error);
}
std::process::exit(exitcode::IOERR);
},
}
db.flush().unwrap();
}
pub fn get_all(json: bool, path: Option<PathBuf>) -> Option<Vec<Bookmark>> {
let db = match open_database(json, path) {
Some(database) => database,
None => return None,
};
let first_key = match db.first() {
Ok(pair) => {
pair.unwrap().0
},
Err(error) => {
if json {
println!("{}", json!({
"status": "fail",
"reason": error.to_string(),
}));
} else {
error!("failed to get first key: {}", error);
}
return None;
},
};
let mut bookmarks_vector: Vec<Bookmark> = Vec::new();
let mut iter = db.range(first_key..);
loop {
match iter.next() {
Some(x) => {
let read_entry;
match bincode::deserialize(&x.unwrap().1) {
Ok(result) => read_entry = result,
Err(error) => {
if json {
println!("{}", json!({
"status": "fail",
"reason": error.to_string(),
}));
} else {
error!("failed deserializing entry: {}", error);
}
return None;
},
}
bookmarks_vector.push(read_entry);
},
None => { break },
}
}
return Some(bookmarks_vector);
}
/* not working for some reason
pub fn update_entry(entry: &Bookmark) {
let db = open_database();
let bytes = match bincode::serialize(&entry) {
Ok(bytes) => bytes,
Err(error) => panic!("failed to serialize entry: {}", error),
};
let old_entry: Bookmark = get_entry(&entry.id.to_simple().to_string()).unwrap();
let old_bytes = match bincode::serialize(&old_entry) {
Ok(bytes) => bytes,
Err(error) => panic!("failed to serialize entry: {}", error),
};
match db.compare_and_swap(
entry.id.to_simple().to_string(),
Some(&old_bytes),
Some(&bytes)) {
Ok(_) => info!("succesfully swapped entry <i>{}", entry.id),
Err(error) => warn!("failed to swap entry <i>{}</i>!\n {}", entry.id, error),
}
db.flush();
}
pub fn get_entry(id: &str) -> Option<Bookmark> {
let db = open_database();
let db_entry = match db.get(id) {
Ok(entry) => entry,
Err(error) => panic!("failed to get old entry: {}", error),
};
if let Some(entry) = db_entry {
let read_entry = match bincode::deserialize(&entry) {
Ok(entry) => entry,
Err(error) => panic!("failed to deserialize entry: {}", error),
};
return Some(read_entry);
} else {
warn!("failed to find entry");
return None;
};
}
*/

61
src/main.rs Normal file
View File

@ -0,0 +1,61 @@
pub mod structures;
mod tests;
mod database;
mod commands;
use crate::structures::{Commands, Cli, Config};
use clap::Parser;
use paris::*;
use std::path::PathBuf;
use std::env;
fn main() {
let cfg: Config = confy::load("tinymark").unwrap();
confy::store("tinymark", &cfg).unwrap();
/*
println!("The configuration is:");
println!("{:#?}", cfg);*/
if cfg.tui {
warn!("TUI is not implemented yet!");
std::process::exit(exitcode::DATAERR);
}
let args = Cli::parse();
let json: bool;
if cfg.json {
json = true;
} else {
json = args.json;
}
let storage_path: Option<PathBuf> = match &cfg.storage_location {
Some(path) => {
let HOME = env::var("HOME");
match HOME {
Ok(val) => {
let mut new_path = PathBuf::new();
new_path.push(val);
new_path.push(path);
Some(new_path)
},
Err(e) => {
commands::env_err(json, e);
None
},
}
},
None => None,
};
match &args.command {
Commands::Add { url, name, description, tags } => commands::add(url, name, description, tags, json, storage_path),
Commands::Edit { url } => commands::edit(json, url, storage_path),
Commands::Delete { url } => database::remove_entry(url, json, storage_path),
Commands::List { } => commands::list(json, storage_path),
Commands::Export { file } => commands::export(file.to_path_buf(), json, storage_path),
Commands::Import { file } => commands::import(file.to_path_buf(), json),
}
}

131
src/structures.rs Normal file
View File

@ -0,0 +1,131 @@
use url::Url;
use uuid::Uuid;
use serde_derive::{Serialize, Deserialize};
use clap::{AppSettings, Parser, Subcommand};
use std::fmt;
use chrono::prelude::*;
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
pub tui: bool,
pub json: bool,
pub storage_location: Option<PathBuf>,
}
impl Default for Config {
fn default() -> Self {
Config {
tui: false,
json: false,
storage_location: Some(PathBuf::from(r"$HOME/.local/share/tinymark")),
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Bookmark {
//pub id: Uuid,
pub link: Url,
pub label: String,
pub description: Option<String>,
pub tags: Vec<String>,
pub container: Option<Uuid>,
pub created_at: DateTime<Utc>,
}
fn do_nothing() {
//yea
}
impl fmt::Display for Bookmark {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
println!("Bookmark: {}", &self.label);
println!("{}", &self.link);
match &self.description {
Some(s) => println!("{}", s),
None => do_nothing(),
};
print!("[");
for i in &self.tags {
print!("{},", i);
}
print!("]");
write!(f, "\nCreated at: {}\n", &self.created_at.with_timezone(&Local).to_rfc2822())
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Container {
pub id: Uuid,
pub label: String,
pub container: Option<Uuid>,
pub container_type: ContainerTypes,
}
#[derive(Serialize, Deserialize, Debug)]
pub enum ContainerTypes {
Folder,
Group,
}
#[derive(Parser)]
pub struct Cli {
/// Output as JSON
#[clap(long)]
pub json: bool,
#[clap(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
/// Add a bookmark
#[clap(setting(AppSettings::ArgRequiredElseHelp))]
Add {
/// The URL to add
url: Url,
/// The name of the bookmark
name: String,
/// A short description
description: Option<String>,
/// Optional comma-seperated tags
tags: Vec<String>
},
/// Edit a bookmark
Edit {
url: Option<Url>,
},
/// Delete a bookmark
#[clap(setting(AppSettings::ArgRequiredElseHelp))]
Delete {
// The bookmark to delete
url: Url,
},
/// List all bookmarks
List,
/// Export the bookmarks to a JSON file
#[clap(setting(AppSettings::ArgRequiredElseHelp))]
Export {
/// The output file
file: PathBuf,
},
/// Import bookmarks from a JSON file
#[clap(setting(AppSettings::ArgRequiredElseHelp))]
Import {
/// The input file
file: PathBuf,
},
}

7
src/tests.rs Normal file
View File

@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}