Refactor Store trait to use &String for input. Implement index node serialization.

This commit is contained in:
femsci 2023-02-03 12:29:38 +01:00
parent 02c01ffa2c
commit 179b220c2e
Signed by: femsci
GPG key ID: 08F7911F0E650C67
4 changed files with 120 additions and 27 deletions

View file

@ -24,5 +24,15 @@ fn main() {
Ok(x) => x, Ok(x) => x,
}; };
store.get_creds("nya".to_string(), "meow".to_string()); let (key, specifier) = ("nya".to_string(), "meow".to_string());
match store.get_creds(&key, &specifier) {
Some(x) => {
println!("Credentials: {:?}", x);
}
None => println!(
"Credentials for key '{}' and specifier '{}' not found...",
key, specifier
),
}
} }

View file

@ -4,8 +4,7 @@ use std::{
fs::File, fs::File,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
io::{BufReader, Read, Seek, SeekFrom, Write}, io::{BufReader, Read, Seek, SeekFrom, Write},
iter::TakeWhile, path::Path,
path::{Iter, Path},
}; };
use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit, Nonce}; use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit, Nonce};
@ -230,7 +229,7 @@ fn try_create_store(path: &String, passphrase: &Vec<u8>) -> bool {
let meta = LocalStoreMeta { let meta = LocalStoreMeta {
record_count: 0, record_count: 0,
specifier_count: 0, specifier_count: 0,
index_node_arity: 64, index_node_arity: 16,
data_block_size: 8092, data_block_size: 8092,
data_offset: 0, data_offset: 0,
}; };
@ -254,6 +253,13 @@ fn try_create_store(path: &String, passphrase: &Vec<u8>) -> bool {
header.chksum_crc = header.get_checksum(); header.chksum_crc = header.get_checksum();
let mut index_block: Vec<u8> = vec![0; meta.data_block_size as usize]; let mut index_block: Vec<u8> = vec![0; meta.data_block_size as usize];
let root_node_buf = IndexNode {
node_type: IndexNodeType::Leaf,
children: Vec::new(),
}
.serialize(&meta);
index_block[0..root_node_buf.len()].copy_from_slice(&root_node_buf);
let mut buf = serialize_header(&header); let mut buf = serialize_header(&header);
@ -500,20 +506,25 @@ impl LocalRecord {
} }
impl Store for LocalStore { impl Store for LocalStore {
fn get_creds(&self, specifier: String, key: String) -> Option<StoreRecord> { fn get_creds(&self, specifier: &String, key: &String) -> Option<StoreRecord> {
self.btree_find_key(&key); match self.btree_find_key(&key) {
Some(x) => {
println!("Found: {}", x);
todo!() todo!()
} }
None => return None,
}
}
fn get_creds_by_specifier(&self, specifier: String) -> Vec<StoreRecord> { fn get_creds_by_specifier(&self, specifier: &String) -> Vec<StoreRecord> {
todo!() todo!()
} }
fn store_creds( fn store_creds(
&self, &self,
specifier: String, specifier: &String,
key: String, key: &String,
value: Vec<u8>, value: &Vec<u8>,
r#type: RecordType, r#type: RecordType,
meta: Option<String>, meta: Option<String>,
) { ) {
@ -521,11 +532,11 @@ impl Store for LocalStore {
} }
} }
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
enum IndexNodeType { enum IndexNodeType {
Internal, Internal = 1,
Leaf, Leaf = 2,
Invalid, Invalid = 0,
} }
impl From<u8> for IndexNodeType { impl From<u8> for IndexNodeType {
@ -557,6 +568,20 @@ impl IndexNode {
fn len(&self) -> usize { fn len(&self) -> usize {
self.children.len() self.children.len()
} }
fn serialize(&self, meta: &LocalStoreMeta) -> Vec<u8> {
let mut buf: Vec<u8> = vec![0; 16 * meta.index_node_arity as usize + 2];
let mut cnt = 2;
for child in self.children() {
buf[cnt..(cnt + 8)].copy_from_slice(&child.key.to_be_bytes());
buf[(cnt + 8)..(cnt + 16)].copy_from_slice(&child.pointer.to_be_bytes());
cnt += 16;
}
buf[0] = self.node_type as u8;
buf
}
} }
impl LocalStore { impl LocalStore {
@ -740,7 +765,7 @@ mod tests {
StoreRecord, StoreRecord,
}; };
use super::LocalRecord; use super::{IndexNode, IndexNodeEntry, IndexNodeType, LocalRecord};
#[test] #[test]
fn header_size_const_greater_than_realsize() { fn header_size_const_greater_than_realsize() {
@ -816,4 +841,62 @@ mod tests {
assert_eq!(serialized, reserialized); assert_eq!(serialized, reserialized);
} }
#[test]
fn index_node_serialize() {
let root = IndexNode {
node_type: IndexNodeType::Internal,
children: vec![IndexNodeEntry {
key: 1,
pointer: 258,
}],
};
let leaf = IndexNode {
node_type: IndexNodeType::Leaf,
children: vec![
IndexNodeEntry {
key: 1,
pointer: 516,
},
IndexNodeEntry {
key: 4,
pointer: 520,
},
IndexNodeEntry {
key: 16,
pointer: 524,
},
],
};
let meta = super::LocalStoreMeta {
record_count: 3,
specifier_count: 0,
index_node_arity: 16,
data_block_size: 8192,
data_offset: 0,
};
let root_bytes = root.serialize(&meta);
let leaf_bytes = leaf.serialize(&meta);
assert_eq!(IndexNodeType::from(root_bytes[0]), root.node_type);
assert_eq!(IndexNodeType::from(leaf_bytes[0]), leaf.node_type);
assert_eq!(root_bytes[2..10], root.children[0].key.to_be_bytes());
assert_eq!(root_bytes[10..18], root.children[0].pointer.to_be_bytes());
assert!(root_bytes.iter().skip(18).all(|x| *x == 0u8));
let mut cnt = 2;
for child in leaf.children {
assert_eq!(leaf_bytes[cnt..(cnt + 8)], child.key.to_be_bytes());
assert_eq!(
leaf_bytes[(cnt + 8)..(cnt + 16)],
child.pointer.to_be_bytes()
);
cnt += 16;
}
assert!(root_bytes.iter().skip(cnt).all(|x| *x == 0u8));
}
} }

View file

@ -39,13 +39,13 @@ impl From<u8> for RecordType {
} }
pub trait Store { pub trait Store {
fn get_creds(&self, specifier: String, key: String) -> Option<StoreRecord>; fn get_creds(&self, specifier: &String, key: &String) -> Option<StoreRecord>;
fn get_creds_by_specifier(&self, specifier: String) -> Vec<StoreRecord>; fn get_creds_by_specifier(&self, specifier: &String) -> Vec<StoreRecord>;
fn store_creds( fn store_creds(
&self, &self,
specifier: String, specifier: &String,
key: String, key: &String,
value: Vec<u8>, value: &Vec<u8>,
r#type: RecordType, r#type: RecordType,
meta: Option<String>, meta: Option<String>,
); );

View file

@ -1,6 +1,6 @@
use reqwest::header::HeaderValue; use reqwest::header::HeaderValue;
use super::{Store, StoreRecord, RecordType}; use super::{RecordType, Store, StoreRecord};
pub struct ServerStore { pub struct ServerStore {
address: String, address: String,
@ -41,19 +41,19 @@ impl ServerStore {
} }
impl Store for ServerStore { impl Store for ServerStore {
fn get_creds(&self, specifier: String, key: String) -> Option<StoreRecord> { fn get_creds(&self, specifier: &String, key: &String) -> Option<StoreRecord> {
todo!() todo!()
} }
fn get_creds_by_specifier(&self, specifier: String) -> Vec<StoreRecord> { fn get_creds_by_specifier(&self, specifier: &String) -> Vec<StoreRecord> {
todo!() todo!()
} }
fn store_creds( fn store_creds(
&self, &self,
specifier: String, specifier: &String,
key: String, key: &String,
value: Vec<u8>, value: &Vec<u8>,
r#type: RecordType, r#type: RecordType,
meta: Option<String>, meta: Option<String>,
) { ) {