2016-12-26 13:58:17 -07:00
|
|
|
/* number.rs
|
|
|
|
* Eryn Wells <eryn@erynwells.me>
|
|
|
|
*/
|
|
|
|
|
2016-12-26 18:23:58 -07:00
|
|
|
#[derive(PartialEq, Debug)]
|
|
|
|
pub struct Number { value: f64, }
|
|
|
|
|
|
|
|
impl Number {
|
|
|
|
pub fn new(value: f64) -> Number {
|
|
|
|
Number { value: value }
|
|
|
|
}
|
2016-12-26 13:58:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Radix { Bin, Oct, Dec, Hex }
|
|
|
|
|
2016-12-26 18:41:42 -07:00
|
|
|
#[derive(PartialEq, Debug)]
|
|
|
|
pub enum Sign { Pos, Neg }
|
|
|
|
|
2016-12-26 13:58:17 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct NumberBuilder {
|
|
|
|
exact: bool,
|
|
|
|
radix: Radix,
|
2016-12-26 18:41:42 -07:00
|
|
|
sign: Sign,
|
2016-12-26 13:58:17 -07:00
|
|
|
value: f64,
|
2016-12-26 18:41:42 -07:00
|
|
|
point: u32,
|
2016-12-26 13:58:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl NumberBuilder {
|
|
|
|
pub fn new() -> NumberBuilder {
|
|
|
|
NumberBuilder {
|
|
|
|
exact: false,
|
|
|
|
radix: Radix::Dec,
|
2016-12-26 18:41:42 -07:00
|
|
|
sign: Sign::Pos,
|
2016-12-26 13:58:17 -07:00
|
|
|
value: 0.0,
|
2016-12-26 18:23:58 -07:00
|
|
|
point: 0,
|
2016-12-26 13:58:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:41:42 -07:00
|
|
|
pub fn exact<'a>(&'a mut self, ex: bool) -> &'a mut NumberBuilder {
|
2016-12-26 13:58:17 -07:00
|
|
|
self.exact = ex;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:41:42 -07:00
|
|
|
pub fn radix<'a>(&'a mut self, r: Radix) -> &'a mut NumberBuilder {
|
2016-12-26 13:58:17 -07:00
|
|
|
self.radix = r;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:41:42 -07:00
|
|
|
pub fn sign<'a>(&'a mut self, s: Sign) -> &'a mut NumberBuilder {
|
|
|
|
self.sign = s;
|
|
|
|
self
|
2016-12-26 13:58:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn extend_value<'a>(&'a mut self, digit: char) -> &'a mut Self {
|
|
|
|
if let Some(place) = NumberBuilder::place_value(digit) {
|
|
|
|
self.value = self.radix.value() * self.value + place;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// TODO: Indicate an error.
|
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:23:58 -07:00
|
|
|
pub fn extend_decimal_value<'a>(&'a mut self, digit: char) -> &'a mut Self {
|
|
|
|
self.extend_value(digit);
|
|
|
|
self.point += 1;
|
2016-12-26 18:41:42 -07:00
|
|
|
println!("value = {}, point = {}", self.value, self.point);
|
2016-12-26 18:23:58 -07:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:41:42 -07:00
|
|
|
pub fn resolve(&self) -> Number {
|
|
|
|
// TODO: Convert fields to Number type.
|
|
|
|
let value = if self.point == 0 {
|
|
|
|
self.value
|
|
|
|
} else {
|
|
|
|
self.value / 10u32.pow(self.point) as f64
|
|
|
|
};
|
|
|
|
let value = if self.sign == Sign::Neg { value * -1.0 } else { value };
|
|
|
|
Number { value: value }
|
|
|
|
}
|
|
|
|
|
2016-12-26 13:58:17 -07:00
|
|
|
pub fn radix_value(&self) -> u32 {
|
|
|
|
self.radix.value() as u32
|
|
|
|
}
|
|
|
|
|
|
|
|
fn place_value(digit: char) -> Option<f64> {
|
|
|
|
match digit {
|
|
|
|
'0' ... '9' => Some((digit as u32 - '0' as u32) as f64),
|
|
|
|
'a' ... 'f' => Some((digit as u32 - 'a' as u32) as f64),
|
|
|
|
'A' ... 'F' => Some((digit as u32 - 'A' as u32) as f64),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Radix {
|
|
|
|
fn value(&self) -> f64 {
|
|
|
|
match *self {
|
|
|
|
Radix::Bin => 2.0,
|
|
|
|
Radix::Oct => 8.0,
|
|
|
|
Radix::Dec => 10.0,
|
|
|
|
Radix::Hex => 16.0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-26 18:41:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn builds_integers() {
|
|
|
|
let mut b = NumberBuilder::new();
|
|
|
|
b.extend_value('3');
|
|
|
|
assert_eq!(b.resolve().value, 3.0);
|
|
|
|
b.extend_value('4');
|
|
|
|
assert_eq!(b.resolve().value, 34.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn builds_negative_integers() {
|
|
|
|
let num = NumberBuilder::new().sign(Sign::Neg).extend_value('3').resolve();
|
|
|
|
assert_eq!(num.value, -3.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn builds_decimals() {
|
|
|
|
let mut b = NumberBuilder::new();
|
|
|
|
b.extend_value('5');
|
|
|
|
assert_eq!(b.resolve().value, 5.0);
|
|
|
|
b.extend_decimal_value('3');
|
|
|
|
assert_eq!(b.resolve().value, 5.3);
|
|
|
|
b.extend_decimal_value('4');
|
|
|
|
assert_eq!(b.resolve().value, 5.34);
|
|
|
|
}
|
|
|
|
}
|