#[macro_export]
macro_rules! custom_key {
($(#[$($meta:meta)*])* $vis:vis struct $key:ident $(;)?) => {
$crate::custom_key!(
$(#[$($meta)*])*
$vis struct $key;
let hasher: $crate::__private::RandomState;
);
};
($(#[$($meta:meta)*])* $vis:vis struct $key:ident; let hasher: $s:ty $(;)?) => {
$crate::custom_key!(
$(#[$($meta)*])*
$vis struct $key;
let hasher: $s = <$s as ::core::default::Default>::default();
);
};
($(#[$($meta:meta)*])* $vis:vis struct $key:ident; let hasher: $s:ty = $init:expr $(;)?) => {
$(#[$($meta)*])*
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Clone, Copy)]
#[repr(transparent)]
$vis struct $key($crate::Key);
impl $key {
#[inline]
fn paracord() -> &'static $crate::ParaCord<$s> {
static S: ::std::sync::OnceLock<$crate::ParaCord<$s>> = ::std::sync::OnceLock::new();
S.get_or_init(|| $crate::ParaCord::with_hasher($init))
}
#[inline]
pub fn try_new_existing(s: &str) -> Option<Self> {
Self::paracord().get(s).map(Self)
}
#[inline]
pub fn new(s: &str) -> Self {
Self(Self::paracord().get_or_intern(s))
}
#[inline]
pub fn as_str(&self) -> &'static str {
unsafe { Self::paracord().resolve_unchecked(self.0) }
}
#[inline]
pub fn count() -> usize {
Self::paracord().len()
}
#[doc = concat!("(`",stringify!($key),"`, `&str`)")]
#[inline]
pub fn iter() -> impl Iterator<Item = (Self, &'static str)> {
Self::paracord().iter().map(|(k, s)| (Self(k), s))
}
}
impl ::core::fmt::Display for $key {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
f.write_str(self.as_str())
}
}
impl ::core::convert::AsRef<str> for $key {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl ::core::ops::Deref for $key {
type Target = str;
#[inline]
fn deref(&self) -> &str {
self.as_str()
}
}
$crate::__private::serde::custom_key_serde!($key);
};
}
#[cfg(test)]
mod tests {
#[test]
fn misc() {
custom_key!(pub struct Foo);
let _foo = Foo::new("foo");
let foo = Foo::try_new_existing("foo").unwrap();
assert_eq!(foo.to_string(), "foo");
assert_eq!(foo.as_ref(), "foo");
assert_eq!(Foo::count(), 1);
let keys: Vec<_> = Foo::iter().collect();
assert_eq!(keys, [(foo, "foo")]);
}
}