//! Error types related to serialization.

/// Error returned when serializing fails.
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct Error {
    internal: ErrorInternal,
}

impl From<ErrorInternal> for Error {
    fn from(value: ErrorInternal) -> Self {
        Error {
            internal: value,
        }
    }
}

#[derive(Debug, thiserror::Error)]
#[error("Unsupported data type {unsupported}")]
pub(crate) enum ErrorInternal {
    #[error("unsupported data type {0}")]
    Unsupported(&'static str),
    #[error("{0}")]
    Custom(String),
    #[error("invalid char {c} in key '{key}' at position {pos}")]
    InvalidKeyChar { key: String, c: char, pos: usize },
    #[error("empty key is not allowed")]
    EmptyKey,
    #[error("failed to write")]
    FmtWriteFailed,
    #[error("failed to write")]
    IoWriteFailed(#[from] std::io::Error),
}

impl Error {
    pub(crate) fn unsupported_data_type(type_name: &'static str) -> Self {
        let type_name = if type_name.starts_with("serialize_") {
            &type_name[10..]
        } else {
            type_name
        };

        ErrorInternal::Unsupported(type_name).into()
    }

    pub(crate) fn failed_write(_: std::fmt::Error) -> Self {
        ErrorInternal::FmtWriteFailed.into()
    }

    pub(crate) fn into_fmt(self) -> Result<Result<(), Self>, std::fmt::Error> {
        if let ErrorInternal::FmtWriteFailed = self.internal {
            Err(std::fmt::Error)
        } else {
            Ok(Err(self))
        }
    }
}

impl serde::ser::Error for Error {
    fn custom<T: std::fmt::Display>(msg: T) -> Self {
        ErrorInternal::Custom(msg.to_string()).into()
    }
}

