From f18aaa494551c8e8c61b8922ae329f69d7d64e47 Mon Sep 17 00:00:00 2001 From: poz Date: Fri, 12 Dec 2025 22:45:55 +0100 Subject: [PATCH] mark error paths as #[cold] --- src/desktop.rs | 14 +++++++++----- src/lib.rs | 10 ++++++++-- src/main.rs | 2 +- src/syscall.rs | 14 +++++++++++--- src/system.rs | 24 ++++++++++++++++++------ src/uptime.rs | 4 +++- 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/desktop.rs b/src/desktop.rs index ab285c5..19a154a 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -1,5 +1,9 @@ use std::ffi::CStr; +#[inline] +#[cold] +const fn unknown() -> &'static str { "Unknown" } + #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_desktop_info() -> String { @@ -7,9 +11,9 @@ pub fn get_desktop_info() -> String { let desktop_str = unsafe { let ptr = libc::getenv(c"XDG_CURRENT_DESKTOP".as_ptr()); if ptr.is_null() { - "Unknown" + unknown() } else { - let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown"); + let s = CStr::from_ptr(ptr).to_str().unwrap_or_else(|_| unknown()); s.strip_prefix("none+").unwrap_or(s) } }; @@ -17,10 +21,10 @@ pub fn get_desktop_info() -> String { let backend_str = unsafe { let ptr = libc::getenv(c"XDG_SESSION_TYPE".as_ptr()); if ptr.is_null() { - "Unknown" + unknown() } else { - let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown"); - if s.is_empty() { "Unknown" } else { s } + let s = CStr::from_ptr(ptr).to_str().unwrap_or_else(|_| unknown()); + if s.is_empty() { unknown() } else { s } } }; diff --git a/src/lib.rs b/src/lib.rs index 18a992e..9a177e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,13 @@ pub mod syscall; pub mod system; pub mod uptime; -use std::mem::MaybeUninit; +use std::{io, mem::MaybeUninit}; + +#[inline] +#[cold] +pub fn last_os_error() -> io::Result { + Err(io::Error::last_os_error()) +} /// Wrapper for `libc::utsname` with safe accessor methods pub struct UtsName(libc::utsname); @@ -20,7 +26,7 @@ impl UtsName { pub fn uname() -> Result { let mut uts = MaybeUninit::uninit(); if unsafe { libc::uname(uts.as_mut_ptr()) } != 0 { - return Err(std::io::Error::last_os_error()); + return last_os_error(); } Ok(Self(unsafe { uts.assume_init() })) } diff --git a/src/main.rs b/src/main.rs index 176e5c0..0263c15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod uptime; use std::io::{self, Cursor, Write}; -pub use microfetch_lib::UtsName; +pub use microfetch_lib::{UtsName, last_os_error}; use crate::{ desktop::get_desktop_info, diff --git a/src/syscall.rs b/src/syscall.rs index 0c8634b..1afda3a 100644 --- a/src/syscall.rs +++ b/src/syscall.rs @@ -10,6 +10,8 @@ use std::io; +use crate::last_os_error; + /// Direct syscall to open a file /// /// # Returns @@ -169,6 +171,12 @@ pub unsafe fn sys_close(fd: i32) -> i32 { } } +#[inline] +#[cold] +fn path_too_long() -> io::Result { + Err(io::Error::new(io::ErrorKind::InvalidInput, "Path too long")) +} + /// Read entire file using direct syscalls. This avoids libc overhead and can be /// significantly faster for small files. /// @@ -182,7 +190,7 @@ pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result { // Use stack-allocated buffer for null-terminated path (max 256 bytes) let path_bytes = path.as_bytes(); if path_bytes.len() >= 256 { - return Err(io::Error::new(io::ErrorKind::InvalidInput, "Path too long")); + return path_too_long(); } let mut path_buf = [0u8; 256]; @@ -192,14 +200,14 @@ pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result { unsafe { let fd = sys_open(path_buf.as_ptr(), O_RDONLY); if fd < 0 { - return Err(io::Error::last_os_error()); + return last_os_error(); } let bytes_read = sys_read(fd, buffer.as_mut_ptr(), buffer.len()); let _ = sys_close(fd); if bytes_read < 0 { - return Err(io::Error::last_os_error()); + return last_os_error(); } #[allow(clippy::cast_sign_loss)] diff --git a/src/system.rs b/src/system.rs index ba8fe79..a152210 100644 --- a/src/system.rs +++ b/src/system.rs @@ -1,6 +1,14 @@ use std::{ffi::CStr, fmt::Write as _, io, mem::MaybeUninit}; -use crate::{UtsName, colors::COLORS, syscall::read_file_fast}; +use crate::{colors::COLORS, last_os_error, syscall::read_file_fast, UtsName}; + +#[inline] +#[cold] +const fn unknown_user() -> &'static str { "unknown_user" } + +#[inline] +#[cold] +const fn unknown_host() -> &'static str { "unknown_host" } #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] @@ -8,12 +16,12 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String { let username = unsafe { let ptr = libc::getenv(c"USER".as_ptr()); if ptr.is_null() { - "unknown_user" + unknown_user() } else { - CStr::from_ptr(ptr).to_str().unwrap_or("unknown_user") + CStr::from_ptr(ptr).to_str().unwrap_or_else(|_| unknown_user()) } }; - let hostname = utsname.nodename().to_str().unwrap_or("unknown_host"); + let hostname = utsname.nodename().to_str().unwrap_or_else(|_| unknown_host()); let capacity = COLORS.yellow.len() + username.len() @@ -35,13 +43,17 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String { result } +#[inline] +#[cold] +const fn unknown_shell() -> &'static str { "unknown_shell" } + #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_shell() -> String { unsafe { let ptr = libc::getenv(c"SHELL".as_ptr()); if ptr.is_null() { - return "unknown_shell".into(); + return unknown_shell().into(); } let bytes = CStr::from_ptr(ptr).to_bytes(); @@ -63,7 +75,7 @@ pub fn get_root_disk_usage() -> Result { let path = b"/\0"; if unsafe { libc::statvfs(path.as_ptr().cast(), vfs.as_mut_ptr()) } != 0 { - return Err(io::Error::last_os_error()); + return last_os_error(); } let vfs = unsafe { vfs.assume_init() }; diff --git a/src/uptime.rs b/src/uptime.rs index 095af7d..6a2cdfb 100644 --- a/src/uptime.rs +++ b/src/uptime.rs @@ -1,5 +1,7 @@ use std::{io, mem::MaybeUninit}; +use crate::last_os_error; + /// Faster integer to string conversion without the formatting overhead. #[inline] fn itoa(mut n: u64, buf: &mut [u8]) -> &str { @@ -73,7 +75,7 @@ pub fn get_current() -> Result { let uptime_seconds = { let mut info = MaybeUninit::uninit(); if unsafe { sys_sysinfo(info.as_mut_ptr()) } != 0 { - return Err(io::Error::last_os_error()); + return last_os_error(); } #[allow(clippy::cast_sign_loss)] unsafe {