#[macro_use] extern crate approx; use std::ops; #[derive(Debug, Copy, Clone)] pub struct Color { red: f32, green: f32, blue: f32, } impl Color { pub fn new(red: f32, green: f32, blue: f32) -> Color { Color { red, green, blue, } } pub fn red(&self) -> f32 { self.red } pub fn green(&self) -> f32 { self.green } pub fn blue(&self) -> f32 { self.blue } pub fn ppm_str(&self) -> String { // need to scale 0 - 1 -> 0 - 255 let r = (self.red * 255.0) as u8; let g = (self.green * 255.0) as u8; let b = (self.blue * 255.0) as u8; format!("{} {} {}", r, g, b) } } impl PartialEq for Color { fn eq(&self, _rhs: &Self) -> bool { relative_eq!(self.red, _rhs.red) && relative_eq!(self.green, _rhs.green) && relative_eq!(self.blue, _rhs.blue) } } impl ops::Add for Color { type Output = Color; fn add(self, _rhs: Color) -> Color { Color::new( self.red + _rhs.red, self.green + _rhs.green, self.blue + _rhs.blue, ) } } impl ops::Mul for Color { type Output = Color; fn mul(self, _rhs: Color) -> Color { Color::new( self.red * _rhs.red, self.green * _rhs.green, self.blue * _rhs.blue, ) } } impl ops::Mul for Color { type Output = Color; fn mul(self, _rhs: i32) -> Color { let val = _rhs as f32; Color::new( self.red * val, self.green * val, self.blue * val, ) } } impl ops::Sub for Color { type Output = Color; fn sub(self, _rhs: Color) -> Color { Color::new( self.red - _rhs.red, self.green - _rhs.green, self.blue - _rhs.blue, ) } } #[cfg(test)] mod tests { use super::*; #[test] fn color() { let c = Color::new(-0.5, 0.4, 1.7); assert_eq!(-0.5, c.red); assert_eq!(0.4, c.green); assert_eq!(1.7, c.blue); } #[test] fn add() { let c1 = Color::new(0.9, 0.6, 0.75); let c2 = Color::new(0.7, 0.1, 0.25); let res = Color::new(1.6, 0.7, 1.0); assert_eq!(res, c1 + c2); } #[test] fn sub() { let c1 = Color::new(0.9, 0.6, 0.75); let c2 = Color::new(0.7, 0.1, 0.25); let res = Color::new(0.2, 0.5, 0.5); assert_eq!(res, c1 - c2); } #[test] fn mul_by_scalar() { let c = Color::new(0.9, 0.6, 0.75); let res = Color::new(1.8, 1.2, 1.5); assert_eq!(res, c * 2); } #[test] fn mul() { let c1 = Color::new(1.0, 0.2, 0.4); let c2 = Color::new(0.9, 1.0, 0.1); let res = Color::new(0.9, 0.2, 0.04); assert_eq!(res, c1 * c2); } }