From b3ee815b51823ed97e728a6e55ea613186a8c48b Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Mon, 1 Feb 2021 21:24:34 +0100 Subject: [PATCH] base program --- .gitignore | 3 + Cargo.lock | 63 +++++++++++++++++++++ Cargo.toml | 11 ++++ src/converter.rs | 142 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 54 ++++++++++++++++++ 5 files changed, 273 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/converter.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6ebc35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea/ +target/ +*.iml \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c6d29c1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,63 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "number_system_converter" +version = "0.1.0" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "once_cell" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" + +[[package]] +name = "regex" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" + +[[package]] +name = "thread_local" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915" +dependencies = [ + "once_cell", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8d70e67 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "number_system_converter" +version = "0.1.0" +authors = ["Nilstrieb "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +regex = "1.4.3" +lazy_static = "1.4.0" \ No newline at end of file diff --git a/src/converter.rs b/src/converter.rs new file mode 100644 index 0000000..e53eabb --- /dev/null +++ b/src/converter.rs @@ -0,0 +1,142 @@ +pub fn convert(from: &str, to: &str, val: &str) -> Result { + let int_value = match from { + "b" => from_bin_to_int(val)?, + "o" => from_oct_to_int(val)?, + "d" => from_dec_to_int(val), + "h" => from_hex_to_int(val)?, + _ => return Err(format!("Not a valid system: {}", from)) + }; + + match to { + "b" => Ok(from_int_to_bin(int_value)), + "o" => Ok(from_int_to_oct(int_value)), + "d" => Ok(from_int_to_dec(int_value)), + "h" => Ok(from_int_to_hex(int_value)), + _ =>Err(format!("Not a valid system: {}", from)) + } +} + +pub fn from_int_to_oct(mut val: i32) -> String { + let mut s = String::new(); + if val == 0 { + s += "0"; + } + while val > 0 { + let rest = val % 8; + s += &rest.to_string(); + val = val / 8; + } + + return s.chars().rev().collect(); +} + +pub fn from_int_to_hex(mut val: i32) -> String { + let mut s = String::new(); + if val == 0 { + s += "0"; + } + while val > 0 { + let rest = val % 16; + let to_string = rest.to_string(); + + s += match rest { + 10 => "A", + 11 => "B", + 12 => "C", + 13 => "D", + 14 => "E", + 15 => "F", + _ => &to_string + }; + val = val / 16; + } + + return s.chars().rev().collect(); +} + +pub fn from_int_to_bin(mut val: i32) -> String { + let mut s = String::new(); + if val == 0 { + s += "0"; + } + while val > 0 { + let rest = val % 2; + s += &rest.to_string(); + val = val / 2; + } + + return s.chars().rev().collect(); +} + +pub fn from_int_to_dec(val: i32) -> String { + val.to_string() +} + +pub fn from_dec_to_int(val: &str) -> i32 { + val.parse().expect("Not a valid decimal number") +} + +pub fn from_oct_to_int(val: &str) -> Result { + let mut dec = 0; + + for (i, c) in val.chars().rev().enumerate() { + let exp = i32::pow(8, i as u32); + + dec += exp * match c.to_ascii_lowercase() { + '0' => 0, + '1' => 1, + '2' => 2, + '3' => 3, + '4' => 4, + '5' => 5, + '6' => 6, + '7' => 7, + _ => return Err(format!("Not a valid octal number: {} at char {}: {}", val, i, c)) + }; + } + return Ok(dec); +} + +pub fn from_hex_to_int(val: &str) -> Result { + let mut dec = 0; + + for (i, c) in val.chars().rev().enumerate() { + let exp = i32::pow(16, i as u32); + + dec += exp * match c.to_ascii_lowercase() { + '0' => 0, + '1' => 1, + '2' => 2, + '3' => 3, + '4' => 4, + '5' => 5, + '6' => 6, + '7' => 7, + '8' => 8, + '9' => 9, + 'a' => 10, + 'b' => 11, + 'c' => 12, + 'd' => 13, + 'e' => 14, + 'f' => 15, + _ => return Err(format!("Not a valid hex number: {} at char {}: {}", val, i, c)) + }; + } + return Ok(dec); +} + +pub fn from_bin_to_int(val: &str) -> Result { + let mut dec = 0; + + for (i, c) in val.chars().rev().enumerate() { + let exp = i32::pow(2, i as u32); + if c == '1' { + dec += exp; + } else if c == '0' {} else { + return Err(format!("Not a valid binary number: {} at char {}: {}", val, i, c)); + } + } + + return Ok(dec); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..0edfbab --- /dev/null +++ b/src/main.rs @@ -0,0 +1,54 @@ +mod converter; + +#[macro_use] +extern crate lazy_static; +extern crate regex; + +use std::io; +use regex::Regex; +use std::result::Result::Err; + +fn main() { + println!("Enter a conversion | help"); + + + loop { + let mut input = String::new(); + + io::stdin() + .read_line(&mut input) + .expect("Failed to read line"); + + let trimmed = input.trim(); + + if trimmed == "help" { + println!("Enter a number and end it with a suffix [bodh] and then a space and the system you want it converted to.\n\ + Example: '255d h'\n\ + Will lead to: 'FF'"); + } else if trimmed == "exit" || trimmed == "c" || trimmed == "x"{ + break; + } else { + let splits = split(trimmed); + match splits { + Ok(a) => { + match converter::convert(&a.1, &a.2, &a.0) { + Ok(a) => println!("{}", a), + Err(e) => println!("{}", e) + } + } + Err(_) => println!("Invalid input") + } + } + } +} + +fn split(s: &str) -> Result<(String, String, String), ()> { + lazy_static! { + static ref RE: Regex = Regex::new(r"^(\w+) ?(\w) (\w)$").unwrap(); + } + + for capture in RE.captures_iter(s) { + return Ok((capture[1].to_string(), capture[2].to_string(), capture[3].to_string())); + } + Err(()) +}