arg: parse start

serial
Avril 4 years ago
parent 295f0a1bcd
commit fd2ad0fdb4
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -8,6 +8,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
mapcat = { path = "." }
memmap = "0.7.0"
num_cpus = "1.13.0"
smallvec = "1.5.1"

@ -0,0 +1,65 @@
use std::{fmt,error};
/// Print help message then exit with code `2`.
pub fn usage() -> !
{
eprintln!("uasge: {} <output file> <input files...>", std::env::args().next().unwrap());
eprintln!();
eprintln!("mapcat v{}: mmap() based file concatenation", env!("CARGO_PKG_VERSION"));
eprintln!(" by {} with <3 (licensed GPL3+)", env!("CARGO_PKG_AUTHORS"));
eprintln!();
eprintln!("NOTES:");
eprintln!("The output file is required, if one is not provided, we will just print this message and exit with error code `2`. If there are no input files, it will just create an empty output and return with error code `0` (unless there were other errors)");
eprintln!("Output files are always clobbered regardless if there are any inputs, or if the concatenation operation succeeds / fails");
eprintln!();
eprintln!(" (compiled with write parallelisation enabled)"); //TODO: we will eventually feature gate the threaded scheduler based solution. but for now, it is the only one implemented so we'll just print this always
std::process::exit(2)
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Operation
{
pub output: String,
pub inputs: Vec<String>,
}
/// Parse the arguments passed to the process
#[inline] pub fn parse_args() -> Result<Operation, ArgParseError>
{
parse(std::env::args().skip(1))
}
fn parse<J: Into<String>, I: IntoIterator<Item = J>>(args: I) -> Result<Operation, ArgParseError>
{
let mut args = args.into_iter().map(Into::into);
let output = args.next().ok_or(ArgParseError::NoOutput)?;
Ok(
Operation {
output,
inputs: args.collect(),
}
)
}
#[derive(Debug)]
pub enum ArgParseError
{
NoOutput,
}
impl error::Error for ArgParseError{}
impl fmt::Display for ArgParseError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::NoOutput => write!(f, "output file was not provided"),
}
}
}

@ -1,33 +1,38 @@
#![allow(dead_code)]
#[macro_export] macro_rules! unwrap {
(return $($code:expr)?; $err:expr) => {
{
match $err {
Ok(v) => v,
Err(e) => {
eprintln!("Error: {}", e);
#[allow(unused_variables)]
let rc = -1;
$(let rc = $code;)?
std::process::exit(rc)
},
}
}
};
}
mod state;
mod pool;
mod map;
mod job;
mod work;
mod arg;
mod consts;
fn usage() -> !
{
eprintln!("uasge: {} <output file> <input files...>", std::env::args().next().unwrap());
eprintln!();
eprintln!("mapcat v{}: mmap() based file concatenation", env!("CARGO_PKG_VERSION"));
eprintln!(" by {} with <3 (licensed GPL3+)", env!("CARGO_PKG_AUTHORS"));
eprintln!();
eprintln!("NOTES:");
eprintln!("The output file is required, if one is not provided, we will just exit with error code `2`. If there are no input files, it will just create an empty output and return with error code `0` (unless there were other errors)");
eprintln!("Output files are always clobbered regardless if there are any inputs, or if the concatenation operation succeeds / fails");
eprintln!();
eprintln!(" (compiled with write parallelisation enabled)"); //TODO: we will eventually feature gate the threaded scheduler based solution. but for now, it is the only one implemented so we'll just print this always
std::process::exit(0)
}
fn main() {
usage()
fn work(arg::Operation{output, inputs}: arg::Operation) -> Result<(), Box<dyn std::error::Error>>
{
// todo:
// - create and open output file
// - open and stat all input files in order (`job::create_from_file`).
@ -41,4 +46,14 @@ fn main() {
// - Read the completion stream receiver until all file jobs have been signaled as completed
// - wait on all worker threads to complete.
// - ensure all data was written.
Ok(())
}
fn main() {
match arg::parse_args() {
Ok(op) => unwrap!(return 1; work(op)),
Err(arg::ArgParseError::NoOutput) => arg::usage(),
}
}

Loading…
Cancel
Save