Skip to content

Commit 705b8d8

Browse files
committed
avrow-cli: switch to structopt
1 parent acb15fb commit 705b8d8

File tree

7 files changed

+173
-193
lines changed

7 files changed

+173
-193
lines changed

avrow-cli/Cargo.toml

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ edition = "2018"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10-
clap = {version="2.33.1", features=["yaml"] }
11-
avrow = { path = "../../ravro", features=["all"] }
12-
argh = "0.1.3"
10+
avrow = { path = "../../avrow", features=["all"] }
1311
anyhow = "1.0.32"
14-
colored = "2.0.0"
12+
structopt = "0.3.20"
1513

1614
[[bin]]
1715
name = "av"

avrow-cli/README.md

+23-20
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,32 @@
33

44
Inspired from avro-tools.jar
55

6-
### Following subcommands are the supported as of now.
6+
## Install
77

88
```
9-
Usage: target/debug/av <command> [<args>]
10-
11-
av: command line tool for examining avro datafiles.
12-
13-
Options:
14-
--help display usage information
15-
16-
Commands:
17-
getmeta Get metadata information of the avro datafile.
18-
getschema Prints the writer's schema encoded in the provided datafile.
19-
read Prints data from datafile as human readable value
20-
tobytes Dumps the avro datafile as bytes for debugging purposes
21-
fingerprint Prints fingerprint of the canonical form of writer's schema.
22-
canonical Prints the canonical form of writer's schema encoded in the
23-
provided datafile.
24-
canonical
9+
cargo install --path .
2510
```
11+
This will install the binary as `av`.
2612

27-
Usage:
13+
### Following subcommands are the supported as of now.
2814

