use std::fmt::Display;
use std::ops::{Add, Div, Mul, Sub};
use std::str;
use crate::utils::{self, from_string};
use crate::NumberBase;
use crate::graphemes::grapheme_creation::GRAPHEMES;
use super::operations::*;
#[allow(non_camel_case_types)]
#[derive(Debug, Clone)]
pub struct uBase {
digits: Vec<u16>,
base: u16,
}
impl NumberBase for uBase {
type DecimalType = u128;
fn base(&self) -> u16 {
self.base
}
fn digits(&self) -> &Vec<u16> {
&self.digits
}
fn convert(&mut self, base: u16) -> Self {
let res = utils::convert(self.base, self.digits.clone(), base);
self.digits = res;
self.base = base;
self.clone()
}
fn from_string(base: u16, number: &str) -> Self {
let digits = from_string(base, number);
Self { digits, base }
}
fn from_vec(base: u16, number: Vec<u16>) -> Self {
Self {
digits: number,
base,
}
}
fn greater_than(&self, number: Self) -> bool {
let mut number = number;
if self.base != number.base {
number.convert(self.base);
}
greater_than(self.digits(), number.digits())
}
fn as_binary(&self) -> Self::DecimalType {
let mut binding_value = self.clone();
binding_value.convert(2);
binding_value.display_sub10().unwrap()
}
fn as_octal(&self) -> Self::DecimalType {
let mut binding_value = self.clone();
binding_value.convert(8);
binding_value.display_sub10().unwrap()
}
fn as_decimal(&self) -> Self::DecimalType {
let mut binding_value = self.clone();
binding_value.convert(10);
binding_value.display_sub10().unwrap()
}
fn as_hex(&self) -> String {
let mut binding_value = self.clone();
binding_value.convert(16);
binding_value.display()
}
fn display(&self) -> String {
let mut res_string = String::new();
let grapheme_collection: String = self
.digits
.iter()
.map(|x| {
str::from_utf8(
GRAPHEMES
.get(x)
.expect("Internal error. Could not fetch digit form graphemes map"),
)
.unwrap()
})
.collect();
res_string += &grapheme_collection;
if res_string.is_empty() {
String::from("0")
} else {
res_string.split('\0').collect()
}
}
}
impl Display for uBase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.display())
}
}
impl uBase {
fn display_sub10(&mut self) -> Option<u128> {
if self.base > 10 {
return None;
}
let str: String = self.display();
let number: u128 = str.parse().unwrap();
Some(number)
}
}
impl Add for uBase {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
let mut rhs = rhs;
if self.base != rhs.base {
rhs.convert(self.base);
}
let digits = add(self.base, self.digits(), rhs.digits());
Self {
digits,
base: self.base,
}
}
}
impl Sub for uBase {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
let mut rhs = rhs;
if self.base != rhs.base {
rhs.convert(self.base);
}
if !self.greater_than(rhs.clone()) {
panic!("Attempted to subtract with overflow");
}
let digits = subtract(self.base, self.digits(), rhs.digits());
Self {
digits,
base: self.base,
}
}
}
impl Div for uBase {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
let mut rhs = rhs;
if self.base != rhs.base {
rhs.convert(self.base);
}
let (quotient, _) = div(self.base, self.digits(), rhs.digits());
Self {
digits: quotient,
base: self.base,
}
}
}
impl Mul for uBase {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
let mut rhs = rhs;
if self.base != rhs.base {
rhs.convert(self.base);
}
let digits = mul(self.base, self.digits(), rhs.digits());
Self {
digits,
base: self.base,
}
}
}