minecraft-command-types 0.1.0

Provides an AST like structure for Minecraft commands.
Documentation
use nonempty::NonEmpty;
use std::collections::{BTreeMap, BTreeSet};

pub trait HasMacro {
    fn has_macro(&self) -> bool;
    fn has_macro_conflict(&self) -> bool;
}

#[macro_export]
macro_rules! impl_has_macro_false {
    ($($t:ty),*) => {
        $(
            impl HasMacro for $t {
                #[inline(always)]
                fn has_macro(&self) -> bool { false }

                fn has_macro_conflict(&self) -> bool { false }
            }
        )*
    };
}

impl_has_macro_false!(
    bool,
    i8,
    i16,
    i32,
    i64,
    String,
    ordered_float::NotNan<f32>,
    ordered_float::NotNan<f64>
);

impl<A: HasMacro, B: HasMacro> HasMacro for (A, B) {
    fn has_macro(&self) -> bool {
        self.0.has_macro() || self.1.has_macro()
    }

    fn has_macro_conflict(&self) -> bool {
        self.0.has_macro_conflict() || self.1.has_macro_conflict()
    }
}

impl<T: HasMacro> HasMacro for Option<T> {
    fn has_macro(&self) -> bool {
        self.as_ref().map(|t| t.has_macro()).unwrap_or(false)
    }

    fn has_macro_conflict(&self) -> bool {
        self.as_ref()
            .map(|t| t.has_macro_conflict())
            .unwrap_or(false)
    }
}

impl<T: HasMacro> HasMacro for Vec<T> {
    fn has_macro(&self) -> bool {
        self.iter().any(|t| t.has_macro())
    }

    fn has_macro_conflict(&self) -> bool {
        self.iter().any(|t| t.has_macro_conflict())
    }
}

impl<T: HasMacro> HasMacro for NonEmpty<T> {
    fn has_macro(&self) -> bool {
        self.iter().any(|t| t.has_macro())
    }

    fn has_macro_conflict(&self) -> bool {
        self.iter().any(|t| t.has_macro_conflict())
    }
}

impl<T: HasMacro> HasMacro for Box<T> {
    fn has_macro(&self) -> bool {
        self.as_ref().has_macro()
    }

    fn has_macro_conflict(&self) -> bool {
        self.as_ref().has_macro_conflict()
    }
}

impl<K, V: HasMacro> HasMacro for BTreeMap<K, V> {
    fn has_macro(&self) -> bool {
        self.values().any(|t| t.has_macro())
    }

    fn has_macro_conflict(&self) -> bool {
        self.values().any(|t| t.has_macro_conflict())
    }
}

impl<T: HasMacro> HasMacro for BTreeSet<T> {
    fn has_macro(&self) -> bool {
        self.iter().any(|t| t.has_macro())
    }

    fn has_macro_conflict(&self) -> bool {
        self.iter().any(|t| t.has_macro_conflict())
    }
}