oh_my_toml 0.1.0

Awesome TOML configuration derive macro
Documentation
//! Impls for standard library's collections

use crate::DeserializeErrors;
use crate::util::deserialize_sequence;
use crate::{Key, Value};
use std::rc::Rc;
use std::sync::Arc;

use std::collections::{BTreeSet, BinaryHeap, HashSet, LinkedList, VecDeque};

use std::borrow::Cow;

use crate::{DeserializeValue, Error};
use miette::{Diagnostic, SourceSpan};
use nonempty::NonEmpty;
use thiserror::Error;

/// Implement sequence
macro_rules! impl_DeserializeTomlValue_for {
    (
        $collection:ty where $($tt:tt)*
    ) => {
        impl<'de, $($tt)*> $crate::DeserializeValue<'de>
            for $collection
        {
            type Error = DeserializeSequenceError<T::Error>;

            fn deserialize_value<'k>(
                _key: Key<'k>,
                value: Value<'de>,
            ) -> Result<Self, DeserializeErrors<Self, NonEmpty<Self::Error>>> {
                match deserialize_sequence(
                    value,
                    T::deserialize_value,
                    |value| {
                        DeserializeSequenceError::<T::Error>::details(
                            crate::util::value_type_description(value),
                        )
                    }
                ) {
                    Ok(t) => {
                        Ok(t.into_iter().collect())
                    }
                    Err((a, b)) => {
                        Err(DeserializeErrors::new(a.map(|it| it.into_iter().collect()), b))
                    }
                }
            }
        }
    };
}

/// Failed to deserialize a homogeneous collection, e.g. [`Vec`] or [`HashSet`]
#[derive(Diagnostic, Error, Debug, Clone, Eq, PartialEq, Hash)]
#[error("Type mismatch")]
pub enum DeserializeSequenceError<E: Error> {
    /// Received value is not actually a TOML List
    NotList {
        /// Details on why deserialization failed
        details: String,
        /// Location of the error in the source file
        #[label("{details}")]
        span: SourceSpan,
    },
    /// Received value is an invalid sequence
    InvalidSequence {
        /// Details on why deserialization failed
        details: String,
        /// Location of the error in the source file
        #[label("{details}")]
        span: SourceSpan,
        /// A list of errors for each inner element that failed to deserialize
        #[related]
        errors: NonEmpty<E>,
    },
}

impl<E: Error> Error for DeserializeSequenceError<E> {
    fn expected_type() -> Cow<'static, str> {
        format!("list of {}", E::expected_type()).into()
    }
}

impl_DeserializeTomlValue_for!( HashSet<T, S>
     where
        T: DeserializeValue<'de> + Eq + std::hash::Hash,
        S: std::hash::BuildHasher + Default,
);
impl_DeserializeTomlValue_for!( Vec<T>
    where
        T: DeserializeValue<'de>
);
impl_DeserializeTomlValue_for!( BTreeSet<T>
    where
        T: DeserializeValue<'de> + Ord
);
impl_DeserializeTomlValue_for!( BinaryHeap<T>
    where
        T: DeserializeValue<'de> + Ord
);
impl_DeserializeTomlValue_for!( LinkedList<T>
    where
        T: DeserializeValue<'de>
);
impl_DeserializeTomlValue_for!( VecDeque<T>
    where
        T: DeserializeValue<'de>
);
impl_DeserializeTomlValue_for!( Rc<[T]>
    where
        T: DeserializeValue<'de>
);
impl_DeserializeTomlValue_for!( Cow<'a, [T]>
    where
        'a, T: DeserializeValue<'de> + Clone
);
impl_DeserializeTomlValue_for!( Box<[T]>
    where
        T: DeserializeValue<'de>
);
impl_DeserializeTomlValue_for!( Arc<[T]>
    where
        T: DeserializeValue<'de>
);