use std::borrow::Cow;
use std::ffi::CStr;
use std::num::NonZeroUsize;
use std::str::Utf8Error;
#[derive(thiserror::Error, Debug)]
pub enum VclError {
#[error("{0}")]
String(String),
#[error("{0}")]
Str(&'static str),
#[error("{}", cstr_to_string(.0))]
CStr(&'static CStr),
#[error("Unable to allocate {0} bytes in a Workspace")]
WsOutOfMemory(NonZeroUsize),
#[error("{0}")]
Utf8Error(#[from] Utf8Error),
#[error("{0}")]
Box(#[from] Box<dyn std::error::Error>),
}
impl VclError {
pub fn new(s: String) -> Self {
Self::String(s)
}
pub fn as_str(&self) -> Cow<str> {
match self {
Self::String(s) => Cow::Borrowed(s.as_str()),
Self::Utf8Error(e) => Cow::Owned(e.to_string()),
Self::Str(s) => Cow::Borrowed(s),
Self::Box(e) => Cow::Owned(e.to_string()),
Self::CStr(s) => Cow::Owned(cstr_to_string(s)),
Self::WsOutOfMemory(sz) => {
Cow::Owned(format!("Unable to allocate {sz} bytes in a Workspace"))
}
}
}
}
fn cstr_to_string(value: &CStr) -> String {
match value.to_string_lossy() {
Cow::Borrowed(s) => s.to_string(),
Cow::Owned(s) => {
format!("{s} (error is not exact because it contains non-utf8 characters)")
}
}
}
impl From<String> for VclError {
fn from(s: String) -> Self {
Self::String(s)
}
}
impl From<&'static str> for VclError {
fn from(s: &'static str) -> Self {
Self::Str(s)
}
}
impl From<&'static CStr> for VclError {
fn from(s: &'static CStr) -> Self {
Self::CStr(s)
}
}
pub type VclResult<T> = Result<T, VclError>;