actix_failwrap 1.0.3

A micro-package that enables ergonomic error propagation (using thiserror) inside actix-web route handlers.
Documentation
//! Attribute Count Helper
//!
//! This module declares helpers to ensure
//! there are no duplicated attributes.

use proc_macro2::Span;
use syn::spanned::Spanned;
use syn::{Attribute, Error as SynError};

/// **`get_single_attr()`**
///
/// Gets a sole attribute from an attribute iterator
/// or a pre-formatted [`SynError`] if many or 0 expected
/// attributes were found.
pub fn get_single_attr<I: IntoIterator<Item = Attribute>>(
    iter: I,
    ident: &str,
) -> Result<Option<Attribute>, SynError> {
    let attributes = iter
        .into_iter()
        .filter(|attr| {
            attr.path()
                .is_ident(ident)
        })
        .collect::<Vec<_>>();

    if let ..=1 = attributes.len() {
        Ok(attributes
            .first()
            .cloned())
    } else {
        let mut extra_attrs_iter = attributes.iter();

        let extra_attr_spans = extra_attrs_iter
            .next()
            .map_or_else(Span::call_site, |first| {
                extra_attrs_iter.fold(first.span(), |acc, curr| {
                    acc.join(curr.span())
                        .unwrap_or(acc)
                })
            });

        Err(SynError::new(extra_attr_spans, format!("{ident} attribute is allowed only once.")))
    }
}