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