Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions module/core/format_tools/src/format/output_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
mod private
{

use std::borrow::Cow;

use crate::*;
use print::
{
Expand Down Expand Up @@ -78,6 +80,36 @@ mod private
}
}

/// Print table, which is constructed with vectors and `Cow`s, with the
/// specified output formatter.
///
/// This function is useful when you do not want to use `AsTable`, or implement `Fields`, and
/// other traits, but you just have string slices in vectors.
///
/// `rows` should not contain header of the table, it will be automatically added if `has_header`
/// is true.
pub fn vector_table_write< 'data, 'context >
(
column_names : Vec< Cow< 'data, str > >,
has_header : bool,
rows : Vec< Vec< Cow< 'data, str > > >,
c : &mut Context< 'context >,
) -> fmt::Result
{
InputExtract::extract_from_raw_table
(
column_names,
has_header,
rows,
c.printer.filter_col,
c.printer.filter_row,
| x |
{
c.printer.output_format.extract_write( x, c )
}
)
}

}

mod table;
Expand Down Expand Up @@ -106,6 +138,7 @@ pub mod own
#[ doc( inline ) ]
pub use private::
{
vector_table_write,
};

}
Expand Down
112 changes: 64 additions & 48 deletions module/core/format_tools/src/format/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,44 +354,89 @@ mod private
}
}


/// Extract input data from and collect it in a format consumable by output formatter.
pub fn extract< 't, 'context, Table, RowKey, Row, CellKey>
pub fn extract< 'context, Table, RowKey, Row, CellKey>
(
table : &'t Table,
table : &'data Table,
filter_col : &'context ( dyn FilterCol + 'context ),
filter_row : &'context ( dyn FilterRow + 'context ),
callback : impl for< 'a2 > FnOnce( &'a2 InputExtract< 'a2 > ) -> fmt::Result,
)
-> fmt::Result
where
'data : 't,
// 't : 'data,
Table : TableRows< RowKey = RowKey, Row = Row, CellKey = CellKey >,
Table : TableHeader< CellKey = CellKey >,
RowKey : table::RowKey,
Row : Cells< CellKey > + 'data,
Row : Cells< CellKey > + 'data,
CellKey : table::CellKey + ?Sized + 'data,
// CellRepr : table::CellRepr,
{
let rows = table.rows().map( | r | r.cells().map( | ( _, c ) | {
match c
{
Some( c ) => c,
None => Cow::from( "" ),
}
}).collect()).collect();

let has_header = table.header().is_some();

let column_names = match table.header()
{
Some( header ) => header.map( | ( k, _ ) | Cow::from( k.borrow() ) ).collect(),

None => match table.rows().next()
{
Some( r ) => r.cells().map( | ( k, _ ) | Cow::from( k.borrow() ) ).collect(),
None => Vec::new()
}
};

Self::extract_from_raw_table
(
column_names,
has_header,
rows,
filter_col,
filter_row,
callback,
)
}

