From 5561da6a1d5700580bc439c57797f34d1a54f21f Mon Sep 17 00:00:00 2001 From: why8ther Date: Fri, 2 Dec 2022 21:09:06 +0800 Subject: [PATCH 1/2] Remove the unsafe code in Table::as_ref --- src/csv.rs | 7 ++--- src/evcxr.rs | 10 ++++---- src/lib.rs | 72 +++++++++++++++++++++++++++------------------------- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/csv.rs b/src/csv.rs index 9c5cd9f853..db70328481 100644 --- a/src/csv.rs +++ b/src/csv.rs @@ -3,6 +3,7 @@ use csv; pub use self::csv::{Reader, Writer, Result, ReaderBuilder}; +use crate::AsTableSlice; use std::path::Path; use std::io::{Read, Write}; @@ -67,14 +68,14 @@ impl super::Table { /// Write the table to the specified writer. pub fn to_csv(&self, w: W) -> Result> { - self.as_ref().to_csv(w) + self.as_slice().to_csv(w) } /// Write the table to the specified writer. /// /// This allows for format customisation. pub fn to_csv_writer(&self, writer: Writer) -> Result> { - self.as_ref().to_csv_writer(writer) + self.as_slice().to_csv_writer(writer) } } @@ -147,4 +148,4 @@ mod tests { assert_eq!(table.get_row(1).unwrap().get_cell(2).unwrap().get_content(), "C"); assert_eq!(table.get_row(2).unwrap().get_cell(1).unwrap().get_content(), "DEFG"); } -} \ No newline at end of file +} diff --git a/src/evcxr.rs b/src/evcxr.rs index 11d632acc2..6df05efd5e 100644 --- a/src/evcxr.rs +++ b/src/evcxr.rs @@ -1,6 +1,6 @@ //! This modules contains traits and implementations to work within Evcxr -use super::TableSlice; +use super::AsTableSlice; use super::utils::StringWriter; use std::io::Write; @@ -10,20 +10,20 @@ pub trait EvcxrDisplay { fn evcxr_display(&self); } -impl<'a, T> EvcxrDisplay for T +impl EvcxrDisplay for T where - T: AsRef>, + T: AsTableSlice, { fn evcxr_display(&self) { let mut writer = StringWriter::new(); // Plain Text let _ = writer.write_all(b"EVCXR_BEGIN_CONTENT text/plain\n"); - let _ = self.as_ref().print(&mut writer); + let _ = self.as_slice().print(&mut writer); let _ = writer.write_all(b"\nEVCXR_END_CONTENT\n"); // Html let _ = writer.write_all(b"EVCXR_BEGIN_CONTENT text/html\n"); - let _ = self.as_ref().print_html(&mut writer); + let _ = self.as_slice().print_html(&mut writer); let _ = writer.write_all(b"\nEVCXR_END_CONTENT\n"); println!("{}", writer.as_string()); } diff --git a/src/lib.rs b/src/lib.rs index 977f58d306..94c4bb9c8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,7 +59,7 @@ pub struct Table { /// # } /// ``` /// -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct TableSlice<'a> { format: &'a TableFormat, titles: &'a Option, @@ -220,6 +220,7 @@ impl<'a> TableSlice<'a> { out.flush()?; Ok(()) } + } impl<'a> IntoIterator for &'a TableSlice<'a> { @@ -259,7 +260,7 @@ impl Table { // #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")] #[cfg(test)] // Only used for testing for now pub (crate) fn get_column_num(&self) -> usize { - self.as_ref().get_column_num() + self.as_slice().get_column_num() } /// Get the number of rows @@ -353,13 +354,13 @@ impl Table { /// Print the table to `out` and returns the number /// of lines printed, or an error pub fn print(&self, out: &mut T) -> Result { - self.as_ref().print(out) + self.as_slice().print(out) } /// Print the table to terminal `out`, applying styles when needed and returns the number /// of lines printed, or an error pub fn print_term(&self, out: &mut T) -> Result { - self.as_ref().print_term(out) + self.as_slice().print_term(out) } /// Print the table to standard output. Colors won't be displayed unless @@ -371,7 +372,7 @@ impl Table { /// # Returns /// A `Result` holding the number of lines printed, or an `io::Error` if any failure happens pub fn print_tty(&self, force_colorize: bool) -> Result { - self.as_ref().print_tty(force_colorize) + self.as_slice().print_tty(force_colorize) } /// Print the table to standard output. Colors won't be displayed unless @@ -381,12 +382,23 @@ impl Table { /// Any failure to print is ignored. For better control, use `print_tty()`. /// Calling `printstd()` is equivalent to calling `print_tty(false)` and ignoring the result. pub fn printstd(&self) { - self.as_ref().printstd() + self.as_slice().printstd() } /// Print table in HTML format to `out`. pub fn print_html(&self, out: &mut T) -> Result<(), Error> { - self.as_ref().print_html(out) + self.as_slice().print_html(out) + } + +} + +trait AsTableSlice { + fn as_slice(&self) -> TableSlice<'_> ; +} + +impl AsTableSlice for Table { + fn as_slice(&self) -> TableSlice<'_> { + TableSlice { format: &self.format, titles: &self.titles, rows: &self.rows } } } @@ -412,7 +424,7 @@ impl IndexMut for Table { impl fmt::Display for Table { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_ref().fmt(fmt) + self.as_slice().fmt(fmt) } } @@ -456,7 +468,7 @@ impl<'a> IntoIterator for &'a Table { type Item = &'a Row; type IntoIter = Iter<'a, Row>; fn into_iter(self) -> Self::IntoIter { - self.as_ref().row_iter() + self.row_iter() } } @@ -502,20 +514,15 @@ impl<'a> Iterator for ColumnIterMut<'a> { } } -impl<'a> AsRef> for TableSlice<'a> { - fn as_ref(&self) -> &TableSlice<'a> { - self +impl <'a> AsTableSlice for TableSlice<'a> { + fn as_slice(&self) -> TableSlice<'_> { + *self } } -impl<'a> AsRef> for Table { +impl<'a> AsRef> for TableSlice<'a> { fn as_ref(&self) -> &TableSlice<'a> { - unsafe { - // All this is a bit hacky. Let's try to find something else - let s = &mut *((self as *const Table) as *mut Table); - s.rows.shrink_to_fit(); - &*(self as *const Table as *const TableSlice<'a>) - } + self } } @@ -528,17 +535,14 @@ pub trait Slice<'a, E> { } impl<'a, T, E> Slice<'a, E> for T - where T: AsRef>, + where T: AsTableSlice, [Row]: Index { type Output = TableSlice<'a>; fn slice(&'a self, arg: E) -> Self::Output { - let sl = self.as_ref(); - TableSlice { - format: sl.format, - titles: sl.titles, - rows: sl.rows.index(arg), - } + let mut sl = self.as_slice(); + sl.rows = sl.rows.index(arg); + sl } } @@ -600,7 +604,7 @@ macro_rules! ptable { #[cfg(test)] mod tests { - use crate::{Table, Slice, Row, Cell, format}; + use crate::{Table, Slice, Row, Cell, format, AsTableSlice}; use format::consts::{FORMAT_DEFAULT, FORMAT_NO_LINESEP, FORMAT_NO_COLSEP, FORMAT_CLEAN, FORMAT_BOX_CHARS}; use crate::utils::StringWriter; @@ -661,21 +665,21 @@ mod tests { fn table_size() { let mut table = Table::new(); assert!(table.is_empty()); - assert!(table.as_ref().is_empty()); + assert!(table.as_slice().is_empty()); assert_eq!(table.len(), 0); - assert_eq!(table.as_ref().len(), 0); + assert_eq!(table.as_slice().len(), 0); assert_eq!(table.get_column_num(), 0); - assert_eq!(table.as_ref().get_column_num(), 0); + assert_eq!(table.as_slice().get_column_num(), 0); table.add_empty_row(); assert!(!table.is_empty()); - assert!(!table.as_ref().is_empty()); + assert!(!table.as_slice().is_empty()); assert_eq!(table.len(), 1); - assert_eq!(table.as_ref().len(), 1); + assert_eq!(table.as_slice().len(), 1); assert_eq!(table.get_column_num(), 0); - assert_eq!(table.as_ref().get_column_num(), 0); + assert_eq!(table.as_slice().get_column_num(), 0); table[0].add_cell(Cell::default()); assert_eq!(table.get_column_num(), 1); - assert_eq!(table.as_ref().get_column_num(), 1); + assert_eq!(table.as_slice().get_column_num(), 1); } #[test] From b412a700dfe03bebdc971e25e9b30ed2bd23da51 Mon Sep 17 00:00:00 2001 From: why8ther Date: Mon, 12 Dec 2022 05:48:31 +0000 Subject: [PATCH 2/2] Implement `AsTableSlice` for `AsRef` for better backward compatibility --- src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 94c4bb9c8e..330c99104c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -402,6 +402,12 @@ impl AsTableSlice for Table { } } +impl AsTableSlice for T where T: AsRef
{ + fn as_slice(&self) -> TableSlice<'_> { + self.as_ref().as_slice() + } +} + impl Index for Table { type Output = Row; fn index(&self, idx: usize) -> &Self::Output { @@ -526,6 +532,7 @@ impl<'a> AsRef> for TableSlice<'a> { } } + /// Trait implemented by types which can be sliced pub trait Slice<'a, E> { /// Type output after slicing