diff --git a/Cargo.lock b/Cargo.lock index ab5a815..e17a0fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,7 +156,7 @@ dependencies = [ [[package]] name = "stacksafe" -version = "0.1.2" +version = "0.1.3" dependencies = [ "derive-visitor", "serde", @@ -166,7 +166,7 @@ dependencies = [ [[package]] name = "stacksafe-macro" -version = "0.1.2" +version = "0.1.3" dependencies = [ "proc-macro-error2", "quote", diff --git a/Cargo.toml b/Cargo.toml index f1509bc..cb530b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,12 +7,12 @@ edition = "2021" license = "Apache-2.0" repository = "https://github.com/fast/stacksafe" rust-version = "1.80.0" -version = "0.1.2" +version = "0.1.3" [workspace.dependencies] # workspace dependencies -stacksafe = { version = "0.1.2", path = "stacksafe" } -stacksafe-macro = { version = "=0.1.2", path = "stacksafe-macro" } +stacksafe = { version = "0.1.3", path = "stacksafe" } +stacksafe-macro = { version = "=0.1.3", path = "stacksafe-macro" } # crates.io dependencies derive-visitor = "0.4" diff --git a/stacksafe/src/lib.rs b/stacksafe/src/lib.rs index 378fb27..6ad15e1 100644 --- a/stacksafe/src/lib.rs +++ b/stacksafe/src/lib.rs @@ -218,6 +218,38 @@ impl StackSafe { pub fn new(value: T) -> Self { StackSafe(std::mem::ManuallyDrop::new(value)) } + + /// Consumes the [`StackSafe`] wrapper and returns the inner value. + /// + /// # Panics + /// + /// In debug builds, panics if called outside of a stack-safe context. + /// This helps ensure that recursive data structure access is properly + /// protected against stack overflow. + /// + /// # Examples + /// + /// ```rust + /// # #[stacksafe::stacksafe] + /// # fn main() { + /// use stacksafe::StackSafe; + /// + /// let wrapped = StackSafe::new(vec![1, 2, 3]); + /// let inner = wrapped.into_inner(); + /// assert_eq!(inner, vec![1, 2, 3]); + /// # } + /// ``` + pub fn into_inner(mut self) -> T { + debug_assert!( + crate::internal::is_protected(), + "`StackSafe` should only be accessed within a stack-safe context\n\ + help: add `#[stacksafe::stacksafe]` to the function containing this access" + ); + + let value = unsafe { std::mem::ManuallyDrop::take(&mut self.0) }; + std::mem::forget(self); + value + } } impl From for StackSafe {