use std::cmp::Ordering;
use super::Item;
#[ derive( Clone, Copy, Debug, Default, PartialEq, Eq ) ]
pub enum SortKey
{
#[ default ]
Name,
Accessed,
Size,
}
#[ derive( Clone, Copy, Debug, Default, PartialEq, Eq ) ]
pub struct Directions
{
pub name: bool,
pub accessed: bool,
pub size: bool,
}
impl Directions
{
pub fn descending( self, key: SortKey ) -> bool
{
match key
{
SortKey::Name => self.name,
SortKey::Accessed => self.accessed,
SortKey::Size => self.size,
}
}
fn set( &mut self, key: SortKey, descending: bool )
{
match key
{
SortKey::Name => self.name = descending,
SortKey::Accessed => self.accessed = descending,
SortKey::Size => self.size = descending,
}
}
}
#[ derive( Clone, Copy, Debug, Default, PartialEq, Eq ) ]
pub struct Sort
{
pub key: SortKey,
pub directions: Directions,
}
impl Sort
{
pub fn descending( self ) -> bool
{
self.directions.descending( self.key )
}
pub fn select( self, key: SortKey ) -> Self
{
Sort { key, ..self }
}
pub fn with_direction( mut self, key: SortKey, descending: bool ) -> Self
{
self.directions.set( key, descending );
self.select( key )
}
pub( crate ) fn compare( self, a: &Item, b: &Item ) -> Ordering
{
let by_key = match self.key
{
SortKey::Name => Ordering::Equal,
SortKey::Accessed => a.accessed.cmp( &b.accessed ),
SortKey::Size => if a.is_dir || b.is_dir { Ordering::Equal } else { a.size.cmp( &b.size ) },
};
let by_name = a.name.to_lowercase().cmp( &b.name.to_lowercase() ).then_with( || a.name.cmp( &b.name ) );
let order = by_key.then( by_name );
b.is_dir.cmp( &a.is_dir ).then( if self.descending() { order.reverse() } else { order } )
}
}