mod private
{
use serde_json;
use core::fmt;
use backoff; use error_tools::dependency::thiserror;
#[ derive( Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize ) ]
#[ non_exhaustive ]
pub struct ApiError
{
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub code : Option< String >,
pub message : String,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub param : Option< String >,
#[ serde( skip_serializing_if = "Option::is_none" ) ]
pub r#type : Option< String >,
}
impl fmt::Display for ApiError
{
#[ inline ]
fn fmt( &self, formatter : &mut fmt::Formatter< '_ > ) -> core::fmt::Result
{
write!( formatter, "API Error : {}", self.message )?;
if let Some( code ) = &self.code
{
write!( formatter, " (Code : {code})" )?;
}
if let Some( param ) = &self.param
{
write!( formatter, " (Param : {param})" )?;
}
if let Some( r#type ) = &self.r#type
{
write!( formatter, " (Type : {type})" )?;
}
core ::result::Result::Ok( () )
}
}
#[ derive( Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize ) ]
#[ non_exhaustive ]
pub struct ApiErrorWrap
{
pub status_code : u16,
pub error : ApiError,
}
impl fmt::Display for ApiErrorWrap
{
#[ inline ]
fn fmt( &self, formatter : &mut fmt::Formatter< '_ > ) -> core::fmt::Result
{
write!( formatter, "HTTP Status : {}, API Error : {}", self.status_code, self.error )
}
}
#[ derive( Debug, Clone, PartialEq, thiserror::Error ) ]
#[ non_exhaustive ]
pub enum OpenAIError
{
#[ error( "API Error : {0}" ) ]
Api( ApiError ),
#[ error( "HTTP Error : {0}" ) ]
Http( String ),
#[ error( "WebSocket Error : {0}" ) ]
Ws( String ), #[ error( "WebSocket Invalid Message Error : {0}" ) ]
WsInvalidMessage( String ),
#[ error( "Internal Error : {0}" ) ]
Internal( String ), #[ error( "Invalid Argument Error : {0}" ) ]
InvalidArgument( String ),
#[ error( "Missing Argument Error : {0}" ) ]
MissingArgument( String ),
#[ error( "Missing Environment Error : {0}" ) ]
MissingEnvironment( String ),
#[ error( "Missing Header Error : {0}" ) ]
MissingHeader( String ),
#[ error( "Missing File Error : {0}" ) ]
MissingFile( String ),
#[ error( "File Error : {0}" ) ]
File( String ),
#[ error( "Network Error : {0}" ) ]
Network( String ),
#[ error( "Timeout Error : {0}" ) ]
Timeout( String ),
#[ error( "Stream Error : {0}" ) ]
Stream( String ), #[ error( "Unknown Error : {0}" ) ]
Unknown( String ),
#[ error( "Rate Limit Error : {0}" ) ]
RateLimit( String ),
}
impl From< reqwest::Error > for OpenAIError
{
#[ inline ]
fn from( error : reqwest::Error ) -> Self
{
if error.is_timeout()
{
OpenAIError::Timeout( error.to_string() )
}
else if error.is_connect() || error.is_request()
{
OpenAIError::Network( error.to_string() )
}
else if error.is_builder()
{
OpenAIError::Internal( format!( "HTTP client build error : {error}" ) )
}
else if error.is_status()
{
let status = error.status().unwrap_or_default();
OpenAIError::Http( format!( "HTTP error with status {status}: {error}" ) )
}
else
{
OpenAIError::Http( error.to_string() )
}
}
}
impl From< serde_json::Error > for OpenAIError
{
#[ inline ]
fn from( error : serde_json::Error ) -> Self
{
OpenAIError::Internal( format!( "JSON error : {error}" ) )
}
}
impl From< backoff::Error< OpenAIError > > for OpenAIError
{
#[ inline ]
fn from( error : backoff::Error< OpenAIError > ) -> Self
{
match error
{
backoff ::Error::Transient { err, .. } => err,
backoff ::Error::Permanent( e ) => e,
}
}
}
#[ must_use ]
#[ inline ]
pub fn map_deserialization_error( error : &serde_json::Error ) -> OpenAIError
{
OpenAIError::Internal( format!( "Deserialization error : {error}" ) )
}
pub type Result< T > = error_tools::untyped::Result< T >;
}
crate ::mod_interface!
{
exposed use
{
ApiError,
ApiErrorWrap,
OpenAIError,
Result,
map_deserialization_error,
};
}