/// Extract input data from a table that is constructed with vectors and `Cow`s and collect
/// it in a format consumable by output formatter.
///
/// `rows` should not contain header of the table, it will be automatically added if `has_header`
/// is true.
pub fn extract_from_raw_table< 'context >
(
column_names : Vec< Cow< 'data, str > >,
has_header : bool,
rows : Vec< Vec< Cow< 'data, str > > >,
filter_col : &'context ( dyn FilterCol + 'context ),
filter_row : &'context ( dyn FilterRow + 'context ),
callback : impl for< 'a2 > FnOnce( &'a2 InputExtract< 'a2 > ) -> fmt::Result,
) -> fmt::Result
{
// let mcells = table.mcells();
let mut mcells_vis = [ 0 ; 2 ];
let mut mcells = [ 0 ; 2 ];
let mut mchars = [ 0 ; 2 ];

// key width, index
let mut key_to_ikey : HashMap< &'t CellKey, usize > = HashMap::new();
let mut key_to_ikey : HashMap< Cow< 'data, str >, usize > = HashMap::new();

let mut col_descriptors : Vec< ColDescriptor< '_ > > = Vec::with_capacity( mcells[ 0 ] );
let mut row_descriptors : Vec< RowDescriptor > = Vec::with_capacity( mcells[ 1 ] );
let mut has_header = false;

let mut data : Vec< Vec< ( Cow< 't, str >, [ usize ; 2 ] ) > > = Vec::new();
let rows = table.rows();
let mut data : Vec< Vec< ( Cow< 'data, str >, [ usize ; 2 ] ) > > = Vec::new();
let mut irow : usize = 0;
let filter_col_need_args = filter_col.need_args();
// let filter_row_need_args = filter_row.need_args();

let mut row_add = | row_iter : &'_ mut dyn _IteratorTrait< Item = ( &'t CellKey, Cow< 't, str > ) >, typ : LineType |
let mut row_add = | row_data : Vec< Cow< 'data, str > >, typ : LineType |
{

irow = row_descriptors.len();
Expand All @@ -401,18 +446,21 @@ mod private
let mut ncol = 0;
let mut ncol_vis = 0;

let fields : Vec< ( Cow< 't, str >, [ usize ; 2 ] ) > = row_iter
let fields : Vec< ( Cow< 'data, str >, [ usize ; 2 ] ) > = row_data
.into_iter()
.enumerate()
.filter_map
(
| ( key, val ) |
| ( ikey, val ) |
{
let key = &column_names[ ikey ];
let l = col_descriptors.len();

ncol += 1;

if filter_col_need_args
{
if !filter_col.filter_col( key.borrow() )
if !filter_col.filter_col( key.as_ref() )
{
return None;
}
Expand All @@ -430,7 +478,7 @@ mod private
let sz = string::size( &val );

key_to_ikey
.entry( key )
.entry( key.clone() )
.and_modify( | icol |
{
let col = &mut col_descriptors[ *icol ];
Expand Down Expand Up @@ -469,18 +517,9 @@ mod private

// process header first

if let Some( header ) = table.header()
if has_header
{
rows.len().checked_add( 1 ).expect( "Table has too many rows" );
// assert!( header.len() <= usize::MAX, "Header of a table has too many cells" );
has_header = true;

let mut row2 = header.map( | ( key, title ) |
{
( key, Cow::Borrowed( title ) )
});

row_add( &mut row2, LineType::Header );
row_add( column_names.clone(), LineType::Header );
}

// Collect rows
Expand All @@ -489,30 +528,7 @@ mod private
{
// assert!( row.cells().len() <= usize::MAX, "Row of a table has too many cells" );

let mut row2 = row
.cells()
.map
(
| ( key, val ) |
{

let val = match val
{
Some( val ) =>
{
val
}
None =>
{
Cow::Borrowed( "" )
}
};

return ( key, val );
}
);

row_add( &mut row2, LineType::Regular );
row_add( row, LineType::Regular );
}

// calculate size in chars
Expand Down
59 changes: 59 additions & 0 deletions module/core/format_tools/tests/inc/table_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,62 @@ fn iterator_over_strings()
// assert!( got.contains( "│ 1627845583 │ [ │ │" ) );

}

#[ test ]
fn test_vector_table()
{
let column_names : Vec< Cow< 'static, str > > = vec![
"id".into(),
"created_at".into(),
"file_ids".into(),
"tools".into(),
];

let rows : Vec< Vec< Cow< 'static, str > > > = vec!
[
vec!
[
"1".into(),
"1627845583".into(),
"[ file1, file2 ]".into(),
"".into(),
],

vec!
[
"2".into(),
"13".into(),
"[ file3, file4 ]".into(),
"[ tool1 ]".into(),
],
];

use the_module::
{
output_format,
filter,
print,
};

let mut output = String::new();
let mut context = print::Context::new( &mut output, Default::default() );

let res = output_format::vector_table_write
(
column_names,
true,
rows,
&mut context,
);

assert!( res.is_ok() );

println!( "{}", output );

let exp = r#"│ id │ created_at │ file_ids │ tools │
──────────────────────────────────────────────────
│ 1 │ 1627845583 │ [ file1, file2 ] │ │
│ 2 │ 13 │ [ file3, file4 ] │ [ tool1 ] │"#;

a_id!( output.as_str(), exp );
}
Loading