This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 39b2c06ed fix(rust): stabilize meta string dynamic cache (#3822)
39b2c06ed is described below

commit 39b2c06ed7aab4b36fe5b50f17592a8ff02c00e9
Author: Shawn Yang <[email protected]>
AuthorDate: Tue Jul 7 22:34:11 2026 +0530

    fix(rust): stabilize meta string dynamic cache (#3822)
    
    ## Why?
    
    
    
    ## What does this PR do?
    
    
    
    ## Related issues
    
    
    
    ## AI Contribution Checklist
    
    
    
    - [ ] Substantial AI assistance was used in this PR: `yes` / `no`
    - [ ] If `yes`, I included a completed [AI Contribution
    
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
    in this PR description and the required `AI Usage Disclosure`.
    - [ ] If `yes`, my PR description includes the required `ai_review`
    summary and screenshot evidence or equivalent persisted links of the
    final clean AI review results from both fresh reviewers described in
    `AI_POLICY.md`, the Fory-guided reviewer and the independent general
    reviewer, on the current PR diff or current HEAD after the latest code
    changes.
    
    
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 .../fory-core/src/resolver/meta_string_resolver.rs | 14 ++---
 rust/tests/tests/test_meta_string_resolver.rs      | 60 ++++++++++++++++++++++
 2 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/rust/fory-core/src/resolver/meta_string_resolver.rs 
b/rust/fory-core/src/resolver/meta_string_resolver.rs
index f8593e4e4..154695909 100644
--- a/rust/fory-core/src/resolver/meta_string_resolver.rs
+++ b/rust/fory-core/src/resolver/meta_string_resolver.rs
@@ -185,8 +185,10 @@ impl MetaStringWriterResolver {
 
 pub struct MetaStringReaderResolver {
     meta_string_bytes_to_string: HashMap<*const MetaStringBytes, MetaString>,
-    hash_to_meta_string_bytes: HashMap<i64, MetaStringBytes>,
-    long_long_byte_map: HashMap<(u64, u64, u8), MetaStringBytes>,
+    // `dynamic_read` stores raw pointers into these values. Keep the bytes 
behind
+    // a stable heap owner so HashMap rehashes cannot move the pointee.
+    hash_to_meta_string_bytes: HashMap<i64, Box<MetaStringBytes>>,
+    long_long_byte_map: HashMap<(u64, u64, u8), Box<MetaStringBytes>>,
     dynamic_read: Vec<Option<*const MetaStringBytes>>,
     dynamic_read_id: usize,
 }
@@ -270,12 +272,12 @@ impl MetaStringReaderResolver {
         let mb_ref: &mut MetaStringBytes = match 
self.hash_to_meta_string_bytes.entry(hash_code) {
             Entry::Occupied(entry) => {
                 reader.skip(len)?;
-                entry.into_mut()
+                entry.into_mut().as_mut()
             }
             Entry::Vacant(entry) => {
                 let bytes = reader.read_bytes(len)?.to_vec();
                 let mb = MetaStringBytes::new(bytes, hash_code)?;
-                entry.insert(mb)
+                entry.insert(Box::new(mb)).as_mut()
             }
         };
 
@@ -318,7 +320,7 @@ impl MetaStringReaderResolver {
         let key = (v1, v2, encoding_val);
 
         let mb_ref = match self.long_long_byte_map.entry(key) {
-            Entry::Occupied(entry) => entry.into_mut(),
+            Entry::Occupied(entry) => entry.into_mut().as_mut(),
             Entry::Vacant(entry) => {
                 let mut data = vec![0u8; 16];
                 data[0..8].copy_from_slice(&v1.to_le_bytes());
@@ -329,7 +331,7 @@ impl MetaStringReaderResolver {
                 let hash_code =
                     (hash_code as u64 & 0xffffffffffffff00_u64) as i64 | 
(encoding_val as i64);
                 let mb = MetaStringBytes::new(data, hash_code)?;
-                entry.insert(mb)
+                entry.insert(Box::new(mb)).as_mut()
             }
         };
         // update dynamic_read
diff --git a/rust/tests/tests/test_meta_string_resolver.rs 
b/rust/tests/tests/test_meta_string_resolver.rs
index d083ae658..468c869d3 100644
--- a/rust/tests/tests/test_meta_string_resolver.rs
+++ b/rust/tests/tests/test_meta_string_resolver.rs
@@ -133,3 +133,63 @@ pub fn big_ms() {
         meta_string_reader.reset();
     }
 }
+
+#[test]
+pub fn big_dynamic_survives_growth() {
+    let mut meta_string_writer = MetaStringWriterResolver::default();
+    let data: Vec<_> = (0..20)
+        .map(|i| {
+            Rc::from(
+                NAMESPACE_ENCODER
+                    
.encode(&format!("long_meta_string_name_{i:02}_after_growth"))
+                    .unwrap(),
+            )
+        })
+        .collect();
+
+    let mut buffer = vec![];
+    let mut writer = Writer::from_buffer(&mut buffer);
+    for meta_string in data.iter() {
+        meta_string_writer
+            .write_meta_string_bytes(&mut writer, meta_string.clone())
+            .unwrap();
+    }
+    writer.write_var_u32(3);
+
+    let binding = writer.dump();
+    let mut reader = Reader::new(binding.as_slice());
+    let mut meta_string_reader = MetaStringReaderResolver::default();
+    for meta_string in data.iter() {
+        let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+        assert_eq!(&**meta_string, read);
+    }
+    let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+    assert_eq!(&*data[0], read);
+}
+
+#[test]
+pub fn small_dynamic_survives_growth() {
+    let mut meta_string_writer = MetaStringWriterResolver::default();
+    let data: Vec<_> = (0..20)
+        .map(|i| 
Rc::from(NAMESPACE_ENCODER.encode(&format!("s{i:014}")).unwrap()))
+        .collect();
+
+    let mut buffer = vec![];
+    let mut writer = Writer::from_buffer(&mut buffer);
+    for meta_string in data.iter() {
+        meta_string_writer
+            .write_meta_string_bytes(&mut writer, meta_string.clone())
+            .unwrap();
+    }
+    writer.write_var_u32(3);
+
+    let binding = writer.dump();
+    let mut reader = Reader::new(binding.as_slice());
+    let mut meta_string_reader = MetaStringReaderResolver::default();
+    for meta_string in data.iter() {
+        let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+        assert_eq!(&**meta_string, read);
+    }
+    let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+    assert_eq!(&*data[0], read);
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to