spark_connect_core/
errors.rsuse std::fmt::{Debug, Display, Formatter};
use std::io::Write;
use std::error::Error;
use arrow::error::ArrowError;
#[cfg(feature = "datafusion")]
use datafusion::error::DataFusionError;
#[cfg(feature = "polars")]
use polars::error::PolarsError;
#[derive(Debug)]
pub enum SparkError {
NotYetImplemented(String),
ExternalError(Box<dyn Error + Send + Sync>),
AnalysisException(String),
IoError(String, std::io::Error),
ArrowError(ArrowError),
InvalidConnectionUrl(String),
}
impl SparkError {
pub fn from_external_error(error: Box<dyn Error + Send + Sync>) -> Self {
Self::ExternalError(error)
}
}
impl From<std::io::Error> for SparkError {
fn from(error: std::io::Error) -> Self {
SparkError::IoError(error.to_string(), error)
}
}
impl From<std::str::Utf8Error> for SparkError {
fn from(error: std::str::Utf8Error) -> Self {
SparkError::AnalysisException(error.to_string())
}
}
impl From<std::string::FromUtf8Error> for SparkError {
fn from(error: std::string::FromUtf8Error) -> Self {
SparkError::AnalysisException(error.to_string())
}
}
impl From<ArrowError> for SparkError {
fn from(error: ArrowError) -> Self {
SparkError::ArrowError(error)
}
}
impl From<tonic::Status> for SparkError {
fn from(status: tonic::Status) -> Self {
SparkError::AnalysisException(status.message().to_string())
}
}
impl From<serde_json::Error> for SparkError {
fn from(value: serde_json::Error) -> Self {
SparkError::AnalysisException(value.to_string())
}
}
#[cfg(feature = "datafusion")]
impl From<DataFusionError> for SparkError {
fn from(_value: DataFusionError) -> Self {
SparkError::AnalysisException("Error converting to DataFusion DataFrame".to_string())
}
}
#[cfg(feature = "polars")]
impl From<PolarsError> for SparkError {
fn from(_value: PolarsError) -> Self {
SparkError::AnalysisException("Error converting to Polars DataFrame".to_string())
}
}
impl<W: Write> From<std::io::IntoInnerError<W>> for SparkError {
fn from(error: std::io::IntoInnerError<W>) -> Self {
SparkError::IoError(error.to_string(), error.into())
}
}
impl Display for SparkError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SparkError::ExternalError(source) => write!(f, "External error: {}", &source),
SparkError::AnalysisException(desc) => write!(f, "Analysis error: {desc}"),
SparkError::IoError(desc, _) => write!(f, "Io error: {desc}"),
SparkError::ArrowError(desc) => write!(f, "Apache Arrow error: {desc}"),
SparkError::NotYetImplemented(source) => write!(f, "Not yet implemented: {source}"),
SparkError::InvalidConnectionUrl(val) => write!(f, "Invalid URL error: {val}"),
}
}
}
impl Error for SparkError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if let Self::ExternalError(e) = self {
Some(e.as_ref())
} else {
None
}
}
}