filebyte 1.4.7

A powerful CLI tool for analyzing files and directories with detailed metadata, permissions, and size information
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone)]
pub enum SizeUnit {
    Bytes,
    Kilobytes,
    Megabytes,
    Gigabytes,
    Terabytes,
    Bits,
    Kilobits,
    Megabits,
    Gigabits,
    Terabits,
}

#[derive(Debug, Clone)]
pub enum SortBy {
    Name,
    Size,
    Date,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileInfo {
    pub name: String,
    pub path: String,
    pub size: u64,
    pub size_human: String,
    pub file_type: String,
    pub created: Option<String>,
    pub modified: Option<String>,
    pub permissions: String,
    pub is_directory: bool,
}

impl SizeUnit {
    pub fn from_str(s: &str) -> Result<Self, String> {
        match s.to_lowercase().as_str() {
            "b" | "bytes" => Ok(SizeUnit::Bytes),
            "kb" | "kilobytes" => Ok(SizeUnit::Kilobytes),
            "mb" | "megabytes" => Ok(SizeUnit::Megabytes),
            "gb" | "gigabytes" => Ok(SizeUnit::Gigabytes),
            "tb" | "terabytes" => Ok(SizeUnit::Terabytes),
            "bits" => Ok(SizeUnit::Bits),
            "kbits" | "kilobits" => Ok(SizeUnit::Kilobits),
            "mbits" | "megabits" => Ok(SizeUnit::Megabits),
            "gbits" | "gigabits" => Ok(SizeUnit::Gigabits),
            "tbits" | "terabits" => Ok(SizeUnit::Terabits),
            "auto" => Ok(SizeUnit::Bytes),
            _ => Err(format!("Invalid size unit: {}", s)),
        }
    }

    pub fn format_size(&self, bytes: u64) -> String {
        match self {
            SizeUnit::Bytes => format!("{} B", bytes),
            SizeUnit::Kilobytes => format!("{:.2} KB", bytes as f64 / 1024.0),
            SizeUnit::Megabytes => format!("{:.2} MB", bytes as f64 / (1024.0 * 1024.0)),
            SizeUnit::Gigabytes => format!("{:.2} GB", bytes as f64 / (1024.0 * 1024.0 * 1024.0)),
            SizeUnit::Terabytes => format!("{:.2} TB", bytes as f64 / (1024.0 * 1024.0 * 1024.0 * 1024.0)),
            SizeUnit::Bits => format!("{} b", bytes * 8),
            SizeUnit::Kilobits => format!("{:.2} Kb", (bytes * 8) as f64 / 1000.0),
            SizeUnit::Megabits => format!("{:.2} Mb", (bytes * 8) as f64 / 1_000_000.0),
            SizeUnit::Gigabits => format!("{:.2} Gb", (bytes * 8) as f64 / 1_000_000_000.0),
            SizeUnit::Terabits => format!("{:.2} Tb", (bytes * 8) as f64 / 1_000_000_000_000.0),
        }
    }

    pub fn auto_format_size(bytes: u64) -> String {
        let units = [
            (SizeUnit::Terabytes, 1024u64.pow(4)),
            (SizeUnit::Gigabytes, 1024u64.pow(3)),
            (SizeUnit::Megabytes, 1024u64.pow(2)),
            (SizeUnit::Kilobytes, 1024u64),
            (SizeUnit::Bytes, 1),
        ];

        for (unit, threshold) in units.iter() {
            if bytes >= *threshold {
                return unit.format_size(bytes);
            }
        }
        format!("{} B", bytes)
    }
}