This commit is contained in:
2025-04-20 07:28:59 +02:00
parent eccea1ad04
commit 0051754c65
11 changed files with 251 additions and 93 deletions

View File

@@ -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)),
}
}
}

View File

@@ -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