diff --git a/Cargo.lock b/Cargo.lock index c540f11..38de42c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,6 +32,7 @@ dependencies = [ "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -42,6 +43,23 @@ name = "cobs" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "csv" +version = "1.0.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive-error" version = "0.0.4" @@ -52,6 +70,11 @@ dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dtoa" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "encode_unicode" version = "0.3.1" @@ -73,8 +96,10 @@ name = "framed_decode" version = "0.1.0" dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", "derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "framed 0.1.4", + "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -86,11 +111,35 @@ dependencies = [ "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itoa" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libc" version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-traits" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.3.15" @@ -138,6 +187,17 @@ dependencies = [ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_json" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ssmarshal" version = "1.0.0" @@ -170,6 +230,16 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "term_size" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.1" @@ -185,6 +255,7 @@ name = "textwrap" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -203,6 +274,11 @@ name = "vec_map" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.2" @@ -212,6 +288,11 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.3.1" @@ -229,9 +310,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum case 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e88b166b48e29667f5443df64df3c61dc07dc2b1a0b0d231800e07f09a33ecc1" "checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f" "checksum cobs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "98acedfd5fc3ef93c4c844980f30318a445c24f76863a9e51f0599b9f1d274ad" +"checksum csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e7a9e063dcebdb56c306f23e672bfd31df3da8ec5f6d696b35f2c29c2a9572f0" +"checksum csv-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1fbabf21d9a52d04675cc5b032d7bae24ecdcd22646f7eefcd0496a122686c" "checksum derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ec098440b29ea3b1ece3e641bac424c19cf996779b623c9e0f2171495425c2c8" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encode_unicode 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c088ec0ed2282dcd054f2c124c0327f953563e6c75fdc6ff5141779596289830" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" +"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" @@ -239,15 +327,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "386122ba68c214599c44587e0c0b411e8d90894503a95425b4f9508e4317901f" "checksum serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0bfa6c5784e7d110514448da0e1dbad41ea5514c3e68be755b23858b83a399" "checksum serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "730fe9f29fe8db69a601837f416e46cba07792031ed6b27557a43e49d62d89ae" +"checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839" "checksum ssmarshal 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "890b38836c01d72fdb636d15c9cfc52ec7fd783b330abc93cd1686f4308dfccc" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ca38ad0b1b8fcebdf9a7906e368ce3a760ffa638c4c4f0cb57f3c26ad34cc86e" "checksum winapi-x86_64-pc-windows-gnu 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a824ed89cff621305f4ae379551c65e1fca1eadb1d4a25e3a4e8989080a2d337" diff --git a/bin/decode_typed b/bin/decode_typed index 03ceb10..7a604da 100755 --- a/bin/decode_typed +++ b/bin/decode_typed @@ -3,13 +3,15 @@ set -e REPO_DIR="$(cd $(dirname ${BASH_SOURCE[0]} )/..; pwd )" -TYPE_CRATE_DIR="${TYPE_CRATE_DIR-${REPO_DIR}/test_type}" -TYPE_NAME="${TYPE_NAME-framed_test_type::Test}" +DECODE_TYPE_CRATE_DIR="${DECODE_TYPE_CRATE_DIR?You must set this environment variable with the path to the crate containing your serialized type. +E.g. \'framed-rs/test_type\'}" +DECODE_TYPE_NAME="${DECODE_TYPE_NAME?You must set this environment variable with the full name of your serialized type including its module path. +E.g. \'framed_test_type::Test\'}" -echo "TYPE_CRATE_DIR = '${TYPE_CRATE_DIR}'" -echo "TYPE_NAME = '${TYPE_NAME}'" +echo "DECODE_TYPE_CRATE_DIR = '${DECODE_TYPE_CRATE_DIR}'" +echo "DECODE_TYPE_NAME = '${DECODE_TYPE_NAME}'" -TYPE_CRATE_NAME="$(cargo read-manifest --manifest-path "${TYPE_CRATE_DIR}/Cargo.toml" | jq '.name' -r)" +TYPE_CRATE_NAME="$(cargo read-manifest --manifest-path "${DECODE_TYPE_CRATE_DIR}/Cargo.toml" | jq '.name' -r)" TMP_DIR="${REPO_DIR}/target/decode_typed/tmp" @@ -17,33 +19,41 @@ mkdir -p "${TMP_DIR}"; rm -f "${TMP_DIR}/"*; # TODO: Move dynamic.rs to TMP_DIR, both here and in the include! in main.rs. -export FRAMED_DECODE_DYNAMIC_RS="${TMP_DIR}/dynamic_${TYPE_NAME}.rs"; +export FRAMED_DECODE_DYNAMIC_RS="${TMP_DIR}/dynamic_${DECODE_TYPE_NAME}.rs"; cat > "${FRAMED_DECODE_DYNAMIC_RS}" < test_data + +# The Test value is printed to stderr: +test_type/main.rs: Sending sample value: Test { + a: 1, + b: 2 +} +``` + +Set environment variables to configure the type to deserialize and the +crate it's in, then pipe the test data to decode_typed. Note that the +serialized data is not self describing, so if you configure the wrong +type you will get garbage data out. + +```text +~/framed-rs % export DECODE_TYPE_CRATE_DIR=test_type; +~/framed-rs % export DECODE_TYPE_NAME=framed_test_type::Test; +~/framed-rs % < test_data bin/decode_typed +# Some build output: + Compiling framed_test_type v0.1.0 (file:///home/user/framed-rs/test_type) + Compiling framed_decode v0.1.0 (file:///home/user/framed-rs/decode) + +# decode logs each received value to stdout: +decode/main.rs: received value of type framed_test_type::Test: Test { + a: 1, + b: 2 +} +``` + +`decode_typed` first builds the type crate with `cargo rustc` then +builds and runs `framed-rs/decode` linked to it. To configure the type +crate build pass cargo arguments in the environment variable +`DECODE_TYPE_CARGO_FLAGS` and rustc arguments in +`DECODE_TYPE_RUSTC_FLAGS`. To configure the decode tool build pass +cargo arguments in `DECODE_BIN_CARGO_FLAGS` and rustc arguments in +`DECODE_BIN_RUSTC_FLAGS`. + +`decode_typed` passes command line arguments to the `framed_decode` +crate's binary; run `decode_typed --help` to see all the possible arguments: + +```text +~/framed-rs % bin/decode_typed --help + +framed_decode 0.1.0 +Alex Helfet +`framed` sends and receives data over lossy streams of bytes. + +`framed_decode` is a command line tool to decode data encoded by the `framed` library. + +USAGE: + decode-5aa7aaf9ea94963a [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + --out-format + Output format type used to write data to stdout. [default: Debug] [values: + Csv, Debug, Json] +``` Note: you must install [`jq`][jq] and have it on your path. + +On Ubuntu you can install it with: `sudo apt install jq`. + [jq]: https://stedolan.github.io/jq/ diff --git a/decode/src/error.rs b/decode/src/error.rs index 263e105..60a0d25 100644 --- a/decode/src/error.rs +++ b/decode/src/error.rs @@ -1,11 +1,23 @@ +use clap; +use csv; use framed; +use serde_json; use std; #[derive(Debug, Error)] pub enum Error { + /// Error in library `clap`. + Clap(clap::Error), + + /// Error in library `csv`. + Csv(csv::Error), + /// Error in library `framed`. #[error(non_std)] Framed(framed::Error), + + /// Error in library `serde_json`. + SerdeJson(serde_json::Error), } pub type Result = std::result::Result; diff --git a/decode/src/main.rs b/decode/src/main.rs index 3d5ba67..d1bb2e8 100644 --- a/decode/src/main.rs +++ b/decode/src/main.rs @@ -2,18 +2,29 @@ #[macro_use] extern crate clap; +extern crate csv; #[macro_use] extern crate derive_error; extern crate framed; +extern crate serde_json; include!(env!("FRAMED_DECODE_DYNAMIC_RS")); mod error; use error::{Error, Result}; -// use clap::{App, Arg}; +use clap::Arg; use framed::typed::Receiver; -use std::io::stdin; +use std::io::{stdin, stdout}; + +arg_enum! { + #[derive(Debug, Eq, PartialEq)] + enum OutputFormat { + Csv, + Debug, + Json + } +} fn main() { match try() { @@ -24,16 +35,39 @@ fn main() { } fn try() -> Result<()> { - let app = app_from_crate!(); - let _matches = app.get_matches(); + let app = app_from_crate!() + .arg(Arg::with_name("out-format") + .long("out-format") + .help("Output format type used to write data to stdout.") + .takes_value(true) + .empty_values(false) + .possible_values(&OutputFormat::variants()) + .default_value("Debug") + .case_insensitive(true)); + let matches = app.get_matches(); + let out_fmt = value_t!(matches, "out-format", OutputFormat)?; + let mut r = Receiver::<_, UserType>::new(stdin()); + let mut csvw: Option> = + match out_fmt { + OutputFormat::Csv => + Some(csv::WriterBuilder::new().from_writer(stdout())), + _ => None, + }; + loop { - let v = r.recv(); - match v { - Ok(v) => { - println!("decode/main.rs: received value of type {}: {:#?}", - USER_TYPE_NAME, v); + let res = r.recv(); + match res { + Ok(v) => match out_fmt { + OutputFormat::Csv => csvw.as_mut() + .expect("Should've been initialized") + .serialize(&v)?, + OutputFormat::Debug => println!("{:#?}", v), + OutputFormat::Json => { + serde_json::to_writer(stdout(), &v)?; + println!(""); + }, }, Err(framed::Error::EofBeforeFrame) => return Ok(()), Err(e) => return Err(Error::from(e)), diff --git a/framed/src/lib.rs b/framed/src/lib.rs index 24be039..eae45de 100644 --- a/framed/src/lib.rs +++ b/framed/src/lib.rs @@ -274,10 +274,9 @@ pub fn decode_to_slice(e: &Encoded, mut dest: &mut [u8]) .map_err(|_| Error::CobsDecodeFailed)?; #[cfg(feature = "trace")] { - println!("framed: dest = {:?}\n\ - framed: body = {:?}\n\ + println!("framed: body = {:?}\n\ framed: decoded = {:?}", - &dest, body, &dest[0..len]); + body, &dest[0..len]); } Ok(len)