Skip to content

Commit

Permalink
READY : format_tools - alternative API function (#1496)
Browse files Browse the repository at this point in the history
* Continue to work on

* Improvements

* Make test

* Remove unnecessary fields

* Fix from merge
  • Loading branch information
InAnYan authored Nov 22, 2024
1 parent ea86324 commit 3620512
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 48 deletions.
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 );
}

0 comments on commit 3620512

Please sign in to comment.