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};
#[derive(Diagnostic, Error, Debug, Clone, Eq, PartialEq, Hash)]
#[error("Type mismatch")]
#[diagnostic(help("expected `true` or `false`"))]
pub struct DeserializeBoolError {
pub details: String,
#[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))
}
}