#![no_std]
#![deny(clippy::all)]
#![deny(clippy::pedantic)]
#![deny(clippy::nursery)]
#![deny(clippy::cargo)]
extern crate alloc;
use alloc::{format, string::String, vec::Vec};
static PREFIXES: [char; 11] = ['b', 'k', 'm', 'g', 't', 'p', 'e', 'z', 'y', 'r', 'q'];
fn parse_one_letter_prefix(string_chars: &[char], si: bool) -> Option<i128> {
let prefix = string_chars.last()?.to_ascii_lowercase();
let number_length = string_chars.len() - 1;
if let Some(prefix_value) = PREFIXES
.iter()
.position(|&c| c == prefix)
{
if let Ok(number) = String::from_iter(&string_chars[..number_length]).parse::<i128>() {
let base: i128 = if si { 1000 } else { 1024 };
#[allow(clippy::cast_possible_truncation)]
return Some(number * base.pow(prefix_value as u32));
}
}
None
}
fn parse_two_letter_prefix(string_chars: &[char]) -> Option<i128> {
let str_len = string_chars.len();
if str_len < 2 {
return None;
}
let number_length = str_len - 2;
let prefix = &string_chars[number_length..];
assert_eq!(prefix.len(), 2);
let lchar = prefix[1].to_ascii_lowercase();
if !['b', 'i'].contains(&lchar) {
return None;
}
let si = lchar == 'b';
parse_one_letter_prefix(&string_chars[..=number_length], si)
}
fn parse_three_letter_prefix(string_chars: &[char]) -> Option<i128> {
let str_len = string_chars.len();
if str_len < 3 {
return None;
}
let number_length = str_len - 3;
let prefix = &string_chars[number_length..];
assert_eq!(prefix.len(), 3);
if !prefix[1].eq_ignore_ascii_case(&'i') || !prefix[2].eq_ignore_ascii_case(&'b') {
return None;
}
parse_one_letter_prefix(&string_chars[..=number_length], false)
}
pub fn parse_prefixes(prefixed_string: &str) -> Result<i128, String> {
if let Ok(parsed) = prefixed_string.parse::<i128>() {
return Ok(parsed);
}
let string_chars: Vec<char> = prefixed_string.chars().collect();
let string_length = string_chars.len();
if string_length < 2 {
return Err(format!("{prefixed_string} is not a prefixed string"));
}
if string_length == 2 {
if let Some(parsed) = parse_one_letter_prefix(&string_chars, false) {
return Ok(parsed);
}
return Err(format!("{prefixed_string} is not a prefixed string."));
}
if string_length == 3 {
let prefix = string_chars[1];
if prefix.is_ascii_digit() {
if let Some(parsed) = parse_one_letter_prefix(&string_chars, false) {
return Ok(parsed);
}
return Err(format!("{prefixed_string} is not a prefixed string."));
}
if let Some(parsed) = parse_two_letter_prefix(&string_chars) {
return Ok(parsed);
}
return Err(format!("{prefixed_string} is not a prefixed string."));
}
let prefix = string_chars[string_length - 3];
if prefix.is_ascii_digit() {
let prefix = string_chars[string_length - 2];
if prefix.is_ascii_digit() {
if let Some(parsed) = parse_one_letter_prefix(&string_chars, false) {
return Ok(parsed);
}
return Err(format!("{prefixed_string} is not a prefixed string."));
}
if let Some(parsed) = parse_two_letter_prefix(&string_chars) {
return Ok(parsed);
}
return Err(format!("{prefixed_string} is not a prefixed string."));
}
if let Some(parsed) = parse_three_letter_prefix(&string_chars) {
return Ok(parsed);
}
Err(format!("{prefixed_string} is not a prefixed string."))
}
#[cfg(test)]
mod pubapi_tests {
use super::parse_prefixes;
#[test]
fn test_one_letter_prefix() {
let result = parse_prefixes("4k").unwrap();
assert_eq!(result, 4096);
}
#[test]
fn test_two_letter_binary_prefix() {
let result = parse_prefixes("4ki").unwrap();
assert_eq!(result, 4096);
}
#[test]
fn test_two_letter_si_prefix() {
let result = parse_prefixes("4kb").unwrap();
assert_eq!(result, 4000);
}
#[test]
fn test_three_letter_prefix() {
let result = parse_prefixes("4kib").unwrap();
assert_eq!(result, 4096);
}
#[test]
fn test_long_numbers() {
let result = parse_prefixes("1000m").unwrap();
assert_eq!(result, 1048576000);
let result = parse_prefixes("4212ki").unwrap();
assert_eq!(result, 4313088);
let result = parse_prefixes("2231MB").unwrap();
assert_eq!(result, 2231000000);
let result = parse_prefixes("12412MiB").unwrap();
assert_eq!(result, 13014925312);
}
#[test]
fn test_correct_prefixes() {
let result = parse_prefixes("1b").unwrap();
assert_eq!(result, 1);
let result = parse_prefixes("1k").unwrap();
assert_eq!(result, 1024);
let result = parse_prefixes("1m").unwrap();
assert_eq!(result, 1048576);
let result = parse_prefixes("1g").unwrap();
assert_eq!(result, 1073741824);
let result = parse_prefixes("1t").unwrap();
assert_eq!(result, 1099511627776);
let result = parse_prefixes("1p").unwrap();
assert_eq!(result, 1125899906842624);
let result = parse_prefixes("1e").unwrap();
assert_eq!(result, 1152921504606846976);
let result = parse_prefixes("1z").unwrap();
assert_eq!(result, 1180591620717411303424);
let result = parse_prefixes("1y").unwrap();
assert_eq!(result, 1208925819614629174706176);
let result = parse_prefixes("1r").unwrap();
assert_eq!(result, 1237940039285380274899124224);
let result = parse_prefixes("1q").unwrap();
assert_eq!(result, 1267650600228229401496703205376);
let result = parse_prefixes("1bi").unwrap();
assert_eq!(result, 1);
let result = parse_prefixes("1ki").unwrap();
assert_eq!(result, 1024);
let result = parse_prefixes("1mi").unwrap();
assert_eq!(result, 1048576);
let result = parse_prefixes("1gi").unwrap();
assert_eq!(result, 1073741824);
let result = parse_prefixes("1ti").unwrap();
assert_eq!(result, 1099511627776);
let result = parse_prefixes("1pi").unwrap();
assert_eq!(result, 1125899906842624);
let result = parse_prefixes("1ei").unwrap();
assert_eq!(result, 1152921504606846976);
let result = parse_prefixes("1zi").unwrap();
assert_eq!(result, 1180591620717411303424);
let result = parse_prefixes("1yi").unwrap();
assert_eq!(result, 1208925819614629174706176);
let result = parse_prefixes("1ri").unwrap();
assert_eq!(result, 1237940039285380274899124224);
let result = parse_prefixes("1qi").unwrap();
assert_eq!(result, 1267650600228229401496703205376);
let result = parse_prefixes("1bib").unwrap();
assert_eq!(result, 1);
let result = parse_prefixes("1kib").unwrap();
assert_eq!(result, 1024);
let result = parse_prefixes("1mib").unwrap();
assert_eq!(result, 1048576);
let result = parse_prefixes("1gib").unwrap();
assert_eq!(result, 1073741824);
let result = parse_prefixes("1tib").unwrap();
assert_eq!(result, 1099511627776);
let result = parse_prefixes("1pib").unwrap();
assert_eq!(result, 1125899906842624);
let result = parse_prefixes("1eib").unwrap();
assert_eq!(result, 1152921504606846976);
let result = parse_prefixes("1zib").unwrap();
assert_eq!(result, 1180591620717411303424);
let result = parse_prefixes("1yib").unwrap();
assert_eq!(result, 1208925819614629174706176);
let result = parse_prefixes("1rib").unwrap();
assert_eq!(result, 1237940039285380274899124224);
let result = parse_prefixes("1qib").unwrap();
assert_eq!(result, 1267650600228229401496703205376);
let result = parse_prefixes("1bb").unwrap();
assert_eq!(result, 1);
let result = parse_prefixes("1kb").unwrap();
assert_eq!(result, 1000);
let result = parse_prefixes("1mb").unwrap();
assert_eq!(result, 1000000);
let result = parse_prefixes("1gb").unwrap();
assert_eq!(result, 1000000000);
let result = parse_prefixes("1tb").unwrap();
assert_eq!(result, 1000000000000);
let result = parse_prefixes("1pb").unwrap();
assert_eq!(result, 1000000000000000);
let result = parse_prefixes("1eb").unwrap();
assert_eq!(result, 1000000000000000000);
let result = parse_prefixes("1zb").unwrap();
assert_eq!(result, 1000000000000000000000);
let result = parse_prefixes("1yb").unwrap();
assert_eq!(result, 1000000000000000000000000);
let result = parse_prefixes("1rb").unwrap();
assert_eq!(result, 1000000000000000000000000000);
let result = parse_prefixes("1qb").unwrap();
assert_eq!(result, 1000000000000000000000000000000);
}
#[test]
fn test_negatives() {
let result = parse_prefixes("-1b").unwrap();
assert_eq!(result, -1);
let result = parse_prefixes("-1bi").unwrap();
assert_eq!(result, -1);
let result = parse_prefixes("-1000m").unwrap();
assert_eq!(result, -1048576000);
let result = parse_prefixes("-4212ki").unwrap();
assert_eq!(result, -4313088);
let result = parse_prefixes("-2231MB").unwrap();
assert_eq!(result, -2231000000);
let result = parse_prefixes("-12412MiB").unwrap();
assert_eq!(result, -13014925312);
}
#[test]
fn test_no_prefix() {
let result = parse_prefixes("8675309").unwrap();
assert_eq!(result, 8675309);
}
#[test]
#[should_panic(expected = "attempt to multiply with overflow")]
fn test_overflow() {
let _result = parse_prefixes("134217728q");
}
#[test]
#[should_panic(expected = "attempt to multiply with overflow")]
fn test_underflow() {
let _result = parse_prefixes("-134217729q");
}
#[test]
fn test_just_below_overflow() {
let result = parse_prefixes("134217727q").unwrap();
assert_eq!(result, 170141182192818631503457902219180900352);
assert_eq!(result, (2u128.pow(127) - 1024u128.pow(10)) as i128);
let result = parse_prefixes("170141183460469231731687303715884105727BIB").unwrap();
assert_eq!(result, (2u128.pow(127) - 1) as i128);
assert_eq!(result, 170141183460469231731687303715884105727);
assert_eq!(result, i128::MAX);
let result = parse_prefixes("-134217728q").unwrap();
let result2 = parse_prefixes("-170141183460469231731687303715884105728bi").unwrap();
assert_eq!(result2, result);
assert_eq!(result, i128::MIN);
assert_eq!(result, -170141183460469231731687303715884105728);
}
#[test]
fn test_edge_cases() {
let result = parse_prefixes("1b").unwrap();
assert_eq!(result, 1);
let result = parse_prefixes("1bib").unwrap();
assert_eq!(result, 1);
let result = parse_prefixes("1bb").unwrap();
assert_eq!(result, 1);
let result = parse_prefixes("100000b").unwrap();
assert_eq!(result, 100000);
let result = parse_prefixes("100000bib").unwrap();
assert_eq!(result, 100000);
let result = parse_prefixes("100000bb").unwrap();
assert_eq!(result, 100000);
}
#[test]
#[should_panic(expected = "Test Passed")]
fn test_invalid_one_letter_prefix() {
let _result = parse_prefixes("1j").expect("Test Passed");
}
#[test]
#[should_panic(expected = "Test Passed")]
fn test_invalid_input_1() {
let _result = parse_prefixes("7KBI").expect("Test Passed");
}
#[test]
#[should_panic(expected = "Test Passed")]
fn test_invalid_input_2() {
let _result = parse_prefixes("5mn").expect("Test Passed");
}
#[test]
#[should_panic(expected = "Test Passed")]
fn test_invalid_input_3() {
let _result = parse_prefixes("1b23434b").expect("Test Passed");
}
#[test]
#[should_panic(expected = "Test Passed")]
fn test_invalid_input_4() {
let _result = parse_prefixes("231m4b").expect("Test Passed");
}
}
#[cfg(test)]
mod privapi_tests {
use super::{parse_one_letter_prefix,parse_two_letter_prefix,parse_three_letter_prefix};
use alloc::vec::Vec;
#[test]
fn test_invalid_1s() {
assert_eq!(parse_one_letter_prefix(&"".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"b".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"mb".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"mib".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"sierbv".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"283974".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"032sc".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"39ki".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"12mi".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"12mib".chars().collect::<Vec<char>>(), false), None);
assert_eq!(parse_one_letter_prefix(&"12kib".chars().collect::<Vec<char>>(), false), None);
}
#[test]
fn test_invalid_2s() {
assert_eq!(parse_two_letter_prefix(&"".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"b".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"mb".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"mib".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"sierbv".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"283974".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"032sc".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"03b".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"03m".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"03mib".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"03ji".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_two_letter_prefix(&"03gib".chars().collect::<Vec<char>>()), None);
}
#[test]
fn test_invalid_3s() {
assert_eq!(parse_three_letter_prefix(&"".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"b".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"mb".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"mib".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"sierbv".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"283974".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"032sc".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"39ki".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"12mi".chars().collect::<Vec<char>>()), None);
assert_eq!(parse_three_letter_prefix(&"12k".chars().collect::<Vec<char>>()), None);
}
#[test]
fn test_valid_1s() {
assert_eq!(parse_one_letter_prefix(&"1b".chars().collect::<Vec<char>>(), false), Some(1));
assert_eq!(parse_one_letter_prefix(&"1b".chars().collect::<Vec<char>>(), true), Some(1));
assert_eq!(parse_one_letter_prefix(&"100k".chars().collect::<Vec<char>>(), false), Some(102400));
assert_eq!(parse_one_letter_prefix(&"100k".chars().collect::<Vec<char>>(), true), Some(100000));
assert_eq!(parse_one_letter_prefix(&"-1b".chars().collect::<Vec<char>>(), false), Some(-1));
assert_eq!(parse_one_letter_prefix(&"-1b".chars().collect::<Vec<char>>(), true), Some(-1));
assert_eq!(parse_one_letter_prefix(&"-100k".chars().collect::<Vec<char>>(), false), Some(-102400));
assert_eq!(parse_one_letter_prefix(&"-100k".chars().collect::<Vec<char>>(), true), Some(-100000));
}
#[test]
fn test_valid_2s() {
assert_eq!(parse_two_letter_prefix(&"1bi".chars().collect::<Vec<char>>()), Some(1));
assert_eq!(parse_two_letter_prefix(&"1bb".chars().collect::<Vec<char>>()), Some(1));
assert_eq!(parse_two_letter_prefix(&"100ki".chars().collect::<Vec<char>>()), Some(102400));
assert_eq!(parse_two_letter_prefix(&"100kb".chars().collect::<Vec<char>>()), Some(100000));
assert_eq!(parse_two_letter_prefix(&"-1bi".chars().collect::<Vec<char>>()), Some(-1));
assert_eq!(parse_two_letter_prefix(&"-1bb".chars().collect::<Vec<char>>()), Some(-1));
assert_eq!(parse_two_letter_prefix(&"-100ki".chars().collect::<Vec<char>>()), Some(-102400));
assert_eq!(parse_two_letter_prefix(&"-100kb".chars().collect::<Vec<char>>()), Some(-100000));
}
#[test]
fn test_valid_3s() {
assert_eq!(parse_three_letter_prefix(&"1bib".chars().collect::<Vec<char>>()), Some(1));
assert_eq!(parse_three_letter_prefix(&"100kib".chars().collect::<Vec<char>>()), Some(102400));
assert_eq!(parse_three_letter_prefix(&"-1bib".chars().collect::<Vec<char>>()), Some(-1));
assert_eq!(parse_three_letter_prefix(&"-100kib".chars().collect::<Vec<char>>()), Some(-102400));
}
}