vscode tasks, better logging, and build numbering

This commit is contained in:
Zoe
2024-08-14 14:19:01 -05:00
parent c373d23ee0
commit fdde40e10d
15 changed files with 230 additions and 112 deletions

16
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,16 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "gdb",
"request": "attach",
"name": "Attach to QEMU",
"preLaunchTask": "(Debug) Build the kernel and run qemu",
"executable": "${workspaceFolder}/target/x86_64-unknown-none/debug/CappuccinOS.elf",
"target": ":1234",
"remote": true,
"cwd": "${workspaceRoot}",
// "gdbpath": "${workspaceRoot}/target/x86_64-unknown-none/debug/CappuccinOS.elf"
}
]
}

25
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,25 @@
{
"tasks": [
{
"type": "shell",
"label": "(Debug) Build the kernel and run qemu",
"command": "make",
"args": [
"run"
],
"options": {
"env": {
"MODE": "debug",
"GDB": "true"
},
"cwd": "${workspaceRoot}",
},
"group": {
"kind": "build",
"isDefault": true
}
}
],
"version": "2.0.0"
}

View File

@@ -22,6 +22,8 @@ QEMU_OPTS += -m ${MEMORY} -drive id=hd0,format=raw,file=${IMAGE_PATH}
LIMINE_BOOT_VARIATION = X64
LIMINE_BRANCH = v8.x-binary
KERNEL_FILE = target/${ARCH}-unknown-none/${MODE}/CappuccinOS.elf
ifeq (${MODE},release)
CARGO_OPTS += --release
endif
@@ -87,8 +89,12 @@ compile-initramfs: copy-initramfs-files
mksquashfs ${INITRAMFS_PATH} ${ARTIFACTS_PATH}/initramfs.img ${MKSQUASHFS_OPTS}
run-scripts:
# Place the build ID into the binary so it can be read at runtime
@HASH=$$(md5sum ${KERNEL_FILE} | cut -c1-12) && \
sed -i "s/__BUILD_ID__/$${HASH}/" ${KERNEL_FILE}
ifeq (${EXPORT_SYMBOLS},true)
nm target/${ARCH}-unknown-none/${MODE}/CappuccinOS.elf > scripts/symbols.table
nm ${KERNEL_FILE} > scripts/symbols.table
@if [ ! -d "scripts/rustc_demangle" ]; then \
git clone "https://github.com/juls0730/rustc_demangle.py" "scripts/rustc_demangle"; \
fi
@@ -190,7 +196,7 @@ ovmf-aarch64:
run: build ${RUN_OPTS} run-${ARCH}
run-x86_64:
qemu-system-x86_64 ${QEMU_OPTS}
tmux new-session -d -s qemu 'qemu-system-x86_64 ${QEMU_OPTS}'
run-riscv64:
qemu-system-riscv64 ${QEMU_OPTS} -cpu rv64 -device ramfb -device qemu-xhci -device usb-kbd -device virtio-scsi-pci,id=scsi -device scsi-hd,drive=hd0

View File

