🏡 index : ~doyle/1p.git

author Jordan Doyle <jordan@doyle.la> 2020-07-05 14:51:09.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2020-07-05 14:54:13.0 +00:00:00
commit
6cd80415f83b88a67da3873891c26b38badd4b64 [patch]
tree
fe0ad18d6ef7111190ccfcad478e107cbcf01e50
download
6cd80415f83b88a67da3873891c26b38badd4b64.tar.gz

Initial commit



Diff

 .gitignore             |   1 +-
 Cargo.lock             | 477 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 Cargo.toml             |   6 +-
 onep-api-op/Cargo.toml |  13 +-
 onep-api-op/src/lib.rs | 242 +++++++++++++++++++++++++-
 onep-api/Cargo.toml    |   9 +-
 onep-api/src/lib.rs    |  46 +++++-
 onep-cli/Cargo.toml    |  16 ++-
 onep-cli/src/main.rs   | 168 ++++++++++++++++++-
 9 files changed, 978 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..9b57655
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,477 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
 "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "clap"
version = "3.0.0-beta.1"
source = "git+https://github.com/clap-rs/clap#9fc8ec965e42db926ef6aa894810c23600dac49d"
dependencies = [
 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "clap_derive 3.0.0-beta.1 (git+https://github.com/clap-rs/clap)",
 "indexmap 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "os_str_bytes 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "textwrap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "clap_derive"
version = "3.0.0-beta.1"
source = "git+https://github.com/clap-rs/clap#9fc8ec965e42db926ef6aa894810c23600dac49d"
dependencies = [
 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "colored"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "darling"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "darling_core"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "darling_macro"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "hermit-abi"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "indexmap"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "libc"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "onep-api"
version = "0.1.0"

[[package]]
name = "onep-api-op"
version = "0.1.0"
dependencies = [
 "onep-api 0.1.0",
 "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde_with 1.5.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "onep-cli"
version = "0.1.0"
dependencies = [
 "clap 3.0.0-beta.1 (git+https://github.com/clap-rs/clap)",
 "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "onep-api 0.1.0",
 "onep-api-op 0.1.0",
 "term-table 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "os_str_bytes"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "proc-macro-error"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
 "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "proc-macro-error-attr"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "proc-macro2"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "regex"
version = "1.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)",
 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "regex-syntax"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "serde"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_derive"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_json"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_with"
version = "1.5.0-alpha.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
 "serde_with_macros 1.2.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_with_macros"
version = "1.2.0-alpha.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "strsim"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "syn"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "syn-mid"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "term-table"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "textwrap"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "unicode-segmentation"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[metadata]
"checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum clap 3.0.0-beta.1 (git+https://github.com/clap-rs/clap)" = "<none>"
"checksum clap_derive 3.0.0-beta.1 (git+https://github.com/clap-rs/clap)" = "<none>"
"checksum colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
"checksum darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
"checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
"checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum indexmap 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum os_str_bytes 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "06de47b848347d8c4c94219ad8ecd35eb90231704b067e67e6ae2e36ee023510"
"checksum proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
"checksum proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
"checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
"checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
"checksum serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
"checksum serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
"checksum serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)" = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3"
"checksum serde_with 1.5.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14922cc3f5279e98d5790b4607854a129749aecccfffc75dc794fbfaba85209e"
"checksum serde_with_macros 1.2.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "460c3cc47cbbfdf107ae7c1e68022ad57b3f3f63d998255c155a54514a3e3f2e"
"checksum strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
"checksum syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd"
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
"checksum term-table 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dea05ef801340799f4c96296e9e8cf79cdfa66ef66fe991522591fde77405105"
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
"checksum textwrap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..675a161
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,6 @@
[workspace]
members = [
    "onep-cli",
    "onep-api",
    "onep-api-op",
]
\ No newline at end of file
diff --git a/onep-api-op/Cargo.toml b/onep-api-op/Cargo.toml
new file mode 100644
index 0000000..19b3e3a
--- /dev/null
+++ b/onep-api-op/Cargo.toml
@@ -0,0 +1,13 @@
[package]
name = "onep-api-op"
version = "0.1.0"
authors = ["Jordan Doyle <jordan@doyle.la>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
onep-api = { path = "../onep-api" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_with = "1.5.0-alpha.1"
\ No newline at end of file
diff --git a/onep-api-op/src/lib.rs b/onep-api-op/src/lib.rs
new file mode 100644
index 0000000..53f0feb
--- /dev/null
+++ b/onep-api-op/src/lib.rs
@@ -0,0 +1,242 @@
use serde::Deserialize;
use serde_json::Value;
use std::process::Command;

#[derive(Debug, Deserialize)]
struct GetAccount {
    name: String,
    domain: String,
}

#[derive(Debug, Deserialize)]
struct ListVault {
    uuid: String,
    name: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ListItem {
    uuid: String,
    vault_uuid: String,
    created_at: String,
    updated_at: String,
    overview: ItemOverview,
}

#[derive(Debug, Deserialize)]
struct ItemOverview {
    #[serde(rename = "URLs", default)]
    urls: Vec<ItemOverviewUrl>,
    title: String,
    url: Option<String>,
    #[serde(rename = "ainfo")]
    account_info: String,
    #[serde(default)]
    tags: Vec<String>,
}

#[derive(Debug, Deserialize)]
struct ItemOverviewUrl {
    #[serde(rename = "l")]
    label: String,
    #[serde(rename = "u")]
    url: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct GetItem {
    details: GetItemDetails,
    overview: ItemOverview,
}

#[derive(Debug, Deserialize)]
struct GetItemDetails {
    #[serde(default)]
    fields: Vec<GetItemDetailsField>,
    #[serde(default)]
    sections: Vec<GetItemSection>,
}

#[derive(Debug, Deserialize)]
struct GetItemDetailsField {
    name: String,
    #[serde(rename = "designation")]
    field_type: String,
    value: Value,
}

impl Into<onep_api::ItemField> for GetItemDetailsField {
    fn into(self) -> onep_api::ItemField {
        onep_api::ItemField {
            name: self.field_type,
            value: match self.value {
                Value::Null => String::new(),
                Value::String(v) => v,
                Value::Number(v) => format!("{}", v),
                Value::Bool(v) => if v { "true" } else { "false" }.to_string(),
                _ => panic!("unknown item field type for {}", self.name),
            },
        }
    }
}

#[derive(Debug, Deserialize)]
struct GetItemSection {
    title: String,
    #[serde(default)]
    fields: Vec<GetItemSectionField>,
}

#[derive(Debug, Deserialize)]
struct GetItemSectionField {
    #[serde(rename = "k")]
    kind: String,
    #[serde(rename = "n")]
    name: String,
    #[serde(rename = "t")]
    field_type: String,
    #[serde(rename = "v", default)]
    value: Value,
}

impl Into<onep_api::ItemField> for GetItemSectionField {
    fn into(self) -> onep_api::ItemField {
        onep_api::ItemField {
            name: self.field_type,
            value: match self.value {
                Value::Null => String::new(),
                Value::String(v) => v,
                Value::Number(v) => format!("{}", v),
                Value::Bool(v) => if v { "true" } else { "false" }.to_string(),
                _ => panic!("unknown item field type for {}", self.name),
            },
        }
    }
}

pub struct OnepasswordOp {}

impl onep_api::OnePassword for OnepasswordOp {
    fn totp(&self, uuid: &str) -> String {
        std::str::from_utf8(
            &Command::new("op")
                .arg("get")
                .arg("totp")
                .arg(uuid)
                .output()
                .expect("failed to exec get totp")
                .stdout,
        )
        .expect("failed to parse get totp output as utf8")
        .to_string()
    }

    fn account(&self) -> onep_api::AccountMetadata {
        let ret: GetAccount = serde_json::from_slice(
            &Command::new("op")
                .arg("get")
                .arg("account")
                .output()
                .expect("failed to exec get account")
                .stdout,
        )
        .expect("failed to parse json");

        onep_api::AccountMetadata {
            name: ret.name,
            domain: ret.domain,
        }
    }

    fn vaults(&self) -> Vec<onep_api::VaultMetadata> {
        let ret: Vec<ListVault> = serde_json::from_slice(
            &Command::new("op")
                .arg("list")
                .arg("vaults")
                .output()
                .expect("failed to exec list vaults")
                .stdout,
        )
        .expect("failed to parse json");

        ret.into_iter()
            .map(|v| onep_api::VaultMetadata {
                uuid: v.uuid,
                name: v.name,
            })
            .collect()
    }

    fn search(&self, terms: Option<&str>) -> Vec<onep_api::ItemMetadata> {
        let ret: Vec<ListItem> = serde_json::from_slice(
            &Command::new("op")
                .arg("list")
                .arg("items")
                .output()
                .expect("failed to exec list items")
                .stdout,
        )
        .expect("failed to parse json");

        ret.into_iter()
            .filter(|v| {
                if let Some(terms) = terms {
                    v.uuid == terms
                        || v.vault_uuid == terms
                        || v.overview.urls.iter().any(|v| v.url.contains(terms))
                        || v.overview.title.contains(terms)
                        || v.overview.account_info.contains(terms)
                        || v.overview.tags.iter().any(|v| v.contains(terms))
                } else {
                    true
                }
            })
            .map(|v| onep_api::ItemMetadata {
                title: v.overview.title,
                account_info: v.overview.account_info,
                uuid: v.uuid,
                vault_uuid: v.vault_uuid,
            })
            .collect()
    }

    fn get(&self, uuid: &str) -> Option<onep_api::Item> {
        let ret: GetItem = serde_json::from_slice(
            &Command::new("op")
                .arg("get")
                .arg("item")
                .arg(uuid)
                .output()
                .expect("failed to exec get item")
                .stdout,
        )
        .expect("failed to parse json");

        Some(onep_api::Item {
            title: ret.overview.title,
            fields: ret
                .details
                .fields
                .into_iter()
                .map(|f| f.into())
                .filter(|f: &onep_api::ItemField| !f.value.is_empty())
                .collect(),
            sections: ret
                .details
                .sections
                .into_iter()
                .map(|v| onep_api::ItemSection {
                    name: v.title,
                    fields: v
                        .fields
                        .into_iter()
                        .map(|f| f.into())
                        .filter(|f: &onep_api::ItemField| !f.value.is_empty())
                        .collect(),
                })
                .collect(),
        })
    }
}
diff --git a/onep-api/Cargo.toml b/onep-api/Cargo.toml
new file mode 100644
index 0000000..d45ed62
--- /dev/null
+++ b/onep-api/Cargo.toml
@@ -0,0 +1,9 @@
[package]
name = "onep-api"
version = "0.1.0"
authors = ["Jordan Doyle <jordan@doyle.la>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
diff --git a/onep-api/src/lib.rs b/onep-api/src/lib.rs
new file mode 100644
index 0000000..28e8069
--- /dev/null
+++ b/onep-api/src/lib.rs
@@ -0,0 +1,46 @@
#[derive(Debug)]
pub struct AccountMetadata {
    pub name: String,
    pub domain: String,
}

#[derive(Debug)]
pub struct VaultMetadata {
    pub uuid: String,
    pub name: String,
}

#[derive(Debug)]
pub struct ItemMetadata {
    pub uuid: String,
    pub vault_uuid: String,
    pub title: String,
    pub account_info: String,
}

#[derive(Debug)]
pub struct Item {
    pub title: String,
    pub fields: Vec<ItemField>,
    pub sections: Vec<ItemSection>,
}

#[derive(Debug)]
pub struct ItemField {
    pub name: String,
    pub value: String,
}

#[derive(Debug)]
pub struct ItemSection {
    pub name: String,
    pub fields: Vec<ItemField>,
}

pub trait OnePassword {
    fn totp(&self, uuid: &str) -> String;
    fn account(&self) -> AccountMetadata;
    fn vaults(&self) -> Vec<VaultMetadata>;
    fn search(&self, terms: Option<&str>) -> Vec<ItemMetadata>;
    fn get(&self, uuid: &str) -> Option<Item>;
}
diff --git a/onep-cli/Cargo.toml b/onep-cli/Cargo.toml
new file mode 100644
index 0000000..61e6441
--- /dev/null
+++ b/onep-cli/Cargo.toml
@@ -0,0 +1,16 @@
[package]
name = "onep-cli"
version = "0.1.0"
authors = ["Jordan D. <jordan@doyle.la>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
onep-api = { path = "../onep-api" }
onep-api-op = { path = "../onep-api-op" }

clap = { git = "https://github.com/clap-rs/clap" }
term-table = "1.3"
itertools = "0.9"
colored = "1.9"
\ No newline at end of file
diff --git a/onep-cli/src/main.rs b/onep-cli/src/main.rs
new file mode 100644
index 0000000..454473b
--- /dev/null
+++ b/onep-cli/src/main.rs
@@ -0,0 +1,168 @@
use clap::Clap;
use colored::*;
use itertools::Itertools;
use onep_api::OnePassword;
use term_table::{
    row::Row,
    table_cell::{Alignment, TableCell},
    Table, TableStyle,
};

#[derive(Clap, Debug)]
#[clap(author, version)]
/// 1password cli for humans
enum Opt {
    /// List all items
    #[clap(alias = "list")]
    Ls {
        #[clap(long, short = 'i')]
        show_uuids: bool,
        #[clap(long, short = 'n')]
        show_account_names: bool,
    },
    /// Grab a two-factor authentication code for the given item
    Totp { uuid: String },
    /// Search for an item
    Search { terms: String },
    /// Show existing password and optionally put it on the clipboard
    #[clap(alias = "get")]
    Show { uuid: String },
}

fn main() {
    let imp = onep_api_op::OnepasswordOp {};

    match Opt::parse() {
        Opt::Ls {
            show_uuids,
            show_account_names,
        } => {
            let account = imp.account();
            let vaults = imp.vaults();
            let results = imp.search(None);

            let mut results_grouped: Vec<(_, Vec<_>)> = Vec::new();
            for (key, group) in &results.into_iter().group_by(|v| v.vault_uuid.clone()) {
                results_grouped.push((key, group.collect()));
            }

            println!("{} ({})", account.name, account.domain);

            let vault_count = results_grouped.len() - 1;

            for (current_vault_index, (vault, group)) in results_grouped.into_iter().enumerate() {
                let vault = vaults
                    .iter()
                    .find(|v| v.uuid == vault)
                    .map(|v| v.name.clone())
                    .unwrap_or_else(|| format!("Unknown Vault ({})", vault));

                println!(
                    "{} {}",
                    if current_vault_index < vault_count {
                        "├──"
                    } else {
                        "└──"
                    },
                    vault.blue()
                );

                let line_start = if current_vault_index < vault_count {
                    ""
                } else {
                    " "
                };

                let item_count = group.len() - 1;

                for (current_item_index, result) in group.into_iter().enumerate() {
                    println!(
                        "{}   {} {}",
                        line_start,
                        if current_item_index < item_count {
                            "├──"
                        } else {
                            "└──"
                        },
                        result.title.trim()
                    );

                    let prefix = if current_item_index < item_count {
                        ""
                    } else {
                        "   "
                    };

                    if show_account_names && !result.account_info.trim().is_empty() {
                        println!(
                            "{}   {} {}",
                            line_start,
                            prefix,
                            result.account_info.trim().green()
                        );
                    }

                    if show_uuids {
                        println!("{}   {} {}", line_start, prefix, result.uuid.yellow());
                    }
                }
            }
        }
        Opt::Totp { uuid } => println!("{}", imp.totp(&uuid).trim()),
        Opt::Search { terms } => {
            for result in imp.search(Some(&terms)) {
                println!("[{}]", result.title.green());
                println!("{}", result.account_info);
                println!("{}", result.uuid);
                println!();
            }
        }
        Opt::Show { uuid } => {
            let result = imp.get(&uuid).unwrap();

            let mut table = Table::new();
            table.style = TableStyle::extended();

            table.add_row(Row::new(vec![TableCell::new_with_alignment(
                result.title,
                2,
                Alignment::Center,
            )]));

            for field in result.fields {
                table.add_row(Row::new(vec![
                    TableCell::new(field.name),
                    TableCell::new_with_alignment(field.value, 1, Alignment::Right),
                ]));
            }

            println!("{}", table.render());

            for section in result.sections {
                if section.fields.is_empty() {
                    continue;
                }

                let mut table = Table::new();
                table.style = TableStyle::extended();

                if !section.name.is_empty() {
                    table.add_row(Row::new(vec![TableCell::new_with_alignment(
                        section.name,
                        2,
                        Alignment::Center,
                    )]));
                }

                for field in section.fields {
                    table.add_row(Row::new(vec![
                        TableCell::new(field.name),
                        TableCell::new_with_alignment(field.value, 1, Alignment::Right),
                    ]));
                }

                println!("{}", table.render());
            }
        }
    }
}