Add sampler module

This commit is contained in:
Rico Riedel 2022-07-29 17:27:14 +02:00
parent 2bdd88a7e8
commit 60ccd12e4b
No known key found for this signature in database
GPG Key ID: 75AC868575DE7B18
5 changed files with 195 additions and 1 deletions

View File

@ -1,6 +1,7 @@
pub mod error; pub mod error;
mod pattern; pub mod pattern;
pub mod printer; pub mod printer;
pub mod sampler;
pub mod term; pub mod term;
mod vec; mod vec;

61
src/sampler/char.rs Normal file
View File

@ -0,0 +1,61 @@
pub trait CharConverter {
fn convert(&self, level: f32) -> char;
}
pub struct CharConverterImpl {
chars: String,
}
impl CharConverterImpl {
pub fn new(chars: String) -> Self {
Self { chars }
}
}
impl CharConverter for CharConverterImpl {
fn convert(&self, level: f32) -> char {
assert!(level >= 0.0);
assert!(level < 1.0);
let index = (level * self.chars.len() as f32) as usize;
self.chars.chars().nth(index).unwrap()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
#[should_panic]
fn convert_index_below_zero() {
CharConverterImpl::new("abc".to_string()).convert(-0.1);
}
#[test]
fn convert_index_zero() {
let converter = CharConverterImpl::new("abc".to_string());
assert_eq!('a', converter.convert(0.0));
}
#[test]
fn convert() {
let converter = CharConverterImpl::new("abc".to_string());
assert_eq!('b', converter.convert(0.5));
}
#[test]
#[should_panic]
fn convert_index_one() {
CharConverterImpl::new("abc".to_string()).convert(1.0);
}
#[test]
#[should_panic]
fn convert_index_above_one() {
CharConverterImpl::new("abc".to_string()).convert(1.1);
}
}

64
src/sampler/color.rs Normal file
View File

@ -0,0 +1,64 @@
use crossterm::style::Color;
pub trait ColorConverter {
fn convert(&self, level: f32) -> Color;
}
pub struct ColorConverterImpl {
colors: Vec<Color>,
}
impl ColorConverterImpl {
pub fn new(colors: Vec<Color>) -> Self {
Self { colors }
}
}
impl ColorConverter for ColorConverterImpl {
fn convert(&self, level: f32) -> Color {
assert!(level >= 0.0);
assert!(level < 1.0);
let index = (level * self.colors.len() as f32) as usize;
self.colors[index]
}
}
#[cfg(test)]
mod test {
use super::*;
use crossterm::style::Color::*;
#[test]
#[should_panic]
fn convert_index_below_zero() {
ColorConverterImpl::new(vec![Red, Green, Blue]).convert(-0.1);
}
#[test]
fn convert_index_zero() {
let converter = ColorConverterImpl::new(vec![Red, Green, Blue]);
assert!(matches!(converter.convert(0.0), Red));
}
#[test]
fn convert() {
let converter = ColorConverterImpl::new(vec![Red, Green, Blue]);
assert!(matches!(converter.convert(0.5), Green));
}
#[test]
#[should_panic]
fn convert_index_one() {
ColorConverterImpl::new(vec![Red, Green, Blue]).convert(1.0);
}
#[test]
#[should_panic]
fn convert_index_above_one() {
ColorConverterImpl::new(vec![Red, Green, Blue]).convert(1.1);
}
}

65
src/sampler/level.rs Normal file
View File

@ -0,0 +1,65 @@
pub enum Level {
Keep,
Draw(f32),
Clear,
}
pub trait LevelConverter {
fn convert(&self, level: f32) -> Level;
}
#[derive(Default)]
pub struct LevelConverterImpl;
impl LevelConverter for LevelConverterImpl {
fn convert(&self, level: f32) -> Level {
if level < 0.0 {
Level::Keep
} else if level < 1.0 {
Level::Draw(level)
} else {
Level::Clear
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn convert_keep() {
let converter = LevelConverterImpl::default();
assert!(matches!(converter.convert(-0.1), Level::Keep));
}
#[test]
fn convert_draw() {
let converter = LevelConverterImpl::default();
if let Level::Draw(level) = converter.convert(0.0) {
assert_eq!(0.0, level);
} else {
panic!();
}
if let Level::Draw(level) = converter.convert(0.5) {
assert_eq!(0.5, level);
} else {
panic!();
}
if let Level::Draw(level) = converter.convert(0.9) {
assert_eq!(0.9, level);
} else {
panic!();
}
}
#[test]
fn convert_clear() {
let converter = LevelConverterImpl::default();
assert!(matches!(converter.convert(1.0), Level::Clear));
assert!(matches!(converter.convert(1.5), Level::Clear));
}
}

3
src/sampler/mod.rs Normal file
View File

@ -0,0 +1,3 @@
mod color;
mod level;
mod char;