From 0283aac6210fb247e5e6559d597ba3ad8cf5f0f2 Mon Sep 17 00:00:00 2001 From: cijiugechu Date: Wed, 25 Feb 2026 16:27:36 +0800 Subject: [PATCH] fix: tie rust export borrows to analysis lifetime --- rust/src/ffi.rs | 21 --------------------- rust/src/lib.rs | 35 +++++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/rust/src/ffi.rs b/rust/src/ffi.rs index 8ac5552..a966915 100644 --- a/rust/src/ffi.rs +++ b/rust/src/ffi.rs @@ -14,27 +14,6 @@ pub struct merve_string { pub length: usize, } -impl merve_string { - /// Convert to a Rust `&str` with an arbitrary lifetime. - /// - /// Returns `""` when `length` is 0 (which includes the case where `data` is null). - /// - /// # Safety - /// The caller must ensure that the backing data outlives `'a` and is valid UTF-8. - /// The `merve_string` itself is a temporary POD value; the data it points to - /// lives in the original source buffer or the analysis handle. - #[must_use] - pub unsafe fn as_str<'a>(&self) -> &'a str { - if self.length == 0 { - return ""; - } - unsafe { - let slice = core::slice::from_raw_parts(self.data.cast(), self.length); - core::str::from_utf8_unchecked(slice) - } - } -} - /// Opaque handle to a CommonJS parse result. pub type merve_analysis = *mut c_void; diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 4e319a7..a06c6ac 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -136,6 +136,17 @@ unsafe impl Send for Analysis<'_> {} unsafe impl Sync for Analysis<'_> {} impl<'a> Analysis<'a> { + #[inline] + fn str_from_ffi(&self, s: ffi::merve_string) -> &str { + if s.length == 0 { + return ""; + } + unsafe { + let slice = core::slice::from_raw_parts(s.data.cast(), s.length); + core::str::from_utf8_unchecked(slice) + } + } + /// Number of named exports found. #[must_use] pub fn exports_count(&self) -> usize { @@ -152,12 +163,12 @@ impl<'a> Analysis<'a> { /// /// Returns `None` if `index` is out of bounds. #[must_use] - pub fn export_name(&self, index: usize) -> Option<&'a str> { + pub fn export_name(&self, index: usize) -> Option<&str> { if index >= self.exports_count() { return None; } let s = unsafe { ffi::merve_get_export_name(self.handle, index) }; - Some(unsafe { s.as_str() }) + Some(self.str_from_ffi(s)) } /// Get the 1-based source line number of the export at `index`. @@ -169,19 +180,23 @@ impl<'a> Analysis<'a> { return None; } let line = unsafe { ffi::merve_get_export_line(self.handle, index) }; - if line == 0 { None } else { Some(line) } + if line == 0 { + None + } else { + Some(line) + } } /// Get the module specifier of the re-export at `index`. /// /// Returns `None` if `index` is out of bounds. #[must_use] - pub fn reexport_name(&self, index: usize) -> Option<&'a str> { + pub fn reexport_name(&self, index: usize) -> Option<&str> { if index >= self.reexports_count() { return None; } let s = unsafe { ffi::merve_get_reexport_name(self.handle, index) }; - Some(unsafe { s.as_str() }) + Some(self.str_from_ffi(s)) } /// Get the 1-based source line number of the re-export at `index`. @@ -193,7 +208,11 @@ impl<'a> Analysis<'a> { return None; } let line = unsafe { ffi::merve_get_reexport_line(self.handle, index) }; - if line == 0 { None } else { Some(line) } + if line == 0 { + None + } else { + Some(line) + } } /// Iterate over all named exports. @@ -260,8 +279,8 @@ pub struct ExportIter<'a, 'b> { count: usize, } -impl<'a> Iterator for ExportIter<'a, '_> { - type Item = Export<'a>; +impl<'a, 'b> Iterator for ExportIter<'a, 'b> { + type Item = Export<'b>; fn next(&mut self) -> Option { if self.index >= self.count {