@@ -1,4 +1,4 @@
use crate::{drivers::acpi::SMP_REQUEST, hcf, libs::cell::OnceCell, mem::HHDM_OFFSET};
use crate::{drivers::acpi::SMP_REQUEST, hcf, libs::cell::OnceCell, mem::HHDM_OFFSET, LogLevel};
use alloc::{sync::Arc, vec::Vec};
@@ -67,7 +67,7 @@ pub struct APIC {
}
unsafe extern "C" fn test<'a>(cpu: &'a limine::smp::Cpu) -> ! {
crate::log_ok!("hey from CPU {:<02}", cpu.id);
crate::log!(LogLevel::Debug, "hey from CPU {:<02}", cpu.id);
hcf();
}
@@ -94,7 +94,11 @@ impl APIC {
let madt = madt.unwrap();
crate::log_info!("MADT located at: {:p}", core::ptr::addr_of!(madt));
crate::log!(
LogLevel::Trace,
"MADT located at: {:p}",
core::ptr::addr_of!(madt)
);
let mut lapic_ptr = (madt.inner.local_apic_address as usize + *HHDM_OFFSET) as *mut u8;
let mut io_apic = None;
@@ -149,7 +153,8 @@ impl APIC {
let io_apic_ptr = io_apic.unwrap().ptr;
crate::println!(
crate::log!(
LogLevel::Debug,
"Found {} core{}, IOAPIC {:p}, LAPIC {lapic_ptr:p}, Processor IDs:",
cpus.len(),
if cpus.len() > 1 { "s" } else { "" },
@@ -157,7 +162,7 @@ impl APIC {
);
for apic in &cpus {
crate::println!(" {}", apic.acpi_processor_id);
crate::log!(LogLevel::Debug, " {}", apic.acpi_processor_id);
}
let apic = Self {
@@ -171,9 +176,9 @@ impl APIC {
let io_apic_ver = apic.read_ioapic(0x01);
let number_of_inputs = ((io_apic_ver >> 16) & 0xFF) + 1;
let _number_of_inputs = ((io_apic_ver >> 16) & 0xFF) + 1;
crate::println!("{number_of_inputs}");
// crate::println!("{number_of_inputs}");
let smp_request = unsafe { SMP_REQUEST.get_response_mut() };

View File

@@ -1,8 +1,7 @@
use core::sync::atomic::{AtomicU8, Ordering};
use super::idt_set_gate;
use crate::hcf;
use crate::{log_error, log_info};
use crate::{hcf, log, LogLevel};
#[repr(C)]
#[derive(Clone, Copy, Debug)]
@@ -43,7 +42,7 @@ extern "C" fn exception_handler(registers: u64) {
match FAULTED.fetch_add(1, Ordering::SeqCst) {
0 => {}
1 => {
log_error!("Exception Loop detected, stopping here");
log!(LogLevel::Fatal, "Exception Loop detected, stopping here");
print_registers(&registers);
hcf();
}
@@ -55,25 +54,25 @@ extern "C" fn exception_handler(registers: u64) {
match int {
0x00 => {
log_error!("DIVISION ERROR!");
log!(LogLevel::Fatal, "DIVISION ERROR!");
}
0x06 => {
log_error!("INVALID OPCODE!");
log!(LogLevel::Fatal, "INVALID OPCODE!");
}
0x08 => {
log_error!("DOUBLE FAULT!");
log!(LogLevel::Fatal, "DOUBLE FAULT!");
}
0x0D => {
log_error!("GENERAL PROTECTION FAULT!");
log!(LogLevel::Fatal, "GENERAL PROTECTION FAULT!");
}
0x0E => {
log_error!("PAGE FAULT!");
log!(LogLevel::Fatal, "PAGE FAULT!");
}
0xFF => {
log_error!("EXCEPTION!");
log!(LogLevel::Fatal, "EXCEPTION!");
}
_ => {
log_error!("EXCEPTION!");
log!(LogLevel::Fatal, "EXCEPTION!");
}
}
@@ -83,9 +82,10 @@ extern "C" fn exception_handler(registers: u64) {
}
fn print_registers(registers: &Registers) {
log_info!("{:-^width$}", " REGISTERS ", width = 98);
log!(LogLevel::Info, "{:-^width$}", " REGISTERS ", width = 98);
log_info!(
log!(
LogLevel::Info,
"INT: {:#018X}, RIP: {:#018X}, CS: {:#018X}, FLG: {:#018X}",
registers.int,
registers.rip,
@@ -93,7 +93,8 @@ fn print_registers(registers: &Registers) {
registers.rflags
);
log_info!(
log!(
LogLevel::Info,
"RSP: {:#018X}, SS: {:#018X}, RAX: {:#018X}, RBX: {:#018X}",
registers.rsp,
registers.ss,
@@ -101,7 +102,8 @@ fn print_registers(registers: &Registers) {
registers.rbx
);
log_info!(
log!(
LogLevel::Info,
"RCX: {:#018X}, RDX: {:#018X}, RSI: {:#018X}, RDI: {:#018X}",
registers.rcx,
registers.rdx,
@@ -109,7 +111,8 @@ fn print_registers(registers: &Registers) {
registers.rdi
);
log_info!(
log!(
LogLevel::Info,
"RBP: {:#018X}, R8: {:#018X}, R9: {:#018X}, R10: {:#018X}",
registers.rbp,
registers.r8,
@@ -117,7 +120,8 @@ fn print_registers(registers: &Registers) {
registers.r10
);
log_info!(
log!(
LogLevel::Info,
"R11: {:#018X}, R12: {:#018X}, R13: {:#018X}, R14: {:#018X}",
registers.r11,
registers.r12,
@@ -125,7 +129,7 @@ fn print_registers(registers: &Registers) {
registers.r14
);
log_info!("R15: {:#018X}", registers.r15);
log!(LogLevel::Info, "R15: {:#018X}", registers.r15);
}
// *macro intensifies*

View File

@@ -1,6 +1,8 @@
pub mod apic;
pub mod exceptions;
use crate::LogLevel;
use self::apic::APIC;
#[repr(C, packed)]
@@ -78,7 +80,7 @@ pub fn idt_set_gate(num: u8, function_ptr: usize) {
}
extern "x86-interrupt" fn null_interrupt_handler() {
crate::log_info!("Unhandled interrupt!");
crate::log!(LogLevel::Debug, "Unhandled interrupt!");
signal_end_of_interrupt();
}

View File

@@ -2,8 +2,9 @@ use alloc::{borrow::ToOwned, string::String, vec::Vec};
use crate::{
drivers::fs::vfs::{vfs_open, UserCred},
log_info,
log,
mem::HHDM_OFFSET,
LogLevel,
};
// use crate::drivers::fs::vfs::VfsFileSystem;
@@ -19,7 +20,7 @@ pub fn print_stack_trace(max_frames: usize, rbp: u64) {
let mut stackframe = rbp as *const StackFrame;
let mut frames_processed = 0;
log_info!("{:-^width$}", " Stack Trace ", width = 98);
log!(LogLevel::Info, "{:-^width$}", " Stack Trace ", width = 98);
for _ in 0..max_frames {
frames_processed += 1;
@@ -44,7 +45,7 @@ pub fn print_stack_trace(max_frames: usize, rbp: u64) {
""
};
log_info!("{:#X} {address_info}", instruction_ptr);
log!(LogLevel::Info, "{:#X} {address_info}", instruction_ptr);
unsafe {
stackframe = (*stackframe).back;
@@ -52,7 +53,7 @@ pub fn print_stack_trace(max_frames: usize, rbp: u64) {
}
if frames_processed == max_frames && !stackframe.is_null() {
log_info!("... <frames omitted>");
log!(LogLevel::Info, "... <frames omitted>");
}
}

View File

@@ -4,6 +4,7 @@ use alloc::vec::Vec;
use limine::request::RsdpRequest;
use limine::request::SmpRequest;
use crate::LogLevel;
use crate::{
arch::io::{inw, outb},
libs::cell::OnceCell,
@@ -45,7 +46,7 @@ impl<'a, T> SDT<'a, T> {
let length = core::ptr::read_unaligned(ptr.add(4).cast::<u32>());
let data = core::slice::from_raw_parts(ptr, length as usize);
crate::log_serial!("SDT at: {ptr:p}\n");
crate::log!(LogLevel::Trace, "SDT at: {ptr:p}");
assert!(data.len() == length as usize);
@@ -267,11 +268,15 @@ struct FADT {
pub fn init_acpi() {
resolve_acpi();
crate::log_ok!("Found {} ACPI Tables!", ACPI.tables.len());
crate::log!(LogLevel::Trace, "Found {} ACPI Tables!", ACPI.tables.len());
crate::log_serial!("Available serial tables:\n");
crate::log!(LogLevel::Trace, "Available ACPI tables:");
for i in 0..ACPI.tables.len() {
crate::log_serial!(" {}\n", core::str::from_utf8(&ACPI.tables[i]).unwrap());
crate::log!(
LogLevel::Trace,
" {}",
core::str::from_utf8(&ACPI.tables[i]).unwrap()
);
}
let fadt = find_table::<FADT>("FACP").expect("Failed to find FADT");
@@ -283,7 +288,7 @@ pub fn init_acpi() {
#[cfg(target_arch = "x86_64")]
crate::arch::interrupts::apic::APIC
.set(crate::arch::interrupts::apic::APIC::new().expect("Failed to enable APIC!"));
crate::log_ok!("APIC enabled!");
crate::log!(LogLevel::Trace, "APIC enabled!");
}
pub fn find_table<T>(table_name: &str) -> Option<SDT<T>> {

View File

@@ -7,7 +7,7 @@ use alloc::{
vec::Vec,
};
use crate::drivers::storage::Partition;
use crate::{drivers::storage::Partition, LogLevel};
use super::vfs::{FsOps, VNode, VNodeOperations};
@@ -267,7 +267,7 @@ impl FatFs {
_ => bpb.sectors_per_fat as usize,
};
crate::println!("Found {fat_type:?} FS");
// crate::println!("Found {fat_type:?} FS");
let cluster_size = bpb.sectors_per_cluster as usize * 512;
@@ -508,8 +508,9 @@ impl FsOps for FatFs {
fat = Some(Arc::from(fat_vec));
} else {
crate::log_info!(
"\x1B[33mWARNING\x1B[0m: FAT is not being stored in memory, this feature is experimental and file reads are expected to be slower."
crate::log!(
LogLevel::Warn,
"FAT is not being stored in memory, this feature is experimental and file reads are expected to be slower."
)
}

View File

@@ -336,7 +336,10 @@ impl Squashfs<'_> {
);
}
_ => {
crate::println!("Unsupported compression type")
crate::log!(
crate::LogLevel::Error,
"Unsupported squashfs compression type"
)
}
}
} else {

View File

@@ -8,7 +8,7 @@ use alloc::{
vec::Vec,
};
use crate::{log_info, log_ok};
use crate::{log, LogLevel};
static mut NODE_TREE: Option<TreeNode> = None;
static mut ROOT_VFS: Vfs = Vfs::null();
@@ -676,16 +676,14 @@ pub fn add_vfs(mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
let vfsp = vfs.as_ptr();
log_info!("Adding vfs at {mount_point}");
log!(LogLevel::Trace, "Adding vfs at {mount_point}");
if mount_point == "/" {
if unsafe { ROOT_VFS.next.is_some() } {
return Err(());
}
crate::println!("reading the root");
let root = vfs.fs.as_mut().unwrap().as_mut().root(vfsp);
crate::println!("successfully read the root");
unsafe { NODE_TREE = Some(TreeNode::new(root)) }
} else {
if unsafe { ROOT_VFS.next.is_none() } {
@@ -705,7 +703,7 @@ pub fn add_vfs(mount_point: &str, fs_ops: Box<dyn FsOps>) -> Result<(), ()> {
unsafe { ROOT_VFS.add_vfs(vfs) };
log_ok!("Added vfs at {mount_point}");
log!(LogLevel::Trace, "Added vfs at {mount_point}");
return Ok(());
}
@@ -756,7 +754,7 @@ pub fn del_vfs(mount_point: &str) -> Result<(), ()> {
return Err(());
}
log_info!("Deleting vfs at {mount_point}");
log!(LogLevel::Trace, "Deleting vfs at {mount_point}");
if mount_point == "/" {
if unsafe { ROOT_VFS.next.as_ref().unwrap().next.is_some() } {

View File

@@ -3,6 +3,7 @@ use alloc::vec::Vec;
use crate::{
arch::io::{inl, outl},
libs::sync::Mutex,
LogLevel,
};
const PCI_CONFIG_PORT: u16 = 0xCF8; // The base I/O port for PCI configuration access
@@ -130,9 +131,9 @@ pub fn enumerate_pci_bus() {
check_bus(bus);
}
crate::println!("====== PCI DEVICES ======");
crate::log!(LogLevel::Debug, "====== PCI DEVICES ======");
for (i, pci_device) in PCI_DEVICES.lock().iter().enumerate() {
crate::println!("Entry {i:2}: {pci_device}")
crate::log!(LogLevel::Debug, "Entry {i:2}: {pci_device}")
}
}

View File

@@ -9,6 +9,8 @@ use crate::{
storage::{GPTHeader, GPTPartitionEntry, Partition, MBR},
},
libs::{sync::Mutex, uuid::Uuid},
mem::LabelBytes,
LogLevel,
};
use super::BlockDevice;
@@ -278,7 +280,7 @@ impl ATABus {
let mut buffer = [0u8; ATA_SECTOR_SIZE];
self.wait_for_drive_ready()
.map_err(|_| crate::log_error!("Error before issuing Identify command."))?;
.map_err(|_| crate::log!(LogLevel::Error, "Error before issuing Identify command."))?;
for chunk in buffer.chunks_exact_mut(core::mem::size_of::<u16>()) {
let word = inw(self.io_bar + ATADriveDataRegister::Data as u16);
@@ -423,7 +425,7 @@ impl ATABus {
let mut buffer_offset = 0;
for _ in 0..sector_count {
self.wait_for_drive_ready()
.map_err(|_| crate::log_error!("Error reading IDE Device"))?;
.map_err(|_| crate::log!(LogLevel::Error, "Error reading IDE Device"))?;
// # Safety
//
@@ -563,7 +565,8 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
}
}
crate::log_info!(
crate::log!(
LogLevel::Trace,
"ATA: Detected {} drive{}",
drives_lock.len(),
match drives_lock.len() {
@@ -575,10 +578,11 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
for drive in drives_lock.iter() {
let sectors = drive.sector_count();
crate::log_info!(
"ATA: Drive 0 has {} sectors ({} MB)",
crate::log!(
LogLevel::Trace,
"ATA: Drive 0 has {} sectors ({})",
sectors,
(sectors * ATA_SECTOR_SIZE as u64) / 1024 / 1024
((sectors as usize) * ATA_SECTOR_SIZE).label_bytes()
);
let mbr_sector: MBR = (*drive.read(0, 1).expect("Failed to read first sector")).into();
@@ -609,13 +613,13 @@ fn ide_initialize(bar0: u32, bar1: u32, _bar2: u32, _bar3: u32, _bar4: u32) {
)
.expect("Failed to read partition table");
crate::println!(
"{}, {}, {}, {:X?}",
(gpt.partition_entry_count * gpt.partition_entry_size) as usize / ATA_SECTOR_SIZE,
gpt.partition_entry_count,
gpt.partition_entry_size,
gpt.guid
);
// crate::println!(
// "{}, {}, {}, {:X?}",
// (gpt.partition_entry_count * gpt.partition_entry_size) as usize / ATA_SECTOR_SIZE,
// gpt.partition_entry_count,
// gpt.partition_entry_size,
// gpt.guid
// );
for i in 0..gpt.partition_entry_count {
let entry_offset = (i * gpt.partition_entry_size) as usize;

View File

@@ -5,7 +5,7 @@
use alloc::vec::Vec;
use limine::{request::KernelFileRequest, BaseRevision};
use mem::HHDM_OFFSET;
use mem::{LabelBytes, HHDM_OFFSET, PHYSICAL_MEMORY_MANAGER};
use crate::drivers::fs::{
initramfs,
@@ -19,6 +19,11 @@ pub mod drivers;
pub mod libs;
pub mod mem;
// the build id will be an md5sum of the kernel binary and will replace __BUILD_ID__ in the final binary
pub static BUILD_ID: &str = "__BUILD_ID__";
pub static LOG_LEVEL: u8 = if cfg!(debug_assertions) { 1 } else { 2 };
// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
#[used]
// The .requests section allows limine to find the requests faster and more safely.
@@ -47,6 +52,8 @@ pub extern "C" fn _start() -> ! {
}
pub fn kmain() -> ! {
print_boot_info();
let _ = drivers::fs::vfs::add_vfs("/", alloc::boxed::Box::new(initramfs::init()));
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -102,10 +109,6 @@ pub fn kmain() -> ! {
.read(0, 0, 0)
);
unsafe {
*(0xDEADBEEF as *mut u32) = 0xBAADF00D;
};
// let file = vfs_open("/example.txt").unwrap();
// as a sign that we didnt panic
@@ -163,6 +166,26 @@ fn draw_gradient() {
.dealloc((buffer_ptr as usize - *HHDM_OFFSET) as *mut u8, pages);
}
fn print_boot_info() {
crate::println!("╔═╗───────────────────╔╗────╔═╗╔══╗");
crate::println!("║╔╝╔═╗ ╔═╗╔═╗╔╦╗╔═╗╔═╗╠╣╔═╦╗║║║║══╣");
crate::println!("║╚╗║╬╚╗║╬║║╬║║║║║═╣║═╣║║║║║║║║║╠══║");
crate::println!("╚═╝╚══╝║╔╝║╔╝╚═╝╚═╝╚═╝╚╝╚╩═╝╚═╝╚══╝");
crate::println!("───────╚╝─╚╝ ©juls0730 {BUILD_ID}");
crate::println!(
"{} of memory available",
PHYSICAL_MEMORY_MANAGER.total_memory().label_bytes()
);
crate::println!(
"The kernel was built in {} mode",
if cfg!(debug_assertions) {
"debug"
} else {
"release"
}
)
}
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
@@ -176,26 +199,31 @@ macro_rules! print {
)
}
#[macro_export]
macro_rules! log_info {
($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[90m? \x1B[97m]\x1B[0m {}", &alloc::format!($($arg)*)));
#[repr(u8)]
enum LogLevel {
Trace = 0,
Debug,
Info,
Warn,
Error,
Fatal,
}
#[macro_export]
macro_rules! log_serial {
($($arg:tt)*) => (
$crate::drivers::serial::write_string(&alloc::format!($($arg)*).replace('\n', "\n\r"))
);
macro_rules! log {
($level:expr, $($arg:tt)*) => {{
if ($level as u8) >= $crate::LOG_LEVEL {
let color_code = match $level {
$crate::LogLevel::Trace => "\x1B[90m",
$crate::LogLevel::Debug => "\x1B[94m",
$crate::LogLevel::Info => "\x1B[92m",
$crate::LogLevel::Warn => "\x1B[93m",
$crate::LogLevel::Error => "\x1B[91m",
$crate::LogLevel::Fatal => "\x1B[95m",
};
$crate::println!("\x1B[97m[ {}* \x1B[97m]\x1B[0;m {}", color_code, &alloc::format!($($arg)*))
}
#[macro_export]
macro_rules! log_error {
($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[91m! \x1B[97m]\x1B[0m {}", &alloc::format!($($arg)*)));
}
#[macro_export]
macro_rules! log_ok {
($($arg:tt)*) => ($crate::println!("\x1B[97m[ \x1B[92m* \x1B[97m]\x1B[0;m {}", &alloc::format!($($arg)*)));
}};
}
#[derive(Debug)]
@@ -229,7 +257,7 @@ fn parse_kernel_cmdline() {
let kernel_arguments = cmdline.unwrap().split_whitespace().collect::<Vec<&str>>();
crate::println!("{kernel_arguments:?}");
// crate::log!(LogLevel::Trace, "{kernel_arguments:?}");
for item in kernel_arguments {
let parts: Vec<&str> = item.split('=').collect();

View File

@@ -55,56 +55,75 @@ pub fn init_allocator() {
drop(allocator_lock);
crate::println!(
"{} of memory available",
PHYSICAL_MEMORY_MANAGER.total_memory().label_bytes()
);
// log_memory_map();
}
pub enum Label {
BYTE(usize),
KIB(usize),
MIB(usize),
GIB(usize),
pub enum ByteLabelKind {
BYTE,
KIB,
MIB,
GIB,
}
impl core::fmt::Display for Label {
pub struct ByteLabel {
byte_label: ByteLabelKind,
count: usize,
}
impl core::fmt::Display for ByteLabel {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Label::BYTE(count) => {
write!(f, "{count} Byte(s)")
let size = self.count;
match self.byte_label {
ByteLabelKind::BYTE => {
write!(f, "{size} Byte")?;
}
Label::KIB(count) => {
write!(f, "{count} KiB(s)")
ByteLabelKind::KIB => {
write!(f, "{size} KiB")?;
}
Label::MIB(count) => {
write!(f, "{count} MiB(s)")
ByteLabelKind::MIB => {
write!(f, "{size} MiB")?;
}
Label::GIB(count) => {
write!(f, "{count} GiB(s)")
ByteLabelKind::GIB => {
write!(f, "{size} GiB")?;
}
}
if size != 1 {
write!(f, "s")?;
}
return Ok(());
}
}
pub trait LabelBytes {
fn label_bytes(&self) -> Label;
fn label_bytes(&self) -> ByteLabel;
}
impl LabelBytes for usize {
fn label_bytes(&self) -> Label {
fn label_bytes(&self) -> ByteLabel {
let bytes = *self;
let mut byte_label = ByteLabel {
byte_label: ByteLabelKind::BYTE,
count: bytes,
};
if bytes >> 30 > 0 {
return Label::GIB(bytes >> 30);
byte_label.byte_label = ByteLabelKind::GIB;
byte_label.count = bytes >> 30;
// return Label::GIB(bytes >> 30);
} else if bytes >> 20 > 0 {
return Label::MIB(bytes >> 20);
byte_label.byte_label = ByteLabelKind::MIB;
byte_label.count = bytes >> 20;
// return Label::MIB(bytes >> 20);
} else if bytes >> 10 > 0 {
return Label::KIB(bytes >> 10);
} else {
return Label::BYTE(bytes);
byte_label.byte_label = ByteLabelKind::KIB;
byte_label.count = bytes >> 10;
// return Label::KIB(bytes >> 10);
}
return byte_label;
}
}