rust_code_obfuscator_core 0.3.2

Core encryption and obfuscation logic for rustfuscator
Documentation
use core::fmt;

#[derive(Copy, Clone)]
pub struct ObfStr {
    /// Initialization function that returns the cached `'static` string.
    ///
    /// The function typically contains a `OnceLock` + decryption logic,
    /// generated by the macro expansion.
    init: fn() -> &'static str,
}

impl ObfStr {
    /// Creates a new `ObfStr` from an initialization function.
    ///
    /// This is intended to be used only by the `obfuscate_string!` macro.
    #[inline]
    pub const fn new(init: fn() -> &'static str) -> Self {
        Self { init }
    }

    /// Returns the decrypted string as a `&'static str`.
    ///
    /// The string is decrypted only once per call-site and then cached.
    #[inline]
    pub fn as_str(self) -> &'static str {
        (self.init)()
    }

    /// Converts this `ObfStr` into an owned `String`.
    ///
    /// This is useful for backward compatibility with APIs that
    /// require ownership.
    #[inline]
    pub fn into_string(self) -> String {
        self.as_str().to_owned()
    }
}

// &str ergonomics
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)()
    }
}
// Formatting
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 {
        // Debug output matches `&str` behavior
        fmt::Debug::fmt((self.init)(), f)
    }
}

// Comparisons
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)()
    }
}

// Conversions
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);
    }
}