use std::io::ErrorKind;
use suno_core::{FfmpegError, FsError};
pub const DISK_FULL_HINT: &str = "the destination disk is full; free space and re-run.";
pub fn is_out_of_space(err: &std::io::Error) -> bool {
matches!(
err.kind(),
ErrorKind::StorageFull | ErrorKind::QuotaExceeded
)
}
pub fn anyhow_is_out_of_space(err: &anyhow::Error) -> bool {
err.chain().any(link_is_out_of_space)
}
fn link_is_out_of_space(err: &(dyn std::error::Error + 'static)) -> bool {
if let Some(io) = err.downcast_ref::<std::io::Error>() {
return is_out_of_space(io);
}
if let Some(fs) = err.downcast_ref::<FsError>() {
return fs.is_out_of_space();
}
if let Some(ff) = err.downcast_ref::<FfmpegError>() {
return ff.is_out_of_space();
}
false
}
#[cfg(test)]
mod tests {
use super::*;
use anyhow::Context;
#[test]
fn enospc_and_quota_are_out_of_space() {
assert!(is_out_of_space(&std::io::Error::from_raw_os_error(28)));
assert!(is_out_of_space(&std::io::Error::from(
ErrorKind::QuotaExceeded
)));
}
#[test]
fn a_generic_io_error_is_not_out_of_space() {
assert!(!is_out_of_space(&std::io::Error::from(
ErrorKind::PermissionDenied
)));
}
#[test]
fn anyhow_walks_the_chain_for_an_out_of_space_source() {
let err = Err::<(), _>(std::io::Error::from_raw_os_error(28))
.context("could not write scratch")
.unwrap_err();
assert!(anyhow_is_out_of_space(&err));
}
#[test]
fn anyhow_without_an_out_of_space_source_is_false() {
let err = Err::<(), _>(std::io::Error::from(ErrorKind::PermissionDenied))
.context("could not write scratch")
.unwrap_err();
assert!(!anyhow_is_out_of_space(&err));
}
#[test]
fn anyhow_detects_a_typed_out_of_space_fs_error() {
let err = anyhow::Error::from(FsError::out_of_space("no space left to write x"));
assert!(anyhow_is_out_of_space(&err));
}
#[test]
fn anyhow_detects_a_typed_out_of_space_ffmpeg_error() {
let err = anyhow::Error::from(FfmpegError::out_of_space("no space left to transcode"));
assert!(anyhow_is_out_of_space(&err));
}
#[test]
fn anyhow_ignores_a_generic_typed_error() {
assert!(!anyhow_is_out_of_space(&anyhow::Error::from(FsError::new(
"permission denied"
))));
assert!(!anyhow_is_out_of_space(&anyhow::Error::from(
FfmpegError::new("bad input")
)));
}
}