# Migration Guide: V to Rust RadixTree This document provides guidance for migrating from the V implementation of RadixTree to the Rust implementation. ## API Changes The Rust implementation maintains API compatibility with the V implementation, but with some idiomatic Rust changes: ### V API ```v // Create a new radix tree mut rt := radixtree.new(path: '/tmp/radixtree_test', reset: true)! // Set a key-value pair rt.set('test', 'value1'.bytes())! // Get a value by key value := rt.get('test')! // Update a value at a prefix rt.update('prefix', 'new_value'.bytes())! // Delete a key rt.delete('test')! // List keys with a prefix keys := rt.list('prefix')! // Get all values with a prefix values := rt.getall('prefix')! ``` ### Rust API ```rust // Create a new radix tree let mut tree = RadixTree::new("/tmp/radixtree_test", true)?; // Set a key-value pair tree.set("test", b"value1".to_vec())?; // Get a value by key let value = tree.get("test")?; // Update a value at a prefix tree.update("prefix", b"new_value".to_vec())?; // Delete a key tree.delete("test")?; // List keys with a prefix let keys = tree.list("prefix")?; // Get all values with a prefix let values = tree.getall("prefix")?; ``` ## Key Differences 1. **Error Handling**: The Rust implementation uses Rust's `Result` type for error handling, while the V implementation uses V's `!` operator. 2. **String Handling**: The Rust implementation uses Rust's `&str` for string parameters and `String` for string return values, while the V implementation uses V's `string` type. 3. **Binary Data**: The Rust implementation uses Rust's `Vec` for binary data, while the V implementation uses V's `[]u8` type. 4. **Constructor**: The Rust implementation uses a constructor function with separate parameters, while the V implementation uses a struct with named parameters. 5. **Ownership**: The Rust implementation follows Rust's ownership model, requiring mutable references for methods that modify the tree. ## Data Compatibility The Rust implementation maintains data compatibility with the V implementation: - The same serialization format is used for nodes - The same OurDB storage format is used - Existing RadixTree data created with the V implementation can be read by the Rust implementation ## Migration Steps 1. **Update Dependencies**: Replace the V RadixTree dependency with the Rust RadixTree dependency in your project. 2. **Update Import Statements**: Replace V import statements with Rust use statements. ```v // V import freeflowuniverse.herolib.data.radixtree ``` ```rust // Rust use radixtree::RadixTree; ``` 3. **Update Constructor Calls**: Replace V constructor calls with Rust constructor calls. ```v // V mut rt := radixtree.new(path: '/path/to/db', reset: false)! ``` ```rust // Rust let mut tree = RadixTree::new("/path/to/db", false)?; ``` 4. **Update Method Calls**: Replace V method calls with Rust method calls. ```v // V rt.set('key', 'value'.bytes())! ``` ```rust // Rust tree.set("key", b"value".to_vec())?; ``` 5. **Update Error Handling**: Replace V error handling with Rust error handling. ```v // V if value := rt.get('key') { println('Found: ${value.bytestr()}') } else { println('Error: ${err}') } ``` ```rust // Rust match tree.get("key") { Ok(value) => println!("Found: {}", String::from_utf8_lossy(&value)), Err(e) => println!("Error: {}", e), } ``` 6. **Update String Conversions**: Replace V string conversions with Rust string conversions. ```v // V value.bytestr() // Convert []u8 to string ``` ```rust // Rust String::from_utf8_lossy(&value) // Convert Vec to string ``` ## Example Migration ### V Code ```v module main import freeflowuniverse.herolib.data.radixtree fn main() { mut rt := radixtree.new(path: '/tmp/radixtree_test', reset: true) or { println('Error creating RadixTree: ${err}') return } rt.set('hello', 'world'.bytes()) or { println('Error setting key: ${err}') return } rt.set('help', 'me'.bytes()) or { println('Error setting key: ${err}') return } if value := rt.get('hello') { println('hello: ${value.bytestr()}') } else { println('Error getting key: ${err}') return } keys := rt.list('hel') or { println('Error listing keys: ${err}') return } println('Keys with prefix "hel": ${keys}') values := rt.getall('hel') or { println('Error getting all values: ${err}') return } println('Values with prefix "hel":') for i, value in values { println(' ${i}: ${value.bytestr()}') } rt.delete('help') or { println('Error deleting key: ${err}') return } println('Deleted "help"') } ``` ### Rust Code ```rust use radixtree::RadixTree; fn main() -> Result<(), Box> { let mut tree = RadixTree::new("/tmp/radixtree_test", true) .map_err(|e| format!("Error creating RadixTree: {}", e))?; tree.set("hello", b"world".to_vec()) .map_err(|e| format!("Error setting key: {}", e))?; tree.set("help", b"me".to_vec()) .map_err(|e| format!("Error setting key: {}", e))?; let value = tree.get("hello") .map_err(|e| format!("Error getting key: {}", e))?; println!("hello: {}", String::from_utf8_lossy(&value)); let keys = tree.list("hel") .map_err(|e| format!("Error listing keys: {}", e))?; println!("Keys with prefix \"hel\": {:?}", keys); let values = tree.getall("hel") .map_err(|e| format!("Error getting all values: {}", e))?; println!("Values with prefix \"hel\":"); for (i, value) in values.iter().enumerate() { println!(" {}: {}", i, String::from_utf8_lossy(value)); } tree.delete("help") .map_err(|e| format!("Error deleting key: {}", e))?; println!("Deleted \"help\""); Ok(()) } ``` ## Performance Considerations The Rust implementation should provide similar or better performance compared to the V implementation. However, there are some considerations: 1. **Memory Usage**: The Rust implementation may have different memory usage patterns due to Rust's ownership model. 2. **Error Handling**: The Rust implementation uses Rust's `Result` type, which may have different performance characteristics compared to V's error handling. 3. **String Handling**: The Rust implementation uses Rust's string types, which may have different performance characteristics compared to V's string types. ## Troubleshooting If you encounter issues during migration, check the following: 1. **Data Compatibility**: Ensure that the data format is compatible between the V and Rust implementations. 2. **API Usage**: Ensure that you're using the correct API for the Rust implementation. 3. **Error Handling**: Ensure that you're handling errors correctly in the Rust implementation. 4. **String Encoding**: Ensure that string encoding is consistent between the V and Rust implementations. If you encounter any issues that are not covered in this guide, please report them to the project maintainers.