diff --git a/Cargo.lock b/Cargo.lock index 2e7e0fd..263e3b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,15 +53,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "clap" -version = "4.5.13" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.13" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -103,6 +103,27 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "heck" version = "0.5.0" @@ -115,6 +136,18 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + [[package]] name = "proc-macro2" version = "1.0.86" @@ -134,11 +167,52 @@ dependencies = [ ] [[package]] -name = "rustCli" +name = "rust-cli" version = "0.1.0" dependencies = [ "anyhow", "clap", + "csv", + "serde", + "serde_json", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2b0dfa4..472d0c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,13 @@ [package] -name = "rustCli" +name = "rust-cli" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow="1.0.86" -clap = { version = "4.5.13", features = ["derive"] } \ No newline at end of file +anyhow="1.0.87" +clap = { version = "4.5.17", features = ["derive"] } +csv = "1.3.0" +serde = { version = "1.0.210", features = ["derive"] } +serde_json = "1.0.128" diff --git a/data.csv b/data.csv new file mode 100644 index 0000000..21a2489 --- /dev/null +++ b/data.csv @@ -0,0 +1,4 @@ +Name,Age,Occupation +Alice,30,Engineer +Bob,25,Designer +Charlie,35,Teacher \ No newline at end of file diff --git a/output.json b/output.json new file mode 100644 index 0000000..cbb2cc3 --- /dev/null +++ b/output.json @@ -0,0 +1,17 @@ +[ + { + "Name": "Alice", + "Age": 30, + "Occupation": "Engineer" + }, + { + "Name": "Bob", + "Age": 25, + "Occupation": "Designer" + }, + { + "Name": "Charlie", + "Age": 35, + "Occupation": "Teacher" + } +] \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..39de20e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +mod opts; + +pub use opts::Opts; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1b35263..c6d7cfe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,38 +1,28 @@ -use clap::Parser; - -#[derive(Parser, Debug)] -#[command(name = "rustCli", version, about="rust命令行工具", long_about = None)] -struct Opts { - #[command(subcommand)] - cmd: SubCommand, -} - -#[derive(Parser, Debug)] -enum SubCommand { - #[command(name = "csv", about = "读取csv文件并默认输出json文件")] - Csv(CsvOpts), -} +mod opts; -#[derive(Parser, Debug)] -struct CsvOpts { - /// Name of the person to greet - #[arg(short, long)] - input: String, +use crate::opts::{Opts, Person, SubCommand}; +use clap::Parser; +use csv::Reader; +use std::fs; - /// Output file name - #[arg(short, long, default_value = "output.json")] - output: String, +/// rust-li csv -i input.csv -o output.json -d "," +fn main() -> anyhow::Result<()> { + let opts = Opts::parse(); + match opts.cmd { + SubCommand::Csv(opts) => { + let mut reader = Reader::from_path(opts.input)?; - /// Delimiter to use for output file - #[arg(short, long, default_value = ",")] - delimiter: String, + let mut persons: Vec = Vec::new(); + // 读取csv文件 + for record in reader.deserialize() { + let person: Person = record?; + println!(" {:?}", person); + persons.push(person); + } - #[arg(long, default_value_t = true)] - header: bool, -} - -/// rustCli csv -i input.csv -o output.json -d "," -fn main() { - let opts = Opts::parse(); - println!("{:?}", opts); + // 输出json文件 + let result = serde_json::to_string_pretty(&persons)?; + Ok(fs::write(opts.output, result)?) + } + } } diff --git a/src/opts.rs b/src/opts.rs new file mode 100644 index 0000000..a1e95d8 --- /dev/null +++ b/src/opts.rs @@ -0,0 +1,52 @@ +use std::path; +use clap::Parser; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "PascalCase")] +pub struct Person { + name: String, + age: u8, + occupation: String, +} + +#[derive(Parser, Debug)] +#[command(name = "rustCli", version, about="rust命令行工具", long_about = None)] +pub struct Opts { + #[command(subcommand)] + pub(crate) cmd: SubCommand, +} + +#[derive(Parser, Debug)] +pub enum SubCommand { + #[command(name = "csv", about = "读取csv文件并默认输出json文件")] + Csv(CsvOpts), +} + +#[derive(Parser, Debug)] +pub struct CsvOpts { + /// 文件输入的路径,必填 + #[arg(short, long, required = true, value_parser = validate_path)] + pub input: String, + + /// 文件输入的路径,默认 output.json + #[arg(short, long, default_value = "output.json")] + pub output: String, + + /// 文件分隔符,默认"," + #[arg(short, long, default_value = ",")] + pub delimiter: String, + + /// 是否有标题行,默认true + #[arg(long, default_value_t = true)] + pub header: bool, +} + +/// 自定义参数校验器: 校验文件路径是否存在 +fn validate_path(path: &str) -> Result { + if path::Path::new(path).exists() { + Ok(path.to_string()) + } else { + Err(format!("{} 文件不存在", path)) + } +} \ No newline at end of file