diff --git a/src/bin/test.rs b/src/bin/test.rs index a45c278..830df4c 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -5,6 +5,7 @@ fn main() { std::fs::create_dir_all("data").ok(); + /* if let Ok(mut bf) = BlockFile::<16>::open("data/cache_data.bin") { if let Ok(id) = bf.insert("This is a test of the block file system.".as_bytes()) { let data = String::from_utf8(bf.get(id).unwrap()).unwrap(); @@ -13,8 +14,9 @@ fn main() } else { println!("Failed to open."); } + */ - /*if let Ok(mut tf) = TrieFile::<8>::open("data/cache_index.bin") { + if let Ok(mut tf) = TrieFile::<8>::open("data/cache_index.bin") { for s in [ "Hello", @@ -29,12 +31,32 @@ fn main() println!("Failed to insert '{}'.", s); } - if let Some(data) = tf.get(s.as_bytes()).unwrap() { - println!("found '{}'.", String::from_utf8(data).unwrap()); + if let Ok(Some(id)) = tf.find(s.as_bytes()) { + println!("found '{}'.", id); + + if let Ok(key) = tf.key(id) { + println!(" > '{}'", String::from_utf8(key).unwrap()); + } + + if let Ok(Some(data)) = tf.get(id) { + println!(" = '{}'", String::from_utf8(data).unwrap()); + } + } + } + + for i in tf.ids().unwrap() { + println!("id {}", i); + + if let Ok(key) = tf.key(i) { + println!(" > '{}'", String::from_utf8(key).unwrap()); + } + + if let Ok(Some(data)) = tf.get(i) { + println!(" = '{}'", String::from_utf8(data).unwrap()); } } } else { println!("Failed to open index."); - }*/ + } } diff --git a/src/blockfile/mod.rs b/src/blockfile/mod.rs index cfbb909..a05e9f7 100644 --- a/src/blockfile/mod.rs +++ b/src/blockfile/mod.rs @@ -238,6 +238,17 @@ impl BlockFile { Ok(data) } + pub fn ids(&self) -> Result, std::io::Error> + // Traverses object list and returns allocated ids. + // + { + let output = Vec::new(); + + // + + Ok(output) + } + fn allocate(&mut self, count:usize) -> Result, std::io::Error> // Mark as allocated and return the next available N blocks. // diff --git a/src/triefile/mod.rs b/src/triefile/mod.rs index 72d6545..4e6b5ec 100644 --- a/src/triefile/mod.rs +++ b/src/triefile/mod.rs @@ -16,8 +16,9 @@ use std::{ }; struct Node { - length:usize, + length:u8, bytes:[u8; 15], + parent:u32, next:u32, child:u32, has_data:bool, @@ -29,6 +30,7 @@ impl Node { Self { length:0, bytes:[0; 15], + parent:u32::MAX, next:0, child:0, has_data:false, @@ -45,6 +47,7 @@ impl Node { [ flags.pack(), self.bytes.to_vec(), + self.parent.pack(), self.next.pack(), self.child.pack(), self.data.to_vec(), @@ -55,7 +58,7 @@ impl Node { { if data.len() == Self::len() { let flags = u8::unpack(data, index)?; - self.length = (flags & 0x0F) as usize; + self.length = (flags & 0x0F) as u8; self.has_data = (flags & 0x80) != 0; for i in 0..15 { @@ -63,6 +66,7 @@ impl Node { *index += 1; } + self.parent = u32::unpack(data, index)?; self.next = u32::unpack(data, index)?; self.child = u32::unpack(data, index)?; @@ -79,7 +83,7 @@ impl Node { const fn len() -> usize { - 24 + Z + 28 + Z } } @@ -109,11 +113,12 @@ impl TrieFile { let mut node_index = 0; let mut key_index = 0; + let mut parent_index = u32::MAX; // Allocate first chain of nodes if none exist. if self.block_count()? == 0 { //println!("originate"); - self.trailing_nodes(key, &mut key_index, data)?; + self.trailing_nodes(key, &mut key_index, data, u32::MAX)?; return Ok(()); } else { //println!("traverse"); @@ -130,7 +135,7 @@ impl TrieFile { // Count length of shared prefix let mut prefix_index = 0; - while prefix_index < node.length + while prefix_index < node.length as usize && (key_index + prefix_index) < key.len() && key[key_index + prefix_index] == node.bytes[prefix_index] { prefix_index += 1; @@ -138,7 +143,7 @@ impl TrieFile { //println!("prefix {}", prefix_index); - if prefix_index == node.length { + if prefix_index == node.length as usize { key_index += prefix_index; // Copy data to node, mark as occupied, and write to file. @@ -159,7 +164,7 @@ impl TrieFile { else { if node.child != 0 { //println!(" - child"); - + parent_index = node_index; node_index = node.child; } @@ -167,7 +172,7 @@ impl TrieFile { else { //println!(" - new child"); - node.child = self.trailing_nodes(key, &mut key_index, data)?; + node.child = self.trailing_nodes(key, &mut key_index, data, node_index)?; self.write_node(node_index, &node)?; } } @@ -182,8 +187,7 @@ impl TrieFile { let prefix = node.bytes[0..prefix_index].to_vec(); let suffix = node.bytes[prefix_index..].to_vec(); - // - node.length = prefix.len(); + node.length = prefix.len() as u8; for i in prefix_index..node.bytes.len() { node.bytes[i] = 0; } @@ -191,7 +195,8 @@ impl TrieFile { let child_index = self.allocate()?; let mut child_node = Node::::new(); - child_node.length = suffix.len(); + child_node.parent = node_index; + child_node.length = suffix.len() as u8; for i in 0..15.min(suffix.len()) { child_node.bytes[i] = suffix[i]; } @@ -207,7 +212,7 @@ impl TrieFile { // Write data to trailing nodes. if key_index < key.len() { - let new_branch = self.trailing_nodes(key, &mut key_index, data)?; + let new_branch = self.trailing_nodes(key, &mut key_index, data, node_index)?; child_node.next = new_branch; } @@ -236,7 +241,7 @@ impl TrieFile { //println!(" - new next"); // Allocate and initialize subsequent nodes until key is resolved. - node.next = self.trailing_nodes(key, &mut key_index, data)?; + node.next = self.trailing_nodes(key, &mut key_index, data, parent_index)?; self.write_node(node_index, &node)?; } } @@ -246,7 +251,7 @@ impl TrieFile { Ok(()) } - pub fn get(&self, key:&[u8]) -> Result>, std::io::Error> + pub fn find(&self, key:&[u8]) -> Result, std::io::Error> { let mut node = Node::::new(); @@ -267,7 +272,7 @@ impl TrieFile { // Count length of shared prefix let mut prefix_index = 0; - while prefix_index < node.length + while prefix_index < node.length as usize && (key_index + prefix_index) < key.len() && key[key_index + prefix_index] == node.bytes[prefix_index] { prefix_index += 1; @@ -275,14 +280,14 @@ impl TrieFile { //println!("prefix {}", prefix_index); - if prefix_index == node.length { + if prefix_index == node.length as usize { key_index += prefix_index; // Return node contents. if key_index == key.len() { //println!(" - found node"); - return Ok(Some(node.data.to_vec())); + return Ok(Some(node_index as usize)); } // Continue to child node. @@ -319,20 +324,74 @@ impl TrieFile { Ok(None) } + pub fn key(&self, id:usize) -> Result, std::io::Error> + { + let mut node_id = id as u32; + let mut bytes = Vec::new(); + let mut node = Node::::new(); + + while node_id != u32::MAX { + self.read_node(node_id, &mut node)?; + + for i in (0..node.length as usize).rev() { + bytes.push(node.bytes[i]); + } + + node_id = node.parent; + } + + bytes.reverse(); + Ok(bytes) + } + + pub fn get(&self, id:usize) -> Result>, std::io::Error> + { + let mut node = Node::::new(); + self.read_node(id as u32, &mut node)?; + + if node.has_data { + Ok(Some(node.data.to_vec())) + } else { + Ok(None) + } + } + + pub fn ids(&self) -> Result, std::io::Error> + { + let mut output = Vec::new(); + + let mut node = Node::::new(); + let length = self.block_count()? as usize; + + for i in 0..length { + self.read_node(i as u32, &mut node)?; + + if node.has_data { + output.push(i); + } + } + + Ok(output) + } + /*pub fn unset(&self, _key:&[u8]) -> Result<(), std::io::Error> { Ok(()) }*/ - fn trailing_nodes(&mut self, key:&[u8], key_index:&mut usize, data:&[u8]) -> Result + fn trailing_nodes(&mut self, key:&[u8], key_index:&mut usize, data:&[u8], parent:u32) -> Result { let starting_node = self.allocate()?; let mut node :Node; let mut node_index = starting_node; + let mut parent_node = parent; while *key_index < key.len() { node = Node::::new(); + node.parent = parent_node; + parent_node = node_index; + // Copy key bytes to node. for i in 0..15.min(key.len() - *key_index) { node.bytes[i] = key[*key_index];