Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the unsafe code in Table::as_ref #146

Merged
merged 2 commits into from Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/csv.rs
Expand Up @@ -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};

Expand Down Expand Up @@ -67,14 +68,14 @@ impl super::Table {

/// Write the table to the specified writer.
pub fn to_csv<W: Write>(&self, w: W) -> Result<Writer<W>> {
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<W: Write>(&self, writer: Writer<W>) -> Result<Writer<W>> {
self.as_ref().to_csv_writer(writer)
self.as_slice().to_csv_writer(writer)
}
}

Expand Down Expand Up @@ -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");
}
}
}
10 changes: 5 additions & 5 deletions 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;

Expand All @@ -10,20 +10,20 @@ pub trait EvcxrDisplay {
fn evcxr_display(&self);
}

impl<'a, T> EvcxrDisplay for T
impl<T> EvcxrDisplay for T
where
T: AsRef<TableSlice<'a>>,
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());
}
Expand Down
79 changes: 45 additions & 34 deletions src/lib.rs
Expand Up @@ -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<Row>,
Expand Down Expand Up @@ -220,6 +220,7 @@ impl<'a> TableSlice<'a> {
out.flush()?;
Ok(())
}

}

impl<'a> IntoIterator for &'a TableSlice<'a> {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -353,13 +354,13 @@ impl Table {
/// Print the table to `out` and returns the number
/// of lines printed, or an error
pub fn print<T: Write + ?Sized>(&self, out: &mut T) -> Result<usize, Error> {
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<T: Terminal + ?Sized>(&self, out: &mut T) -> Result<usize, Error> {
self.as_ref().print_term(out)
self.as_slice().print_term(out)
}

/// Print the table to standard output. Colors won't be displayed unless
Expand All @@ -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<usize, Error> {
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
Expand All @@ -381,12 +382,29 @@ 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<T: Write + ?Sized>(&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 }
}
}

impl <T> AsTableSlice for T where T: AsRef<Table> {
fn as_slice(&self) -> TableSlice<'_> {
self.as_ref().as_slice()
}
}

Expand All @@ -412,7 +430,7 @@ impl IndexMut<usize> 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)
}
}

Expand Down Expand Up @@ -456,7 +474,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()
}
}

Expand Down Expand Up @@ -502,23 +520,19 @@ impl<'a> Iterator for ColumnIterMut<'a> {
}
}

impl<'a> AsRef<TableSlice<'a>> 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<TableSlice<'a>> for Table {
impl<'a> AsRef<TableSlice<'a>> 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
}
}


/// Trait implemented by types which can be sliced
pub trait Slice<'a, E> {
/// Type output after slicing
Expand All @@ -528,17 +542,14 @@ pub trait Slice<'a, E> {
}

impl<'a, T, E> Slice<'a, E> for T
where T: AsRef<TableSlice<'a>>,
where T: AsTableSlice,
[Row]: Index<E, Output = [Row]>
{
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
}
}

Expand Down Expand Up @@ -600,7 +611,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;

Expand Down Expand Up @@ -661,21 +672,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]
Expand Down