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
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()
|
|
}),
|
|
}
|
|
}
|
|
}
|