29-
```bash
30-
av read -d ./data.avro
15+
```
16+
avrow-cli 0.1.0
17+
Command line tool for examining avro datafiles
18+
19+
USAGE:
20+
av <SUBCOMMAND>
21+
22+
FLAGS:
23+
-h, --help Prints help information
24+
-V, --version Prints version information
25+
26+
SUBCOMMANDS:
27+
bytes Dumps the avro datafile as bytes for debugging purposes
28+
canonical Prints the canonical form of writer's schema encoded in the avro datafile.
29+
fingerprint Prints fingerprint of the canonical form of writer's schema in the avro datafile.
30+
help Prints this message or the help of the given subcommand(s)
31+
metadata Get metadata information of the avro datafile
32+
read Prints data in the avro datafile in debug format
33+
schema Prints the writer's schema encoded in the avro datafile
3134
```

avrow-cli/src/main.rs

+67-28
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,81 @@
11
//! avrow-cli is a command line tool to examine and analyze avro data files.
22
//!
3-
//! Usage: avrow-cli -i <avrodatafile> tojson // This prints the data contained in the <avrodatafile> in a readable format.
3+
//! Usage: `av -d <avrodatafile> read`
4+
//!
5+
//! The above command prints the data contained in the <avrodatafile> in a readable format.
6+
//!
47
58
mod subcommand;
69
mod utils;
710

8-
use argh::FromArgs;
11+
use std::path::PathBuf;
12+
use structopt::StructOpt;
13+
use subcommand::{bytes, canonical, fingerprint, metadata, read, schema};
914
use utils::read_datafile;
1015

11-
use subcommand::{Canonical, Fingerprint, GetMeta, GetSchema, ToBytes, ReadData};
12-
13-
#[derive(Debug, FromArgs)]
14-
/// av: command line tool for examining avro datafiles.
15-
struct AvrowCli {
16-
#[argh(subcommand)]
17-
subcommand: SubCommand,
18-
}
19-
20-
#[derive(FromArgs, PartialEq, Debug)]
21-
#[argh(subcommand)]
22-
enum SubCommand {
23-
GetMeta(GetMeta),
24-
GetSchema(GetSchema),
25-
Read(ReadData),
26-
ToBytes(ToBytes),
27-
Fingerprint(Fingerprint),
28-
Canonical(Canonical),
16+
#[derive(StructOpt, Debug)]
17+
#[structopt(about = "Command line tool for examining avro datafiles")]
18+
enum AvrowCli {
19+
#[structopt(
20+
name = "metadata",
21+
about = "Get metadata information of the avro datafile"
22+
)]
23+
Metadata {
24+
#[structopt(short)]
25+
datafile: PathBuf,
26+
},
27+
#[structopt(
28+
name = "schema",
29+
about = "Prints the writer's schema encoded in the avro datafile"
30+
)]
31+
Schema {
32+
#[structopt(short)]
33+
datafile: PathBuf,
34+
},
35+
#[structopt(
36+
about = "Prints fingerprint of the canonical form of writer's schema in the avro datafile."
37+
)]
38+
Fingerprint {
39+
#[structopt(short)]
40+
datafile: PathBuf,
41+
#[structopt(short)]
42+
fingerprint: String,
43+
},
44+
#[structopt(
45+
about = "Prints the canonical form of writer's schema encoded in the avro datafile."
46+
)]
47+
Canonical {
48+
#[structopt(short)]
49+
datafile: PathBuf,
50+
},
51+
#[structopt(about = "Prints data in the avro datafile in debug format")]
52+
Read {
53+
#[structopt(short)]
54+
datafile: PathBuf,
55+
},
56+
#[structopt(
57+
name = "bytes",
58+
about = "Dumps the avro datafile as bytes for debugging purposes"
59+
)]
60+
Bytes {
61+
#[structopt(short)]
62+
datafile: PathBuf,
63+
},
2964
}
3065

3166
fn main() -> anyhow::Result<()> {
32-
let flags: AvrowCli = argh::from_env();
33-
match flags.subcommand {
34-
SubCommand::GetMeta(cmd) => cmd.getmeta()?,
35-
SubCommand::Read(cmd) => cmd.read_data()?,
36-
SubCommand::ToBytes(cmd) => cmd.tobytes()?,
37-
SubCommand::GetSchema(cmd) => cmd.getschema()?,
38-
SubCommand::Fingerprint(cmd) => cmd.fingerprint()?,
39-
SubCommand::Canonical(cmd) => cmd.canonical()?
67+
use AvrowCli::*;
68+
let opt = AvrowCli::from_args();
69+
match opt {
70+
Metadata { datafile } => metadata(&datafile)?,
71+
Schema { datafile } => schema(&datafile)?,
72+
Canonical { datafile } => canonical(&datafile)?,
73+
Read { datafile } => read(&datafile)?,
74+
Bytes { datafile } => bytes(&datafile)?,
75+
Fingerprint {
76+
datafile,
77+
fingerprint: fp,
78+
} => fingerprint(&datafile, &fp)?,
4079
}
4180

4281
Ok(())

avrow-cli/src/subcommand.rs

+62-130
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,89 @@
11
use crate::read_datafile;
22
use anyhow::{anyhow, Context};
3-
use argh::FromArgs;
43
use avrow::{Header, Reader};
54
use std::io::Read;
65
use std::path::PathBuf;
76
use std::str;
87

9-
#[derive(FromArgs, PartialEq, Debug)]
10-
/// Get metadata information of the avro datafile.
11-
#[argh(subcommand, name = "getmeta")]
12-
pub struct GetMeta {
13-
/// datafile as input
14-
#[argh(option, short = 'd')]
15-
datafile: PathBuf,
16-
}
17-
18-
impl GetMeta {
19-
pub fn getmeta(&self) -> Result<(), anyhow::Error> {
20-
let mut avro_datafile = read_datafile(&self.datafile)?;
21-
let header = Header::from_reader(&mut avro_datafile)?;
22-
for (k, v) in header.metadata() {
23-
print!("{}\t", k);
24-
println!(
25-
"{}",
26-
str::from_utf8(v).expect("Invalid UTF-8 in avro header")
27-
);
28-
}
29-
Ok(())
8+
pub fn metadata(datafile: &PathBuf) -> Result<(), anyhow::Error> {
9+
let mut avro_datafile = read_datafile(datafile)?;
10+
let header = Header::from_reader(&mut avro_datafile)?;
11+
for (k, v) in header.metadata() {
12+
print!("{}\t", k);
13+
println!(
14+
"{}",
15+
str::from_utf8(v).expect("Invalid UTF-8 in avro header")
16+
);
3017
}
18+
Ok(())
3119
}
3220

33-
#[derive(FromArgs, PartialEq, Debug)]
34-
/// Prints data from datafile in debug format.
35-
#[argh(subcommand, name = "read")]
36-
pub struct ReadData {
37-
/// datafile as input
38-
#[argh(option, short = 'd')]
39-
datafile: PathBuf,
40-
}
41-
impl ReadData {
42-
pub fn read_data(&self) -> Result<(), anyhow::Error> {
43-
let mut avro_datafile = read_datafile(&self.datafile)?;
44-
let reader = Reader::new(&mut avro_datafile)?;
45-
// TODO: remove irrelevant fields
46-
for i in reader {
47-
println!("{:#?}", i?);
48-
}
49-
50-
Ok(())
21+
pub fn read(datafile: &PathBuf) -> Result<(), anyhow::Error> {
22+
let mut avro_datafile = read_datafile(datafile)?;
23+
let reader = Reader::new(&mut avro_datafile)?;
24+
// TODO: remove irrelevant fields
25+
for i in reader {
26+
println!("{:?}", i?);
5127
}
52-
}
5328

54-
#[derive(FromArgs, PartialEq, Debug)]
55-
/// Dumps the avro datafile as bytes for debugging purposes
56-
#[argh(subcommand, name = "tobytes")]
57-
pub struct ToBytes {
58-
/// datafile as input
59-
#[argh(option, short = 'd')]
60-
datafile: PathBuf,
29+
Ok(())
6130
}
6231

63-
impl ToBytes {
64-
pub fn tobytes(&self) -> Result<(), anyhow::Error> {
65-
let mut avro_datafile = read_datafile(&self.datafile)?;
66-
let mut v = vec![];
32+
pub fn bytes(datafile: &PathBuf) -> Result<(), anyhow::Error> {
33+
let mut avro_datafile = read_datafile(datafile)?;
34+
let mut v = vec![];
6735

68-
avro_datafile
69-
.read_to_end(&mut v)
70-
.with_context(|| "Failed to read data file in memory")?;
36+
avro_datafile
37+
.read_to_end(&mut v)
38+
.with_context(|| "Failed to read datafile")?;
7139

72-
println!("{:?}", v);
73-
Ok(())
74-
}
40+
println!("{:?}", v);
41+
Ok(())
7542
}
7643

77-
#[derive(FromArgs, PartialEq, Debug)]
78-
/// Prints the writer's schema encoded in the provided datafile.
79-
#[argh(subcommand, name = "getschema")]
80-
pub struct GetSchema {
81-
/// datafile as input
82-
#[argh(option, short = 'd')]
83-
datafile: PathBuf,
44+
pub fn schema(datafile: &PathBuf) -> Result<(), anyhow::Error> {
45+
let mut avro_datafile = read_datafile(datafile)?;
46+
let header = Header::from_reader(&mut avro_datafile)?;
47+
// TODO print human readable schema
48+
println!("{}", header.schema());
49+
Ok(())
8450
}
8551

86-
impl GetSchema{
87-
pub fn getschema(&self) -> Result<(), anyhow::Error> {
88-
let mut avro_datafile = read_datafile(&self.datafile)?;
89-
let header = Header::from_reader(&mut avro_datafile)?;
90-
// TODO print human readable schema
91-
dbg!(header.schema());
92-
Ok(())
93-
}
94-
}
95-
96-
#[derive(FromArgs, PartialEq, Debug)]
97-
/// Prints fingerprint of the canonical form of writer's schema.
98-
#[argh(subcommand, name = "fingerprint")]
99-
pub struct Fingerprint {
100-
/// datafile as input
101-
#[argh(option, short = 'd')]
102-
datafile: String,
103-
/// the fingerprinting algorithm (rabin64 (default), sha256, md5)
104-
#[argh(option, short = 'f')]
105-
fingerprint: String,
106-
}
107-
impl Fingerprint {
108-
pub fn fingerprint(&self) -> Result<(), anyhow::Error> {
109-
let mut avro_datafile = read_datafile(&self.datafile)?;
110-
let header = Header::from_reader(&mut avro_datafile)?;
111-
match self.fingerprint.as_ref() {
112-
"rabin64" => {
113-
println!("0x{:x}", header.schema().canonical_form().rabin64());
114-
},
115-
"sha256" => {
116-
let mut fingerprint_str = String::new();
117-
let sha256 = header.schema().canonical_form().sha256();
118-
for i in sha256 {
119-
let a = format!("{:x}", i);
120-
fingerprint_str.push_str(&a);
121-
}
122-
123-
println!("{}", fingerprint_str);
52+
pub fn fingerprint(datafile: &PathBuf, fingerprint: &str) -> Result<(), anyhow::Error> {
53+
let mut avro_datafile = read_datafile(datafile)?;
54+
let header = Header::from_reader(&mut avro_datafile)?;
55+
match fingerprint.as_ref() {
56+
"rabin64" => {
57+
println!("0x{:x}", header.schema().canonical_form().rabin64());
58+
}
59+
"sha256" => {
60+
let mut fingerprint_str = String::new();
61+
let sha256 = header.schema().canonical_form().sha256();
62+
for i in sha256 {
63+
let a = format!("{:x}", i);
64+
fingerprint_str.push_str(&a);
12465
}
125-
"md5" => {
126-
let mut fingerprint_str = String::new();
127-
let md5 = header.schema().canonical_form().md5();
128-
for i in md5 {
129-
let a = format!("{:x}", i);
130-
fingerprint_str.push_str(&a);
131-
}
132-
133-
println!("{}", fingerprint_str);
66+
67+
println!("{}", fingerprint_str);
68+
}
69+
"md5" => {
70+
let mut fingerprint_str = String::new();
71+
let md5 = header.schema().canonical_form().md5();
72+
for i in md5 {
73+
let a = format!("{:x}", i);
74+
fingerprint_str.push_str(&a);
13475
}
135-
other => return Err(anyhow!("invalid or unsupported fingerprint: {}", other))
76+
77+
println!("{}", fingerprint_str);
13678
}
137-
Ok(())
79+
other => return Err(anyhow!("invalid or unsupported fingerprint: {}", other)),
13880
}
81+
Ok(())
13982
}
14083

141-
#[derive(FromArgs, PartialEq, Debug)]
142-
/// Prints the canonical form of writer's schema encoded in the provided datafile.
143-
#[argh(subcommand, name = "canonical")]
144-
pub struct Canonical {
145-
/// datafile as input
146-
#[argh(option, short = 'd')]
147-
datafile: String,
148-
}
149-
150-
impl Canonical {
151-
pub fn canonical(&self) -> Result<(), anyhow::Error> {
152-
let mut avro_datafile = read_datafile(&self.datafile)?;
153-
let header = Header::from_reader(&mut avro_datafile)?;
154-
println!("{}", header.schema().canonical_form());
155-
Ok(())
156-
}
84+
pub fn canonical(datafile: &PathBuf) -> Result<(), anyhow::Error> {
85+
let mut avro_datafile = read_datafile(datafile)?;
86+
let header = Header::from_reader(&mut avro_datafile)?;
87+
println!("{}", header.schema().canonical_form());
88+
Ok(())
15789
}

0 commit comments

Comments
 (0)