oh_my_toml 0.1.0

Awesome TOML configuration derive macro
Documentation
//! Impls for bools

use nonempty::NonEmpty;
use std::borrow::Cow;
use std::sync::atomic::AtomicBool;

use miette::{Diagnostic, SourceSpan};
use thiserror::Error;

use crate::util::value_type_description;
use crate::{DeserializeErrors, Key, Value};
use crate::{DeserializeValue, Error};

/// Failed to deserialize [`bool`](core::primitive::bool)
#[derive(Diagnostic, Error, Debug, Clone, Eq, PartialEq, Hash)]
#[error("Type mismatch")]
#[diagnostic(help("expected `true` or `false`"))]
pub struct DeserializeBoolError {
    /// Details on why deserialization failed
    pub details: String,
    /// Location of the error in the source file
    #[label("{details}")]
    pub span: SourceSpan,
}

impl Error for DeserializeBoolError {
    fn expected_type() -> Cow<'static, str> {
        "boolean".into()
    }
}

impl DeserializeValue<'_> for bool {
    type Error = DeserializeBoolError;

    fn deserialize_value(
        _key: Key,
        value: Value,
    ) -> Result<Self, DeserializeErrors<Self, NonEmpty<Self::Error>>> {
        value.as_ref().as_bool().ok_or_else(|| {
            DeserializeErrors::err(DeserializeBoolError {
                details: DeserializeBoolError::details(value_type_description(&value)),
                span: value.span().into(),
            })
        })
    }
}

#[cfg(target_has_atomic = "8")]
impl DeserializeValue<'_> for AtomicBool {
    type Error = DeserializeBoolError;

    fn deserialize_value(
        key: Key,
        value: Value,
    ) -> Result<Self, DeserializeErrors<Self, NonEmpty<Self::Error>>> {
        bool::deserialize_value(key, value)
            .map(Into::into)
            .map_err(|it| it.map(Into::into))
    }
}