libopenai/
error.rs

1use serde::Deserialize;
2use std::fmt::{Debug, Display};
3
4pub type Result<T, E = Error> = ::core::result::Result<T, E>;
5
6/// An error returned by a builder
7#[derive(Debug)]
8pub struct BuilderError<T> {
9    pub builder: T,
10    pub err: Error,
11}
12
13/// An error of the `libopenai` library
14#[derive(Debug, thiserror::Error)]
15pub enum Error {
16    #[error("OpenAI error: {0}")]
17    OpenAI(#[from] OpenAiError),
18    #[error("Enviroment error: {0}")]
19    Env(#[from] std::env::VarError),
20    #[error("Reqwest error: {0}")]
21    Reqwest(#[from] reqwest::Error),
22    #[error("JSON error: {0}")]
23    Json(#[from] serde_json::Error),
24    #[error("I/O error: {0}")]
25    Io(#[from] std::io::Error),
26    #[error("Base64 error: {0}")]
27    Base64(#[from] base64::DecodeError),
28    #[error("Image error: {0}")]
29    Image(#[from] image::error::ImageError),
30    #[error("Srt error: {0}")]
31    Srt(#[from] srtlib::ParsingError),
32    #[error("Unknown error: {0}")]
33    Other(#[from] anyhow::Error),
34}
35
36#[derive(Debug, Clone, Deserialize)]
37#[serde(untagged)]
38pub(crate) enum FallibleResponse<T> {
39    Ok(T),
40    Err { error: OpenAiError },
41}
42
43/// Error returned by an OpenAI API's endpoint
44#[derive(Debug, Clone, Deserialize)]
45#[non_exhaustive]
46pub struct OpenAiError {
47    pub message: String,
48    #[serde(rename = "type")]
49    pub ty: String,
50    pub param: Option<String>,
51    pub code: Option<String>,
52}
53
54impl Error {
55    /// Creates a generic error with a custom message
56    #[inline]
57    pub fn msg<M: Display + Debug + Send + Sync + 'static>(msg: M) -> Self {
58        Self::Other(anyhow::Error::msg(msg))
59    }
60}
61
62impl<T> BuilderError<T> {
63    #[inline]
64    pub fn new(builder: T, error: impl Into<Error>) -> Self {
65        return Self {
66            builder,
67            err: error.into(),
68        };
69    }
70
71    #[inline]
72    pub fn msg<M>(builder: T, msg: M) -> Self
73    where
74        M: Display + Debug + Send + Sync + 'static,
75    {
76        return Self {
77            builder,
78            err: Error::msg(msg),
79        };
80    }
81
82    /// Returns the inner builder
83    #[inline]
84    pub fn into_inner(self) -> T {
85        self.builder
86    }
87
88    /// Returns the inner error
89    #[inline]
90    pub fn into_error(self) -> Error {
91        self.err
92    }
93}
94
95impl<T> FallibleResponse<T> {
96    #[inline]
97    pub fn into_result(self) -> Result<T, OpenAiError> {
98        match self {
99            FallibleResponse::Ok(x) => Ok(x),
100            FallibleResponse::Err { error } => {
101                #[cfg(feature = "tracing")]
102                tracing::error!("OpenAI error: {error}");
103                Err(error)
104            }
105        }
106    }
107}
108
109impl<T> From<BuilderError<T>> for Error {
110    #[inline]
111    fn from(value: BuilderError<T>) -> Self {
112        value.into_error()
113    }
114}
115
116impl Display for OpenAiError {
117    #[inline]
118    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119        Display::fmt(&self.message, f)
120    }
121}
122
123impl<T> Display for BuilderError<T> {
124    #[inline]
125    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126        Display::fmt(&self.err, f)
127    }
128}
129
130impl std::error::Error for OpenAiError {}
131impl<T: Debug> std::error::Error for BuilderError<T> {
132    #[inline]
133    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
134        Some(&self.err)
135    }
136}