mark error paths as #[cold]

This commit is contained in:
poz 2025-12-12 22:45:55 +01:00
commit f18aaa4945
No known key found for this signature in database
6 changed files with 50 additions and 18 deletions

View file

@ -1,5 +1,9 @@
use std::ffi::CStr; use std::ffi::CStr;
#[inline]
#[cold]
const fn unknown() -> &'static str { "Unknown" }
#[must_use] #[must_use]
#[cfg_attr(feature = "hotpath", hotpath::measure)] #[cfg_attr(feature = "hotpath", hotpath::measure)]
pub fn get_desktop_info() -> String { pub fn get_desktop_info() -> String {
@ -7,9 +11,9 @@ pub fn get_desktop_info() -> String {
let desktop_str = unsafe { let desktop_str = unsafe {
let ptr = libc::getenv(c"XDG_CURRENT_DESKTOP".as_ptr()); let ptr = libc::getenv(c"XDG_CURRENT_DESKTOP".as_ptr());
if ptr.is_null() { if ptr.is_null() {
"Unknown" unknown()
} else { } 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) s.strip_prefix("none+").unwrap_or(s)
} }
}; };
@ -17,10 +21,10 @@ pub fn get_desktop_info() -> String {
let backend_str = unsafe { let backend_str = unsafe {
let ptr = libc::getenv(c"XDG_SESSION_TYPE".as_ptr()); let ptr = libc::getenv(c"XDG_SESSION_TYPE".as_ptr());
if ptr.is_null() { if ptr.is_null() {
"Unknown" unknown()
} else { } else {
let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown"); let s = CStr::from_ptr(ptr).to_str().unwrap_or_else(|_| unknown());
if s.is_empty() { "Unknown" } else { s } if s.is_empty() { unknown() } else { s }
} }
}; };

View file

@ -6,7 +6,13 @@ pub mod syscall;
pub mod system; pub mod system;
pub mod uptime; pub mod uptime;
use std::mem::MaybeUninit; use std::{io, mem::MaybeUninit};
#[inline]
#[cold]
pub fn last_os_error<T>() -> io::Result<T> {
Err(io::Error::last_os_error())
}
/// Wrapper for `libc::utsname` with safe accessor methods /// Wrapper for `libc::utsname` with safe accessor methods
pub struct UtsName(libc::utsname); pub struct UtsName(libc::utsname);
@ -20,7 +26,7 @@ impl UtsName {
pub fn uname() -> Result<Self, std::io::Error> { pub fn uname() -> Result<Self, std::io::Error> {
let mut uts = MaybeUninit::uninit(); let mut uts = MaybeUninit::uninit();
if unsafe { libc::uname(uts.as_mut_ptr()) } != 0 { 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() })) Ok(Self(unsafe { uts.assume_init() }))
} }

View file

@ -8,7 +8,7 @@ mod uptime;
use std::io::{self, Cursor, Write}; use std::io::{self, Cursor, Write};
pub use microfetch_lib::UtsName; pub use microfetch_lib::{UtsName, last_os_error};
use crate::{ use crate::{
desktop::get_desktop_info, desktop::get_desktop_info,

View file

@ -10,6 +10,8 @@
use std::io; use std::io;
use crate::last_os_error;
/// Direct syscall to open a file /// Direct syscall to open a file
/// ///
/// # Returns /// # Returns
@ -169,6 +171,12 @@ pub unsafe fn sys_close(fd: i32) -> i32 {
} }
} }
#[inline]
#[cold]
fn path_too_long() -> io::Result<usize> {
Err(io::Error::new(io::ErrorKind::InvalidInput, "Path too long"))
}
/// Read entire file using direct syscalls. This avoids libc overhead and can be /// Read entire file using direct syscalls. This avoids libc overhead and can be
/// significantly faster for small files. /// significantly faster for small files.
/// ///
@ -182,7 +190,7 @@ pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result<usize> {
// Use stack-allocated buffer for null-terminated path (max 256 bytes) // Use stack-allocated buffer for null-terminated path (max 256 bytes)
let path_bytes = path.as_bytes(); let path_bytes = path.as_bytes();
if path_bytes.len() >= 256 { 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]; let mut path_buf = [0u8; 256];
@ -192,14 +200,14 @@ pub fn read_file_fast(path: &str, buffer: &mut [u8]) -> io::Result<usize> {
unsafe { unsafe {
let fd = sys_open(path_buf.as_ptr(), O_RDONLY); let fd = sys_open(path_buf.as_ptr(), O_RDONLY);
if fd < 0 { 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 bytes_read = sys_read(fd, buffer.as_mut_ptr(), buffer.len());
let _ = sys_close(fd); let _ = sys_close(fd);
if bytes_read < 0 { if bytes_read < 0 {
return Err(io::Error::last_os_error()); return last_os_error();
} }
#[allow(clippy::cast_sign_loss)] #[allow(clippy::cast_sign_loss)]

View file

@ -1,6 +1,14 @@
use std::{ffi::CStr, fmt::Write as _, io, mem::MaybeUninit}; 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] #[must_use]
#[cfg_attr(feature = "hotpath", hotpath::measure)] #[cfg_attr(feature = "hotpath", hotpath::measure)]
@ -8,12 +16,12 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String {
let username = unsafe { let username = unsafe {
let ptr = libc::getenv(c"USER".as_ptr()); let ptr = libc::getenv(c"USER".as_ptr());
if ptr.is_null() { if ptr.is_null() {
"unknown_user" unknown_user()
} else { } 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() let capacity = COLORS.yellow.len()
+ username.len() + username.len()
@ -35,13 +43,17 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String {
result result
} }
#[inline]
#[cold]
const fn unknown_shell() -> &'static str { "unknown_shell" }
#[must_use] #[must_use]
#[cfg_attr(feature = "hotpath", hotpath::measure)] #[cfg_attr(feature = "hotpath", hotpath::measure)]
pub fn get_shell() -> String { pub fn get_shell() -> String {
unsafe { unsafe {
let ptr = libc::getenv(c"SHELL".as_ptr()); let ptr = libc::getenv(c"SHELL".as_ptr());
if ptr.is_null() { if ptr.is_null() {
return "unknown_shell".into(); return unknown_shell().into();
} }
let bytes = CStr::from_ptr(ptr).to_bytes(); let bytes = CStr::from_ptr(ptr).to_bytes();
@ -63,7 +75,7 @@ pub fn get_root_disk_usage() -> Result<String, io::Error> {
let path = b"/\0"; let path = b"/\0";
if unsafe { libc::statvfs(path.as_ptr().cast(), vfs.as_mut_ptr()) } != 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() }; let vfs = unsafe { vfs.assume_init() };

View file

@ -1,5 +1,7 @@
use std::{io, mem::MaybeUninit}; use std::{io, mem::MaybeUninit};
use crate::last_os_error;
/// Faster integer to string conversion without the formatting overhead. /// Faster integer to string conversion without the formatting overhead.
#[inline] #[inline]
fn itoa(mut n: u64, buf: &mut [u8]) -> &str { fn itoa(mut n: u64, buf: &mut [u8]) -> &str {
@ -73,7 +75,7 @@ pub fn get_current() -> Result<String, io::Error> {
let uptime_seconds = { let uptime_seconds = {
let mut info = MaybeUninit::uninit(); let mut info = MaybeUninit::uninit();
if unsafe { sys_sysinfo(info.as_mut_ptr()) } != 0 { 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)] #[allow(clippy::cast_sign_loss)]
unsafe { unsafe {