use std::slice::{Iter, IterMut};
static BLOCK_SEPARATOR: &str = ",";
#[derive(Default)]
pub struct BlockBuilder {
size: BlockSize,
min_size: f64,
max_size: f64,
}
impl BlockBuilder {
pub fn new() -> Self {
BlockBuilder::default()
}
pub fn size(mut self, size: BlockSize) -> Self {
self.size = size;
self
}
pub fn min_size(mut self, min_size: f64) -> Self {
self.min_size = min_size;
self
}
pub fn max_size(mut self, max_size: f64) -> Self {
self.max_size = max_size;
self
}
pub fn build(self) -> Block {
Block {
size: self.size,
min_size: self.min_size,
max_size: self.max_size,
current_size: 0.0,
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Block {
pub size: BlockSize,
pub min_size: f64,
pub max_size: f64,
current_size: f64,
}
impl Block {
#[inline]
pub fn create() -> BlockBuilder {
BlockBuilder::new()
}
pub fn size(&self) -> BlockSize {
self.size
}
pub fn current_size(&self) -> f64 {
self.current_size
}
pub fn set_current_size(&mut self, size: f64) {
self.current_size = if self.min_size == 0.0 && self.max_size == 0.0 && size > 0.0 {
size
} else if size < self.min_size && self.min_size > 0.0 {
self.min_size
} else if size > self.max_size && self.max_size > 0.0 {
self.max_size
} else {
size
};
}
}
impl From<&str> for Block {
fn from(t: &str) -> Self {
if let Ok(size) = t.parse::<f64>() {
return Block::create().size(BlockSize::Size(size)).build();
}
match t {
"Auto" | "auto" => Block::create().size(BlockSize::Auto).build(),
_ => Block::create().size(BlockSize::Stretch).build(),
}
}
}
impl From<f64> for Block {
fn from(t: f64) -> Self {
Block::create().size(BlockSize::Size(t)).build()
}
}
impl From<i32> for Block {
fn from(t: i32) -> Self {
Block::create().size(BlockSize::Size(t.into())).build()
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BlockSize {
Auto,
Stretch,
Size(f64),
}
impl Default for BlockSize {
fn default() -> Self {
BlockSize::Stretch
}
}
#[derive(Default)]
pub struct BlocksBuilder {
blocks: Vec<Block>,
}
impl BlocksBuilder {
pub fn new() -> Self {
BlocksBuilder::default()
}
pub fn push<C: Into<Block>>(mut self, block: C) -> Self {
self.blocks.push(block.into());
self
}
#[inline(always)]
#[deprecated = "Use push instead"]
pub fn block<C: Into<Block>>(self, block: C) -> Self {
self.push(block)
}
pub fn blocks<R: Into<Block> + Clone>(mut self, blocks: &[R]) -> Self {
for block in blocks.to_vec() {
self.blocks.push(block.into());
}
self
}
pub fn repeat<R: Into<Block> + Copy>(mut self, block: R, count: usize) -> Self {
for _ in 0..count {
self.blocks.push(block.into())
}
self
}
pub fn build(self) -> Blocks {
Blocks(self.blocks)
}
}
impl From<BlocksBuilder> for Blocks {
fn from(builder: BlocksBuilder) -> Self {
builder.build()
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Blocks(pub Vec<Block>);
#[deprecated = "Will be removed on 0.3.1-alpha5. Use `Blocks` instead"]
pub type Columns = Blocks;
#[deprecated = "Will be removed on 0.3.1-alpha5. Use `Blocks` instead"]
pub type Rows = Blocks;
impl Blocks {
#[inline]
pub fn create() -> BlocksBuilder {
BlocksBuilder::new()
}
pub fn get(&self, block: usize) -> Option<&Block> {
self.0.get(block)
}
pub fn get_mut(&mut self, block: usize) -> Option<&mut Block> {
self.0.get_mut(block)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> Iter<Block> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> IterMut<Block> {
self.0.iter_mut()
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl From<&str> for Blocks {
fn from(blocks: &str) -> Self {
let blocks = blocks.replace(" ", "");
let mut block_builder = BlocksBuilder::new();
for block in blocks.split(BLOCK_SEPARATOR) {
block_builder = block_builder.push(Block::from(block));
}
block_builder.build()
}
}
impl From<String> for Blocks {
fn from(blocks: String) -> Self {
Self::from(blocks.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
const ERROR: f64 = f64::EPSILON;
#[test]
fn test_size() {
let size = BlockSize::Size(64.0);
let builder = BlockBuilder::new();
let block = builder.size(size).build();
assert_eq!(block.size, size);
}
#[test]
fn test_min_size() {
let min_size = 64.0;
let builder = BlockBuilder::new();
let block = builder.min_size(min_size).build();
assert!((block.min_size - min_size).abs() < ERROR);
}
#[test]
fn test_max_size() {
let max_size = 64.0;
let builder = BlockBuilder::new();
let block = builder.max_size(max_size).build();
assert!((block.max_size - max_size) < ERROR);
}
#[test]
fn test_set_current_size() {
let out_one_size = 10.0;
let out_two_size = 66.0;
let min_size = 14.0;
let max_size = 64.0;
let builder = BlockBuilder::new();
let mut block = builder.min_size(min_size).max_size(max_size).build();
block.set_current_size(out_one_size);
assert!((block.current_size() - min_size).abs() < ERROR);
block.set_current_size(out_two_size);
assert!((block.current_size() - max_size).abs() < ERROR);
}
#[test]
fn test_block() {
let builder = BlocksBuilder::new();
let blocks = builder.build();
assert_eq!(blocks.len(), 0);
let builder = BlocksBuilder::new();
let blocks = builder
.push(Block::create().build())
.push(Block::create().build())
.build();
assert_eq!(blocks.len(), 2);
}
#[test]
fn test_block_size_into() {
let block: Block = "Auto".into();
assert_eq!(block.size(), BlockSize::Auto);
let block: Block = "auto".into();
assert_eq!(block.size(), BlockSize::Auto);
let block: Block = "Stretch".into();
assert_eq!(block.size(), BlockSize::Stretch);
let block: Block = "stretch".into();
assert_eq!(block.size(), BlockSize::Stretch);
let block: Block = "*".into();
assert_eq!(block.size(), BlockSize::Stretch);
let block: Block = "other".into();
assert_eq!(block.size(), BlockSize::Stretch);
let block: Block = 64.0.into();
assert_eq!(block.size(), BlockSize::Size(64.0));
}
}