Skip to content

Commit

Permalink
Switch from From<f64> to TryFrom<f64>
Browse files Browse the repository at this point in the history
Conversion from f64 can fail if it's something like NaN or Infinity.
  • Loading branch information
dbrgn committed Nov 18, 2016
1 parent 02928c8 commit d343aea
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 9 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ clippy = {version = "~0.0.79", optional = true}
chrono = "0.2"
uuid = "0.2"
quick-error = "1.1.0"
conv = "0.3"

[features]
nightly = ["clippy"]
38 changes: 29 additions & 9 deletions src/coordinates.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Custom data types used in the Gerber format.

use std::convert::{From, Into};
use std::convert::Into;
use conv::TryFrom;
use std::num::FpCategory;

use ::GerberError;

Expand Down Expand Up @@ -40,9 +42,16 @@ pub struct CoordinateNumber {
const DECIMAL_PLACES_CHARS: u8 = 6;
const DECIMAL_PLACES: i64 = 1_000_000;

impl From<f64> for CoordinateNumber {
fn from(val: f64) -> CoordinateNumber {
CoordinateNumber { nano: (val * DECIMAL_PLACES as f64) as i64 }
impl TryFrom<f64> for CoordinateNumber {
type Err = GerberError;
fn try_from(val: f64) -> Result<Self, Self::Err> {
match val.classify() {
FpCategory::Nan => Err(GerberError::ConversionError("Value is NaN".into())),
FpCategory::Infinite => Err(GerberError::ConversionError("Value is infinite".into())),
FpCategory::Zero => Ok(CoordinateNumber { nano: 0 }),
FpCategory::Subnormal => panic!("TODO: not yet decided"),
FpCategory::Normal => Ok(CoordinateNumber { nano: (val * DECIMAL_PLACES as f64) as i64 }),
}
}
}

Expand Down Expand Up @@ -83,24 +92,35 @@ impl CoordinateNumber {
#[cfg(test)]
mod test {
use super::*;
use std::f64;
use conv::TryFrom;

#[test]
/// Test float to decimal conversion
fn test_from_f64() {

fn test_try_from_f64_success() {
let a = CoordinateNumber { nano: 1375000i64 };
let b = CoordinateNumber::from(1.375f64);
let b = CoordinateNumber::try_from(1.375f64).unwrap();
assert_eq!(a, b);

let c = CoordinateNumber { nano: 123456888888i64 };
let d = CoordinateNumber::from(123456.888888f64);
let d = CoordinateNumber::try_from(123456.888888f64).unwrap();
assert_eq!(c, d);

let e = CoordinateNumber { nano: 0i64 };
let f = CoordinateNumber::from(0f64);
let f = CoordinateNumber::try_from(0f64).unwrap();
assert_eq!(e, f);
}

#[test]
/// Test how NaN is handled
fn test_try_from_f64_fail() {
let cn = CoordinateNumber::try_from(f64::NAN);
assert!(cn.is_err());

let cn = CoordinateNumber::try_from(f64::INFINITY);
assert!(cn.is_err());
}

#[test]
/// Test decimal to float conversion
fn test_into_f64() {
Expand Down
2 changes: 2 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
quick_error! {
#[derive(Debug)]
pub enum GerberError {
/// Conversion between two types failed
ConversionError(msg: String) {}
/// Bad coordinate format
CoordinateFormatError(msg: String) {}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

extern crate chrono;
extern crate uuid;
extern crate conv;
#[macro_use] extern crate quick_error;

mod types;
Expand Down

0 comments on commit d343aea

Please sign in to comment.