commit
f16bf876e2
@ -0,0 +1,2 @@
|
||||
/target
|
||||
*~
|
@ -0,0 +1,14 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "units"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "units"
|
||||
version = "0.1.0"
|
||||
authors = ["Avril <flanchan@cumallover.me>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
@ -0,0 +1,62 @@
|
||||
use std::{fmt, error};
|
||||
|
||||
pub fn prog_name() -> &'static str
|
||||
{
|
||||
lazy_static! {
|
||||
static ref NAME: String = std::env::args().next().unwrap();
|
||||
}
|
||||
|
||||
&NAME[..]
|
||||
}
|
||||
|
||||
/// Print usage then exit with error code `0`.
|
||||
pub fn usage() -> !
|
||||
{
|
||||
println!("Unit conversion v{}", env!("CARGO_PKG_VERSION"));
|
||||
println!(" by {} with <3 (license GPL3+)", env!("CARGO_PKG_AUTHORS"));
|
||||
println!();
|
||||
println!("usage: {} <unit> <value>", prog_name());
|
||||
println!("usage: {} --help", prog_name());
|
||||
println!();
|
||||
//TODO: generalise units
|
||||
println!(r#"Units:
|
||||
BYTES\t\tConvert byte unit into single bytes"#);
|
||||
std::process::exit(0)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Operation
|
||||
{
|
||||
Help,
|
||||
Convert(String, String),
|
||||
}
|
||||
|
||||
#[inline] pub fn parse_args() -> Result<Operation, ArgParseError>
|
||||
{
|
||||
parse(std::env::args().skip(1))
|
||||
}
|
||||
|
||||
fn parse<T: Into<String>>(from: impl IntoIterator<Item = T>) -> Result<Operation, ArgParseError>
|
||||
{
|
||||
let mut from = from.into_iter().map(Into::into);
|
||||
|
||||
let first = from.next().ok_or(ArgParseError)?;
|
||||
match first.to_lowercase().trim() {
|
||||
"--help" => Ok(Operation::Help),
|
||||
_ => {
|
||||
Ok(Operation::Convert(first, from.next().ok_or(ArgParseError)?))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArgParseError;
|
||||
|
||||
impl error::Error for ArgParseError{}
|
||||
impl fmt::Display for ArgParseError
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
write!(f, "Failed to parse args. Try passing `--help`.")
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bytes;
|
||||
|
||||
impl Conversion for Bytes
|
||||
{
|
||||
const UNIT: &'static str = "bytes";
|
||||
|
||||
type Output = u64;
|
||||
|
||||
fn convert(&self, input: &str) -> Result<Self::Output, Self::Error>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::convert::Infallible;
|
||||
|
||||
pub mod bytes;
|
||||
|
||||
pub trait Conversion
|
||||
{
|
||||
const UNIT: &'static str;
|
||||
|
||||
type Output: fmt::Display;
|
||||
type Error: Into<ConversionError> = ConversionError;
|
||||
|
||||
fn convert(&self, input: &str) -> Result<Self::Output, Self::Error>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConversionError(String);
|
||||
|
||||
impl error::Error for ConversionError{}
|
||||
impl fmt::Display for ConversionError
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
write!(f, "conversion failed: {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Infallible> for ConversionError
|
||||
{
|
||||
fn from(from: Infallible) -> Self
|
||||
{
|
||||
match from {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch a conversion of `value` for type `unit` and print the result to stdout.
|
||||
pub fn dispatch_out(unit: impl AsRef<str>, value: impl AsRef<str>) -> Result<(), ConversionError>
|
||||
{
|
||||
match unit.as_ref() {
|
||||
bytes::Bytes::UNIT => println!("{}", bytes::Bytes.convert(value.as_ref())?),
|
||||
name => return Err(ConversionError(format!("Unknown unit {}", name))),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
||||
#[macro_export] macro_rules! unwrap {
|
||||
($err:expr) => {
|
||||
match $err {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mod arg;
|
||||
|
||||
mod conv;
|
||||
|
||||
fn main() {
|
||||
use arg::Operation;
|
||||
match unwrap!(arg::parse_args()) {
|
||||
Operation::Help => arg::usage(),
|
||||
Operation::Convert(unit, from) => {
|
||||
unwrap!(conv::dispatch(unit, from));
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in new issue