//! This module contains a [`Rotate`] primitive which can be used in order to rotate [`Table`]. //! //! It's also possible to transpose the table at the point of construction. //! See [`Builder::index`]. //! //! # Example //! #![cfg_attr(feature = "std", doc = "```")] #![cfg_attr(not(feature = "std"), doc = "```ignore")] //! use tabled::{Table, settings::Rotate}; //! //! let data = [[1, 2, 3], [4, 5, 6]]; //! //! let table = Table::new(data).with(Rotate::Left).to_string(); //! //! assert_eq!( //! table, //! concat!( //! "+---+---+---+\n", //! "| 2 | 3 | 6 |\n", //! "+---+---+---+\n", //! "| 1 | 2 | 5 |\n", //! "+---+---+---+\n", //! "| 0 | 1 | 4 |\n", //! "+---+---+---+", //! ) //! ); //! ``` //! //! [`Table`]: crate::Table //! [`Builder::index`]: crate::builder::Builder::index // use core::cmp::max; use core::cmp::max; use crate::{ grid::records::{ExactRecords, Records, Resizable}, settings::TableOption, }; /// Rotate can be used to rotate a table by 90 degrees. #[derive(Debug)] pub enum Rotate { /// Rotate [`Table`] to the left. /// /// [`Table`]: crate::Table Left, /// Rotate [`Table`] to the right. /// /// [`Table`]: crate::Table Right, /// Rotate [`Table`] to the top. /// /// So the top becomes the bottom. /// /// [`Table`]: crate::Table Top, /// Rotate [`Table`] to the bottom. /// /// So the top becomes the bottom. /// /// [`Table`]: crate::Table Bottom, } impl TableOption for Rotate where R: Records + ExactRecords + Resizable, { fn change(self, records: &mut R, _: &mut C, _: &mut D) { let count_rows = records.count_rows(); let count_cols = records.count_columns(); match self { Self::Left => { 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), (row, col)); } } 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); } } } Self::Right => { 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), (row, col)); } } 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); } } } Self::Bottom | Self::Top => { 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), (row, col)); } } } } } }