You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
3.0 KiB

use super::*;
use std::{
io::{self,},
fmt,
error,
num::NonZeroUsize,
};
#[derive(Debug)]
pub enum ErrorLocation {
Oneesan,
Imouto,
Internal,
}
#[derive(Debug)]
pub struct Error {
explination: String,
bytes_done: Option<NonZeroUsize>,
location: ErrorLocation,
inner: Option<io::Error>,
}
fn clamp(value: i64, min: i64, max: i64) -> i64
{
if value < min {
min
} else if value > max {
max
} else {
value
}
}
fn human_bytes(bytes: usize) -> String
{
const POSTFIXES: [&'static str; 7] = ["b", "kb", "mb", "gb", "tb", "pb", "eb"];
if bytes == 0 {
return format!("0 {}", POSTFIXES[0]);
}
let idx = (bytes as f64).log(1024f64).floor() as i64;
let suf = &POSTFIXES[clamp(idx, 0, 6) as usize];
let num = (1024_i64).pow(idx as u32);
format!("{:.2} {}", num, suf)
}
impl Error {
pub fn new(expl: String, from: ErrorLocation, bytes_done: usize) -> Self {
Self {
explination: expl,
location: from,
inner: None,
bytes_done: NonZeroUsize::new(bytes_done),
}
}
}
impl From<io::Error> for Error
{
fn from(f: io::Error) -> Self {
Self {
explination: format!("i/o error: "),
location: ErrorLocation::Internal,
bytes_done: None,
inner: Some(f),
}
}
}
impl fmt::Display for ErrorLocation
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorLocation::Oneesan => write!(f, "<onee>"),
ErrorLocation::Imouto => write!(f, "<imou>"),
_ => write!(f, "<internal>"),
}
}
}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}+{}: {}{}", self.location, match &self.bytes_done {
Some(value) => human_bytes(value.get()),
None => "0 b".to_owned(),
}, self.explination, match &self.inner {
Some(inner) => format!(" {}", inner),
None => "".to_owned(),
})
}
}
impl error::Error for Error
{
fn source(&self) -> Option<&(dyn error::Error + 'static)>
{
match &self.inner {
Some(x) => Some(x),
None => None,
}
}
}
pub(super) trait WeebExt
{
fn into_imouto(self) -> Error;
fn into_oneesan(self) -> Error;
}
pub(super) trait TryWeebExt<T>
{
fn try_imouto(self, bytes_done: usize) -> Result<T, Error>;
fn try_oneesan(self, bytes_done: usize) -> Result<T, Error>;
}
impl WeebExt for io::Error
{
fn into_imouto(self) -> Error
{
Error {
location: ErrorLocation::Imouto,
..Error::from(self)
}
}
fn into_oneesan(self) -> Error
{
Error {
location: ErrorLocation::Oneesan,
..Error::from(self)
}
}
}
impl<T> TryWeebExt<T> for io::Result<T>
{
fn try_imouto(self, bytes_done: usize) -> Result<T, Error>
{
match self {
Ok(v) => Ok(v),
Err(e) => Err(Error {
bytes_done: NonZeroUsize::new(bytes_done),
..e.into_imouto()
}),
}
}
fn try_oneesan(self, bytes_done: usize) -> Result<T, Error>
{
match self {
Ok(v) => Ok(v),
Err(e) => Err(Error {
bytes_done: NonZeroUsize::new(bytes_done),
..e.into_oneesan()
}),
}
}
}