use std::ffi::CString;
use std::marker::PhantomData;
pub(crate) fn key_cstring(name: &'static str) -> CString {
CString::new(name).expect("static key contains null byte")
}
pub struct Key<T> {
name: &'static str,
_marker: PhantomData<T>,
}
impl<T> Key<T> {
pub const fn new(name: &'static str) -> Self {
Self {
name,
_marker: PhantomData,
}
}
pub(crate) fn name(&self) -> &'static str {
self.name
}
}
impl<T> Clone for Key<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Key<T> {}
impl<T> std::fmt::Debug for Key<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Key").field("name", &self.name).finish()
}
}
impl<T> std::fmt::Display for Key<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
impl<T> PartialEq for Key<T> {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl<T> Eq for Key<T> {}
impl<T> std::hash::Hash for Key<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_new() {
const KEY: Key<i64> = Key::new("test_key");
assert_eq!(KEY.name(), "test_key");
}
#[test]
fn test_key_clone_and_copy() {
const KEY: Key<i64> = Key::new("copy_key");
let cloned = KEY;
assert_eq!(KEY, cloned);
let copied = KEY;
assert_eq!(KEY, copied);
}
#[test]
fn test_key_display() {
const KEY: Key<i64> = Key::new("display_key");
assert_eq!(format!("{KEY}"), "display_key");
}
#[test]
fn test_key_debug() {
const KEY: Key<i64> = Key::new("debug_key");
let debug = format!("{KEY:?}");
assert!(debug.contains("debug_key"));
}
#[test]
fn test_key_equality() {
const A: Key<i64> = Key::new("same");
const B: Key<i64> = Key::new("same");
const C: Key<i64> = Key::new("different");
assert_eq!(A, B);
assert_ne!(A, C);
}
#[test]
fn test_key_hash() {
use std::collections::HashSet;
const A: Key<i64> = Key::new("hash_key");
const B: Key<i64> = Key::new("hash_key");
let mut set = HashSet::new();
set.insert(A);
assert!(set.contains(&B));
}
#[test]
fn test_key_cstring() {
let first = key_cstring("cstring_test");
let second = key_cstring("cstring_test");
assert_eq!(first, second);
}
}