use std::fmt::Display;
use std::io::Write;
pub fn best_effort<T, E: Display>(result: Result<T, E>, ctx: &str) -> Option<T> {
match result {
Ok(value) => Some(value),
Err(error) => {
tracing::debug!(context = ctx, %error, "best-effort step failed; continuing");
None
}
}
}
pub fn send_to_consumer<T>(tx: &crossbeam_channel::Sender<T>, event: T) -> bool {
let delivered = tx.send(event).is_ok();
if !delivered {
tracing::trace!("consumer already stopped; event dropped");
}
delivered
}
pub fn no_channel_left<T, E>(result: Result<T, E>) {
drop(result.err());
}
pub fn settle_error_report(written: anyhow::Result<()>, status: u8) -> u8 {
let Err(error) = written else {
return status;
};
let closed_reader = matches!(
error.downcast_ref::<crate::error::AtomwriteError>(),
Some(crate::error::AtomwriteError::BrokenPipe)
) || crate::runtime::find_io_error(&error)
== Some(std::io::ErrorKind::BrokenPipe);
if closed_reader {
return crate::constants::EXIT_BROKEN_PIPE as u8;
}
no_channel_left(writeln!(
std::io::stderr(),
"atomwrite: could not write the error report: {error:#}"
));
status
}
#[cfg(test)]
mod tests {
use super::{best_effort, no_channel_left, settle_error_report};
#[test]
fn ok_value_is_returned() {
assert_eq!(best_effort(Ok::<_, String>(7), "step"), Some(7));
}
#[test]
fn error_is_discarded() {
assert_eq!(best_effort(Err::<u8, _>("boom"), "step"), None);
}
#[test]
fn no_channel_left_accepts_both_outcomes() {
no_channel_left(Ok::<_, String>(()));
no_channel_left(Err::<(), _>("gone"));
}
#[test]
fn send_reports_whether_the_consumer_was_there() {
let (tx, rx) = crossbeam_channel::unbounded::<u8>();
assert!(super::send_to_consumer(&tx, 1));
assert_eq!(rx.recv(), Ok(1));
drop(rx);
assert!(!super::send_to_consumer(&tx, 2));
}
#[test]
fn delivered_report_keeps_the_status() {
assert_eq!(settle_error_report(Ok(()), 65), 65);
}
#[test]
fn closed_reader_wins_over_the_status() {
let closed = std::io::Error::from(std::io::ErrorKind::BrokenPipe);
assert_eq!(settle_error_report(Err(closed.into()), 65), 141);
let typed = crate::error::AtomwriteError::BrokenPipe;
assert_eq!(settle_error_report(Err(typed.into()), 65), 141);
}
#[test]
fn other_write_failure_keeps_the_status() {
let denied = std::io::Error::from(std::io::ErrorKind::PermissionDenied);
assert_eq!(settle_error_report(Err(denied.into()), 65), 65);
}
}