#![cfg_attr(feature = "std", doc = "```")]
#![cfg_attr(not(feature = "std"), doc = "```ignore")]
use core::cmp::max;
use crate::{
grid::records::{ExactRecords, Records, Resizable},
settings::TableOption,
};
#[derive(Debug)]
pub enum Rotate {
Left,
Right,
Top,
Bottom,
}
impl<R, D, C> TableOption<R, C, D> for Rotate
where
R: Records + ExactRecords + Resizable,
{
fn change(self, records: &mut R, _: &mut C, _: &mut D) {
match self {
Self::Left => rotate_left(records),
Self::Right => rotate_right(records),
Self::Bottom | Self::Top => rotate_horizontal(records),
}
}
}
fn rotate_horizontal<R>(records: &mut R)
where
R: Records + ExactRecords + Resizable,
{
let count_rows = records.count_rows();
let count_cols = records.count_columns();
for row in 0..count_rows / 2 {
for col in 0..count_cols {
let last_row = count_rows - row - 1;
records.swap((last_row, col).into(), (row, col).into());
}
}
}
fn rotate_left<R>(records: &mut R)
where
R: Records + ExactRecords + Resizable,
{
let count_rows = records.count_rows();
let count_cols = records.count_columns();
let size = max(count_rows, count_cols);
{
for _ in count_rows..size {
records.push_row();
}
for _ in count_cols..size {
records.push_column();
}
}
for col in 0..size {
for row in col..size {
records.swap((col, row).into(), (row, col).into());
}
}
for row in 0..count_cols / 2 {
records.swap_row(row, count_cols - row - 1);
}
{
for (shift, row) in (count_rows..size).enumerate() {
let row = row - shift;
records.remove_column(row);
}
for (shift, col) in (count_cols..size).enumerate() {
let col = col - shift;
records.remove_row(col);
}
}
}
fn rotate_right<R>(records: &mut R)
where
R: Records + ExactRecords + Resizable,
{
let count_rows = records.count_rows();
let count_cols = records.count_columns();
let size = max(count_rows, count_cols);
{
for _ in count_rows..size {
records.push_row();
}
for _ in count_cols..size {
records.push_column();
}
}
for col in 0..size {
for row in col..size {
records.swap((col, row).into(), (row, col).into());
}
}
for col in 0..count_rows / 2 {
records.swap_column(col, count_rows - col - 1);
}
{
for (shift, row) in (count_rows..size).enumerate() {
let row = row - shift;
records.remove_column(row);
}
for (shift, col) in (count_cols..size).enumerate() {
let col = col - shift;
records.remove_row(col);
}
}
}