use crate::executor::SearchResult;
use std::io::Write;
use std::time::SystemTime;
pub struct OutputFormatter {
use_color: bool,
print0: bool,
}
impl OutputFormatter {
#[must_use]
pub fn new(use_color: bool, print0: bool) -> Self {
OutputFormatter { use_color, print0 }
}
pub fn write_result<W: Write>(
&mut self,
out: &mut W,
result: &SearchResult,
is_winner: bool,
follow_symlinks: bool,
show_index: bool,
_index_width: usize,
) -> std::io::Result<()> {
if show_index {
write!(out, "{:>4} ", format!("[{}]", result.path_index))?;
}
let path_str = result.path.display().to_string();
if self.use_color && is_winner {
write!(out, "\x1b[1;32m{path_str}\x1b[0m")?;
} else {
write!(out, "{path_str}")?;
}
if follow_symlinks {
if let Some(ref canonical) = result.canonical_path {
if canonical != &result.path {
write!(out, " → {}", canonical.display())?;
}
}
}
if self.print0 {
write!(out, "\0")?;
} else {
writeln!(out)?;
}
if let Some(ref meta) = result.metadata {
writeln!(
out,
" inode: {}, device: {}, size: {} bytes",
meta.ino, meta.dev, meta.size
)?;
if let Some(ctime) = meta.ctime {
writeln!(out, " created: {}", Self::format_time(ctime))?;
}
if let Some(mtime) = meta.mtime {
writeln!(out, " modified: {}", Self::format_time(mtime))?;
}
}
Ok(())
}
fn format_time(time: SystemTime) -> String {
use std::time::UNIX_EPOCH;
let duration = time.duration_since(UNIX_EPOCH).unwrap_or_default();
let secs = duration.as_secs();
let days_since_epoch = secs / 86400;
let seconds_today = secs % 86400;
let mut year = 1970;
let mut days_left = days_since_epoch;
loop {
let days_in_year = if Self::is_leap_year(year) { 366 } else { 365 };
if days_left < days_in_year {
break;
}
days_left -= days_in_year;
year += 1;
}
let days_in_months = if Self::is_leap_year(year) {
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
} else {
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
};
let mut month = 1;
let mut day = days_left + 1;
for &days_in_month in &days_in_months {
#[allow(clippy::cast_sign_loss)]
let days_in_month_u64 = days_in_month as u64;
if day <= days_in_month_u64 {
break;
}
day -= days_in_month_u64;
month += 1;
}
let hour = (seconds_today / 3600) as u32;
let minute = ((seconds_today % 3600) / 60) as u32;
let second = (seconds_today % 60) as u32;
format!("{year}-{month:02}-{day:02} {hour:02}:{minute:02}:{second:02}")
}
fn is_leap_year(year: u64) -> bool {
(year.is_multiple_of(4) && !year.is_multiple_of(100)) || year.is_multiple_of(400)
}
}