// License: see LICENSE file at root directory of `master` branch

use {
    alloc::string::String,
    core::fmt::{self, Display, Formatter},
};

#[cfg(feature="std")]
use {
    std::{
        error::Error,
        io::{self, ErrorKind},
    },
};

/// # Error while parsing semver.
#[derive(Debug, PartialEq, Eq)]
pub struct ParseSemverError {

    /// # Error kind
    pub kind: SemverErrorKind,

}

#[cfg(feature="std")]
impl Error for ParseSemverError {

    fn description(&self) -> &str {
        self.kind.description()
    }

}

impl Display for ParseSemverError {

    fn fmt(&self, f: &mut Formatter) -> core::result::Result<(), fmt::Error> {
        f.write_str(self.kind.description())
    }

}

#[cfg(feature="std")]
impl From<ParseSemverError> for io::Error {

    /// # Converts `ParseSemverError` into `io::Error`
    ///
    /// [`ErrorKind::InvalidInput`] will be used.
    ///
    /// [`ErrorKind::InvalidInput`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidInput
    fn from(err: ParseSemverError) -> io::Error {
        io::Error::new(ErrorKind::InvalidInput, err)
    }

}

/// # Semver error kind.
#[derive(Debug, PartialEq, Eq)]
pub enum SemverErrorKind {

    /// # Empty string
    Empty,

    /// # Invalid major version number
    InvalidMajor,

    /// # Invalid minor version number
    InvalidMinor,

    /// # Missing minor version number
    MissingMinor,

    /// # Invalid patch version number
    InvalidPatch,

    /// # Missing patch version number
    MissingPatch,

    /// # Invalid token
    InvalidToken,

    /// # Invalid pre-release
    InvalidPreRelease,

    /// # Invalid build metadata
    InvalidBuildMetadata,

    /// # Too large
    TooLarge,

    /// # Parser error
    ParserError,

    /// # Other
    Other(String),

}

impl SemverErrorKind {

    fn description(&self) -> &str {
        match self {
            SemverErrorKind::Empty => "Empty string",
            SemverErrorKind::InvalidMajor => "Invalid major version number",
            SemverErrorKind::InvalidMinor => "Invalid minor version number",
            SemverErrorKind::MissingMinor => "Missing minor version number",
            SemverErrorKind::InvalidPatch => "Invalid patch version number",
            SemverErrorKind::MissingPatch => "Missing patch version number",
            SemverErrorKind::InvalidToken => "Invalid token",
            SemverErrorKind::InvalidPreRelease => "Invalid pre-release",
            SemverErrorKind::InvalidBuildMetadata => "Invalid build metadata",
            SemverErrorKind::TooLarge => "Too large",
            SemverErrorKind::ParserError => "Parser error",
            SemverErrorKind::Other(s) => &s,
        }
    }

}
