varnish_sys/vcl/
error.rs

1use std::borrow::Cow;
2use std::ffi::CStr;
3use std::num::NonZeroUsize;
4use std::str::Utf8Error;
5
6// TODO: at some point we may want to add a `txt` variant - e.g. if user wants to handle error creation directly.
7
8/// An `Error` describing all issues with the VCL module
9///
10/// This enum is used to describe all the possible errors that can happen when working with the VCL module,
11/// or converting between Rust and C types.
12#[derive(thiserror::Error, Debug)]
13pub enum VclError {
14    /// Create a new `Error` from a string
15    #[error("{0}")]
16    String(String),
17    /// Create a new `Error` from a string slice
18    #[error("{0}")]
19    Str(&'static str),
20    /// Create a new `VclError` from a C string
21    #[error("{}", cstr_to_string(.0))]
22    CStr(&'static CStr),
23    /// In case Workspace allocation fails
24    #[error("Unable to allocate {0} bytes in a Workspace")]
25    WsOutOfMemory(NonZeroUsize),
26    /// Create a new `VclError` from a UTF-8 error
27    #[error("{0}")]
28    Utf8Error(#[from] Utf8Error),
29    /// Create a new `VclError` from a boxed error
30    #[error("{0}")]
31    Box(#[from] Box<dyn std::error::Error>),
32}
33
34impl VclError {
35    /// Create a new `Error` from a string
36    pub fn new(s: String) -> Self {
37        Self::String(s)
38    }
39
40    pub fn as_str(&self) -> Cow<str> {
41        match self {
42            Self::String(s) => Cow::Borrowed(s.as_str()),
43            Self::Utf8Error(e) => Cow::Owned(e.to_string()),
44            Self::Str(s) => Cow::Borrowed(s),
45            Self::Box(e) => Cow::Owned(e.to_string()),
46            Self::CStr(s) => Cow::Owned(cstr_to_string(s)),
47            Self::WsOutOfMemory(sz) => {
48                Cow::Owned(format!("Unable to allocate {sz} bytes in a Workspace"))
49            }
50        }
51    }
52}
53
54fn cstr_to_string(value: &CStr) -> String {
55    match value.to_string_lossy() {
56        Cow::Borrowed(s) => s.to_string(),
57        Cow::Owned(s) => {
58            format!("{s} (error is not exact because it contains non-utf8 characters)")
59        }
60    }
61}
62
63// Any error types are done with the #[from] attribute, so we don't need to implement From for them
64
65impl From<String> for VclError {
66    fn from(s: String) -> Self {
67        Self::String(s)
68    }
69}
70
71impl From<&'static str> for VclError {
72    fn from(s: &'static str) -> Self {
73        Self::Str(s)
74    }
75}
76
77impl From<&'static CStr> for VclError {
78    fn from(s: &'static CStr) -> Self {
79        Self::CStr(s)
80    }
81}
82
83/// Shorthand to [`Result<T, VclError>`]
84pub type VclResult<T> = Result<T, VclError>;