...
This commit is contained in:
@@ -8,22 +8,18 @@ use std::path::PathBuf;
|
||||
|
||||
/// Creates a new TST with the specified database path.
|
||||
pub fn new_tst(path: &str, reset: bool) -> Result<TST, Error> {
|
||||
// If the path exists and reset is true, remove it first
|
||||
let path_buf = PathBuf::from(path);
|
||||
if path_buf.exists() && reset {
|
||||
std::fs::remove_dir_all(&path_buf)?;
|
||||
}
|
||||
|
||||
// Create the directory if it doesn't exist
|
||||
std::fs::create_dir_all(&path_buf)?;
|
||||
|
||||
// Create the configuration for OurDB with reset parameter
|
||||
let config = OurDBConfig {
|
||||
path: path_buf,
|
||||
path: path_buf.clone(),
|
||||
incremental_mode: true,
|
||||
file_size: Some(1024 * 1024), // 10MB file size for better performance with large datasets
|
||||
file_size: Some(1024 * 1024), // 1MB file size for better performance with large datasets
|
||||
keysize: Some(4), // Use keysize=4 (default)
|
||||
reset: Some(reset), // Use the reset parameter
|
||||
};
|
||||
|
||||
// Create a new OurDB instance (it will handle reset internally)
|
||||
let mut db = OurDB::new(config)?;
|
||||
|
||||
let root_id = if db.get_next_id()? == 1 || reset {
|
||||
@@ -275,8 +271,17 @@ pub fn list(tree: &mut TST, prefix: &str) -> Result<Vec<String>, Error> {
|
||||
Err(_) => return Ok(Vec::new()), // Prefix not found, return empty list
|
||||
};
|
||||
|
||||
// For empty prefix, we start with an empty string
|
||||
// For non-empty prefix, we start with the prefix minus the last character
|
||||
// (since the last character is in the node we found)
|
||||
let prefix_base = if chars.len() > 1 {
|
||||
chars[0..chars.len()-1].iter().collect()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
// Collect all keys from the subtree
|
||||
collect_keys_with_prefix(tree, node_id, prefix.to_string(), &mut result)?;
|
||||
collect_keys_with_prefix(tree, node_id, prefix_base, &mut result)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
@@ -327,24 +332,29 @@ fn collect_keys_with_prefix(
|
||||
) -> Result<(), Error> {
|
||||
let node = tree.get_node(node_id)?;
|
||||
|
||||
let mut new_path = current_path.clone();
|
||||
|
||||
// For non-root nodes, add the character to the path
|
||||
if node.character != '\0' {
|
||||
new_path.push(node.character);
|
||||
}
|
||||
|
||||
// If this node is an end of key, add it to the result
|
||||
if node.is_end_of_key {
|
||||
result.push(current_path.clone());
|
||||
result.push(new_path.clone());
|
||||
}
|
||||
|
||||
// Recursively collect keys from all children
|
||||
if let Some(left_id) = node.left_id {
|
||||
collect_all_keys(tree, left_id, current_path.clone(), result)?;
|
||||
collect_keys_with_prefix(tree, left_id, current_path.clone(), result)?;
|
||||
}
|
||||
|
||||
if let Some(middle_id) = node.middle_id {
|
||||
let mut new_path = current_path.clone();
|
||||
new_path.push(node.character);
|
||||
collect_all_keys(tree, middle_id, new_path, result)?;
|
||||
collect_keys_with_prefix(tree, middle_id, new_path.clone(), result)?;
|
||||
}
|
||||
|
||||
if let Some(right_id) = node.right_id {
|
||||
collect_all_keys(tree, right_id, current_path.clone(), result)?;
|
||||
collect_keys_with_prefix(tree, right_id, current_path.clone(), result)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -360,7 +370,11 @@ fn collect_all_keys(
|
||||
let node = tree.get_node(node_id)?;
|
||||
|
||||
let mut new_path = current_path.clone();
|
||||
new_path.push(node.character);
|
||||
|
||||
// Skip adding the character for the root node
|
||||
if node.character != '\0' {
|
||||
new_path.push(node.character);
|
||||
}
|
||||
|
||||
// If this node is an end of key, add it to the result
|
||||
if node.is_end_of_key {
|
||||
@@ -390,20 +404,30 @@ pub fn getall(tree: &mut TST, prefix: &str) -> Result<Vec<Vec<u8>>, Error> {
|
||||
|
||||
// Get values for each key
|
||||
let mut values = Vec::new();
|
||||
let mut errors = Vec::new();
|
||||
|
||||
for key in keys {
|
||||
if let Ok(value) = get(tree, &key) {
|
||||
values.push(value);
|
||||
match get(tree, &key) {
|
||||
Ok(value) => values.push(value),
|
||||
Err(e) => errors.push(format!("Error getting value for key '{}': {:?}", key, e))
|
||||
}
|
||||
}
|
||||
|
||||
// If we couldn't get any values but had keys, return the first error
|
||||
if values.is_empty() && !errors.is_empty() {
|
||||
return Err(Error::InvalidOperation(errors.join("; ")));
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
|
||||
impl TST {
|
||||
/// Helper function to get a node from the database.
|
||||
pub(crate) fn get_node(&mut self, node_id: u32) -> Result<TSTNode, Error> {
|
||||
let data = self.db.get(node_id)?;
|
||||
TSTNode::deserialize(&data)
|
||||
match self.db.get(node_id) {
|
||||
Ok(data) => TSTNode::deserialize(&data),
|
||||
Err(err) => Err(Error::OurDB(err)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to save a node to the database.
|
||||
@@ -413,6 +437,9 @@ impl TST {
|
||||
id: node_id,
|
||||
data: &data,
|
||||
};
|
||||
Ok(self.db.set(args)?)
|
||||
match self.db.set(args) {
|
||||
Ok(id) => Ok(id),
|
||||
Err(err) => Err(Error::OurDB(err)),
|
||||
}
|
||||
}
|
||||
}
|
@@ -114,21 +114,4 @@ impl TSTNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the common prefix of two strings.
|
||||
pub fn get_common_prefix(a: &str, b: &str) -> String {
|
||||
let mut result = String::new();
|
||||
let a_chars: Vec<char> = a.chars().collect();
|
||||
let b_chars: Vec<char> = b.chars().collect();
|
||||
|
||||
let min_len = a_chars.len().min(b_chars.len());
|
||||
|
||||
for i in 0..min_len {
|
||||
if a_chars[i] == b_chars[i] {
|
||||
result.push(a_chars[i]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
// Function removed as it was unused
|
Reference in New Issue
Block a user