diff --git a/cli/Cargo.toml b/cli/Cargo.toml index a0ea752..28ec9b4 100755 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cambridge-asm-cli" -version = "0.15.2" +version = "0.16.0" authors = ["SaadiSave "] edition = "2021" license = "MPL-2.0" @@ -16,15 +16,15 @@ path = "src/main.rs" default = ["cambridge-asm/default"] [dependencies] -env_logger = "0.10" +env_logger = "0.11" serde_json = "1" ron = "0.8" serde_yaml = "0.9" -bincode = "2.0.0-rc.3" anyhow = "1" +ciborium = "0.2.2" [dependencies.cambridge-asm] -version = "0.19.0" +version = "0.21.0" default-features = false features = ["compile"] @@ -33,4 +33,4 @@ version = "4" features = ["derive"] [build-dependencies] -cargo_toml = "0.17" +cargo_toml = "0.20" diff --git a/cli/README.md b/cli/README.md index ff6f98b..a0648fd 100644 --- a/cli/README.md +++ b/cli/README.md @@ -1,6 +1,7 @@ # cambridge-asm-cli -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/saadisave/cambridge-asm/Publish%20CLI?style=for-the-badge)](https://github.com/SaadiSave/cambridge-asm/actions/workflows/publish-cli.yml) [![Crates.io](https://img.shields.io/crates/v/cambridge-asm?style=for-the-badge)](https://crates.io/crates/cambridge-asm) +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/SaadiSave/cambridge-asm/publish-cli.yml?style=for-the-badge)](https://github.com/SaadiSave/cambridge-asm/actions/workflows/publish-cli.yml) +[![Crates.io](https://img.shields.io/crates/v/cambridge-asm?style=for-the-badge)](https://crates.io/crates/cambridge-asm) Command line interface to execute pseudoassembly programs @@ -29,42 +30,37 @@ SUBCOMMANDS: ### `casm help run` ```text -casm-run Run compiled or plaintext pseudoassembly -USAGE: - casm run [OPTIONS] +Usage: casm run [OPTIONS] -ARGS: - Path to the input file containing compiled or plaintext pseudoassembly +Arguments: + Path to the input file containing compiled or plaintext pseudoassembly -OPTIONS: - -f, --format Format of input file [default: pasm] [possible values: pasm, json, ron, - yaml, bin] - -h, --help Print help information - -t, --bench Show execution time - -v, --verbose Increase logging level +Options: + -v, --verbose... Increase logging level + -t, --bench Show execution time + -f, --format Format of input file [default: pasm] [possible values: pasm, json, ron, yaml, cbor] + -h, --help Print help ``` ### `casm help compile` ```text -casm-compile Compile pseudoassembly -USAGE: - casm compile [OPTIONS] +Usage: casm compile [OPTIONS] -ARGS: - Path to the input file containing pseudoassembly +Arguments: + Path to the input file containing pseudoassembly -OPTIONS: - -f, --format Format of output file [default: json] [possible values: json, ron, - yaml, bin] - -h, --help Print help information - -m, --minify Minify output - -o, --output Path to output file - -v, --verbose Increase logging level +Options: + -o, --output Path to output file + -v, --verbose... Increase logging level + -f, --format Format of output file [default: json] [possible values: json, ron, yaml, cbor] + -m, --minify Minify output + -d, --debug Include debuginfo + -h, --help Print help ``` ## Log levels diff --git a/cli/src/main.rs b/cli/src/main.rs index 332712a..5c327b0 100755 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -11,7 +11,7 @@ use cambridge_asm::{ parse::{self, DefaultSet}, }; use clap::{Parser, ValueEnum}; -use std::ffi::OsString; +use std::{fs::File, io::Read, path::PathBuf}; #[derive(Parser)] #[clap(name = "Cambridge Pseudoassembly Interpreter")] @@ -22,7 +22,7 @@ enum Commands { /// Run compiled or plaintext pseudoassembly Run { /// Path to the input file containing compiled or plaintext pseudoassembly - path: OsString, + path: PathBuf, /// Increase logging level #[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count)] @@ -41,11 +41,11 @@ enum Commands { /// Compile pseudoassembly Compile { /// Path to the input file containing pseudoassembly - input: OsString, + input: PathBuf, /// Path to output file #[arg(short = 'o', long = "output")] - output: Option, + output: Option, /// Increase logging level #[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count)] @@ -73,7 +73,7 @@ enum InFormats { Json, Ron, Yaml, - Bin, + Cbor, } #[derive(ValueEnum, Clone)] @@ -81,7 +81,7 @@ enum OutFormats { Json, Ron, Yaml, - Bin, + Cbor, } fn main() -> anyhow::Result<()> { @@ -113,34 +113,30 @@ fn main() -> anyhow::Result<()> { } #[allow(clippy::enum_glob_use, clippy::needless_pass_by_value)] -fn run( - path: OsString, - verbosity: u8, - bench: bool, - format: InFormats, - io: Io, -) -> anyhow::Result<()> { +fn run(path: PathBuf, verbosity: u8, bench: bool, format: InFormats, io: Io) -> anyhow::Result<()> { use InFormats::*; init_logger(verbosity); - let prog_bytes = std::fs::read(path)?; + let file = File::open(path)?; let mut timer = bench.then(std::time::Instant::now); + let read_to_string = |mut f: File| -> std::io::Result<_> { + #[allow(clippy::cast_possible_truncation)] + let mut buf = String::with_capacity(f.metadata()?.len() as usize); + f.read_to_string(&mut buf)?; + Ok(buf) + }; + let mut executor = match format { - Pasm => parse::jit::(String::from_utf8_lossy(&prog_bytes), io).unwrap(), - Json => serde_json::from_str::(&String::from_utf8_lossy(&prog_bytes))? + Pasm => parse::jit::(read_to_string(file)?, io).unwrap(), + Json => serde_json::from_str::(&read_to_string(file)?)? .to_executor::(io), - Ron => ron::from_str::(&String::from_utf8_lossy(&prog_bytes))? + Ron => ron::from_str::(&read_to_string(file)?)?.to_executor::(io), + Yaml => serde_yaml::from_str::(&read_to_string(file)?)? .to_executor::(io), - Yaml => serde_yaml::from_str::(&String::from_utf8_lossy(&prog_bytes))? - .to_executor::(io), - Bin => { - bincode::decode_from_slice::(&prog_bytes, bincode::config::standard())? - .0 - .to_executor::(io) - } + Cbor => ciborium::from_reader::(file)?.to_executor::(io), }; timer = timer.map(|t| { @@ -163,13 +159,13 @@ fn run( #[allow(clippy::enum_glob_use, clippy::needless_pass_by_value)] fn compile( - mut input: OsString, - output: Option, + mut input: PathBuf, + output: Option, verbosity: u8, format: OutFormats, minify: bool, debug: bool, -) -> std::io::Result<()> { +) -> anyhow::Result<()> { use OutFormats::*; init_logger(verbosity); @@ -179,45 +175,50 @@ fn compile( let compiled = compile::compile::(prog, debug).unwrap(); let output_path = output.unwrap_or_else(|| { - input.push(match format { - Json => ".json", - Ron => ".ron", - Yaml => ".yaml", - Bin => ".bin", - }); + let ext = match format { + Json => "json", + Ron => "ron", + Yaml => "yaml", + Cbor => "cbor", + }; + input.set_extension(ext); input }); - let serialised = match format { - Json => { - use serde_json::ser::{to_string, to_string_pretty}; - - { - if minify { - to_string(&compiled).unwrap() - } else { - to_string_pretty(&compiled).unwrap() - } - } - .into_bytes() + let file = std::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(output_path)?; + + let json = |w: File, v: &CompiledProg| { + if minify { + serde_json::to_writer(w, v) + } else { + serde_json::to_writer_pretty(w, v) } - Ron => { - use ron::ser::{to_string, to_string_pretty, PrettyConfig}; - - { - if minify { - to_string(&compiled).unwrap() - } else { - to_string_pretty(&compiled, PrettyConfig::default()).unwrap() - } - } - .into_bytes() + }; + + let ron = |w: File, v: &CompiledProg| { + if minify { + ron::ser::to_writer(w, v) + } else { + ron::ser::to_writer_pretty(w, v, ron::ser::PrettyConfig::default()) } - Yaml => serde_yaml::to_string(&compiled).unwrap().into_bytes(), - Bin => bincode::encode_to_vec(&compiled, bincode::config::standard()).unwrap(), }; - std::fs::write(output_path, serialised) + let yaml = |w: File, v: &CompiledProg| serde_yaml::to_writer(w, v); + + let cbor = |w: File, v: &CompiledProg| ciborium::ser::into_writer(v, w); + + match format { + Json => json(file, &compiled)?, + Ron => ron(file, &compiled)?, + Yaml => yaml(file, &compiled)?, + Cbor => cbor(file, &compiled)?, + }; + + Ok(()) } fn init_logger(verbosity: u8) {