add data packages and remove empty submodule
This commit is contained in:
265
packages/data/radixtree/MIGRATION.md
Normal file
265
packages/data/radixtree/MIGRATION.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# 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<u8>` 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<u8> 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<dyn std::error::Error>> {
|
||||
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.
|
Reference in New Issue
Block a user