use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::BuildHasher;
use std::sync::Arc;
#[doc(hidden)]
pub trait PathPatternItem {
type Item;
}
impl<T> PathPatternItem for Vec<T> {
type Item = T;
}
impl<C> PathPatternItem for Option<C>
where
C: PathPatternItem,
{
type Item = C::Item;
}
impl<C> PathPatternItem for Box<C>
where
C: PathPatternItem,
{
type Item = C::Item;
}
impl<C> PathPatternItem for Arc<C>
where
C: PathPatternItem,
{
type Item = C::Item;
}
impl<T, const N: usize> PathPatternItem for [T; N] {
type Item = T;
}
impl<K, V> PathPatternItem for BTreeMap<K, V> {
type Item = V;
}
impl<K, V, S> PathPatternItem for HashMap<K, V, S>
where
S: BuildHasher,
{
type Item = V;
}
impl<T> PathPatternItem for BTreeSet<T> {
type Item = T;
}
impl<T, S> PathPatternItem for HashSet<T, S>
where
S: BuildHasher,
{
type Item = T;
}
#[doc(hidden)]
#[must_use]
pub fn pattern_item_ref<C>(_: &C) -> Option<&C::Item>
where
C: PathPatternItem,
{
None
}
#[doc(hidden)]
#[must_use]
pub fn normalize_macro_path(path: &str) -> String {
path.split('.')
.map(str::trim)
.map(|segment| segment.strip_prefix("r#").unwrap_or(segment))
.collect::<Vec<_>>()
.join(".")
}
#[macro_export]
macro_rules! path {
($root:ident $(:: $root_tail:ident)* . $segment:tt $(. $rest:tt)*) => {{
let _ = |__tier_value: &$root $(:: $root_tail)*| {
let _ = &$crate::__tier_path_check!((__tier_value).$segment $(. $rest)*);
};
$crate::path::normalize_macro_path(stringify!($segment $(. $rest)*))
}};
}
#[macro_export]
macro_rules! path_pattern {
($root:ident $(:: $root_tail:ident)* . $segment:tt $(. $rest:tt)*) => {{
let _ = |__tier_value: &$root $(:: $root_tail)*| {
$crate::__tier_path_pattern_check!((__tier_value).$segment $(. $rest)*);
};
$crate::path::normalize_macro_path(stringify!($segment $(. $rest)*))
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tier_path_check {
(($value:expr) . $segment:tt) => {
$value.$segment
};
(($value:expr) . $segment:tt $(. $rest:tt)+) => {
$crate::__tier_path_check!(($value.$segment) $(. $rest)+)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tier_path_pattern_check {
(($value:expr) . *) => {
if false {
let _ = $crate::path::pattern_item_ref($value);
}
};
(($value:expr) . * $(. $rest:tt)+) => {
if false {
if let Some(__tier_item) = $crate::path::pattern_item_ref($value) {
$crate::__tier_path_pattern_check!((__tier_item) $(. $rest)+);
}
}
};
(($value:expr) . $segment:tt) => {
if false {
let _ = &$value.$segment;
}
};
(($value:expr) . $segment:tt $(. $rest:tt)+) => {
$crate::__tier_path_pattern_check!((&$value.$segment) $(. $rest)+);
};
}