oh_my_toml 0.1.0

Awesome TOML configuration derive macro
Documentation
//! TOML Values

use crate::{DeserializeErrors, DeserializeTable};
use miette::{Diagnostic, SourceSpan};
use nonempty::NonEmpty;
use thiserror::Error;
use toml::de::DeTable;

use crate::{DeserializeValue, Error, util::value_type_description};

#[doc = concat!("Failed to deserialize [`toml_edit::Table`]")]
#[derive(Diagnostic, Error, Debug, Clone, Eq, PartialEq, Hash)]
#[error("Type mismatch")]
pub struct DeserializeTomlTableError {
    /// Details on why deserialization failed
    pub details: String,
    /// Location of the error in the source file
    #[label("{details}")]
    pub span: SourceSpan,
}

impl Error for DeserializeTomlTableError {
    fn expected_type() -> std::borrow::Cow<'static, str> {
        "table".into()
    }
}

impl<'de> DeserializeTable<'de> for DeTable<'de> {
    type Error = DeserializeTomlTableError;

    fn deserialize_table(
        table: toml::Spanned<DeTable<'de>>,
    ) -> Result<Self, DeserializeErrors<Self, NonEmpty<Self::Error>>> {
        Ok(table.into_inner())
    }
}

/// Failed to deserialize [`Datetime`](toml_datetime::Datetime)
#[derive(Diagnostic, Error, Debug, Clone, Eq, PartialEq, Hash)]
#[error("Type mismatch")]
pub struct DeserializeDatetimeError {
    /// Details on why deserialization failed
    pub details: String,
    /// Location of the error in the source file
    #[label("{details}")]
    pub span: SourceSpan,
}

impl Error for DeserializeDatetimeError {
    fn expected_type() -> std::borrow::Cow<'static, str> {
        "datetime".into()
    }
}

impl DeserializeValue<'_> for toml_datetime::Datetime {
    type Error = DeserializeDatetimeError;

    fn deserialize_value(
        _key: crate::Key,
        value: crate::Value,
    ) -> Result<Self, DeserializeErrors<Self, NonEmpty<Self::Error>>> {
        let span = value.span();
        let description = value_type_description(&value);
        if let toml::de::DeValue::Datetime(datetime) = value.into_inner() {
            Ok(datetime)
        } else {
            Err(DeserializeErrors::err(DeserializeDatetimeError {
                details: DeserializeDatetimeError::details(description),
                span: span.into(),
            }))
        }
    }
}

/// Failed to deserialize [`Array`](toml::Array)
#[derive(Diagnostic, Error, Debug, Clone, Eq, PartialEq, Hash)]
#[error("Type mismatch")]
pub struct DeserializeTomlArrayError {
    /// Details on why deserialization failed
    pub details: String,
    /// Location of the error in the source file
    #[label("{details}")]
    pub span: SourceSpan,
}

impl Error for DeserializeTomlArrayError {
    fn expected_type() -> std::borrow::Cow<'static, str> {
        "list".into()
    }
}

impl<'v> DeserializeValue<'v> for toml::de::DeArray<'v> {
    type Error = DeserializeTomlArrayError;

    fn deserialize_value<'k>(
        _key: crate::Key<'k>,
        value: crate::Value<'v>,
    ) -> Result<Self, DeserializeErrors<Self, NonEmpty<Self::Error>>> {
        let span = value.span();
        let description = value_type_description(&value);
        if let toml::de::DeValue::Array(array) = value.into_inner() {
            Ok(array)
        } else {
            Err(DeserializeErrors::err(DeserializeTomlArrayError {
                details: DeserializeTomlArrayError::details(description),
                span: span.into(),
            }))
        }
    }
}