disklru 0.3.3

DiskLRU is an experimental LRU store.
Documentation
// Copyright (C) 2024 Christian Mauduit <ufoot@ufoot.org>

use rmp_serde::{decode, encode};
use sled::transaction::{ConflictableTransactionError, TransactionError};
use std::fmt;
use std::fmt::{Display, Formatter};

#[derive(Debug)]
pub enum Error {
    DbIo(std::io::Error),
    DbUnexpected(String),
    InvalidData(String),
    ReportBug(String),
    NotImplemented,
}

/// URL to report bugs.
///
/// This is used internally to provide context when something unexpected happens,
/// so that users can find find out which piece of software fails,
/// and how to contact author(s).
///
/// Alternatively, send a direct email to <ufoot@ufoot.org>.
pub const BUG_REPORT_URL: &str = "https://gitlab.com/liberecofr/disklru/-/issues";

pub type Result<T> = std::result::Result<T, Error>;

impl Error {
    pub fn db_io(upstream: std::io::Error) -> Error {
        Error::DbIo(upstream)
    }

    pub fn db_unexpected(why: &str) -> Error {
        Error::DbUnexpected(why.to_string())
    }

    pub fn invalid_data(why: &str) -> Error {
        Error::InvalidData(why.to_string())
    }

    pub fn report_bug(why: &str) -> Error {
        Error::ReportBug(why.to_string())
    }

    pub fn not_implemented() -> Error {
        Error::NotImplemented
    }

    pub fn abort(self) -> ConflictableTransactionError<Error> {
        ConflictableTransactionError::Abort(self)
    }
}

impl From<sled::Error> for Error {
    fn from(e: sled::Error) -> Error {
        match e {
            sled::Error::Io(e) => Error::db_io(e),
            e => Error::db_unexpected(&format!("{}", e)),
        }
    }
}

impl From<Error> for ConflictableTransactionError<Error> {
    fn from(e: Error) -> ConflictableTransactionError<Error> {
        e.abort()
    }
}

impl From<TransactionError<Error>> for Error {
    fn from(e: TransactionError<Error>) -> Error {
        match e {
            TransactionError::Abort(e) => e,
            TransactionError::Storage(e) => Error::db_unexpected(&format!("{:?}", e)),
        }
    }
}

impl From<encode::Error> for Error {
    fn from(e: encode::Error) -> Error {
        Error::invalid_data(&format!("{}", e))
    }
}

impl From<decode::Error> for Error {
    fn from(e: decode::Error) -> Error {
        Error::invalid_data(&format!("{}", e))
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), fmt::Error> {
        match self {
            Error::DbIo(e) => write!(f, "database I/O error: {}", e),
            Error::DbUnexpected(e) => write!(f, "database unexpected error: {}", e),
            Error::InvalidData(e) => write!(f, "invalid data: {}", e),
            Error::ReportBug(e) => write!(
                f,
                "unexpected bug, please report issue on <{}>: {}",
                BUG_REPORT_URL, e
            ),
            Error::NotImplemented => write!(f, "not implemented"),
        }
    }
}