use core::fmt;
#[derive(Copy, Clone)]
pub struct ObfStr {
init: fn() -> &'static str,
}
impl ObfStr {
#[inline]
pub const fn new(init: fn() -> &'static str) -> Self {
Self { init }
}
#[inline]
pub fn as_str(self) -> &'static str {
(self.init)()
}
#[inline]
pub fn into_string(self) -> String {
self.as_str().to_owned()
}
}
impl core::ops::Deref for ObfStr {
type Target = str;
#[inline]
fn deref(&self) -> &str {
(self.init)()
}
}
impl AsRef<str> for ObfStr {
#[inline]
fn as_ref(&self) -> &str {
(self.init)()
}
}
impl fmt::Display for ObfStr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str((self.init)())
}
}
impl fmt::Debug for ObfStr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt((self.init)(), f)
}
}
impl PartialEq for ObfStr {
#[inline]
fn eq(&self, other: &Self) -> bool {
(self.init)() == (other.init)()
}
}
impl Eq for ObfStr {}
impl PartialEq<&str> for ObfStr {
#[inline]
fn eq(&self, other: &&str) -> bool {
(self.init)() == *other
}
}
impl PartialEq<ObfStr> for &str {
#[inline]
fn eq(&self, other: &ObfStr) -> bool {
*self == (other.init)()
}
}
impl PartialEq<String> for ObfStr {
#[inline]
fn eq(&self, other: &String) -> bool {
(self.init)() == other.as_str()
}
}
impl PartialEq<ObfStr> for String {
#[inline]
fn eq(&self, other: &ObfStr) -> bool {
self.as_str() == (other.init)()
}
}
impl From<ObfStr> for String {
#[inline]
fn from(value: ObfStr) -> Self {
value.into_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn hello() -> &'static str {
"hello"
}
fn world() -> &'static str {
"world"
}
#[test]
fn exposes_borrowed_and_owned_values() {
let value = ObfStr::new(hello);
assert_eq!(value.as_str(), "hello");
assert_eq!(&*value, "hello");
assert_eq!(value.as_ref(), "hello");
assert_eq!(value.into_string(), String::from("hello"));
assert_eq!(String::from(value), "hello");
}
#[test]
fn formats_like_a_string_slice() {
let value = ObfStr::new(hello);
assert_eq!(format!("{value}"), "hello");
assert_eq!(format!("{value:?}"), "\"hello\"");
}
#[test]
fn supports_symmetric_string_comparisons() {
let hello_value = ObfStr::new(hello);
let same_value = ObfStr::new(hello);
let world_value = ObfStr::new(world);
let owned = String::from("hello");
assert_eq!(hello_value, same_value);
assert_ne!(hello_value, world_value);
assert_eq!(hello_value, "hello");
assert_eq!("hello", hello_value);
assert_eq!(hello_value, owned);
assert_eq!(String::from("hello"), hello_value);
}
}