basic JSON message handling. not tested yet at all

This commit is contained in:
Sebastian Moser
2023-02-12 23:25:50 +01:00
parent d3ecfcabf4
commit 9825c5242b
7 changed files with 790 additions and 1081 deletions

View File

@@ -6,6 +6,10 @@ use itertools::Itertools;
use crate::error;
use crate::error::MizeError;
use crate::server::proto;
use crate::server::Mutexes;
use serde_json::Value as JsonValue;
use serde::{Serialize, Deserialize};
use super::proto::Delta;
@@ -16,37 +20,72 @@ pub struct Itemstore {
db: surrealdb::Datastore,
}
pub type Item = Vec<[Vec<u8>; 2]>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Item {
#[serde(flatten)]
pub json: JsonValue,
}
impl Item {
pub fn get_id(&self) -> Result<String, MizeError> {
if let JsonValue::Object(ob) = &self.json{
if let Some(id_val) = ob.get("mize-id") {
if let JsonValue::String(id) = id_val {
return Ok(id.to_string())
} else {
return Err(MizeError::new(11).extra_msg("mize-id field in an item was not a String"));
}
} else {
return Err(MizeError::new(11).extra_msg("There was no mize-id field in an item"));
}
} else {
return Err(MizeError::new(11).extra_msg("An Item was not a JsonValue::Object"));
}
}
pub fn apply_delta(&mut self, delta: Delta) -> Result<(), MizeError> {
for (path, value) in delta.raw {
let mut to_replace = &mut self.json;
for name in path {
to_replace = if to_replace.get(&name).is_none() {
return Err(MizeError::new(11)
.extra_msg("Error applying a Delta to an Item. The path could not be followed."));
} else {
to_replace.get_mut(&name).ok_or(MizeError::new(11))?
};
}
*to_replace = value;
}
return Ok(())
}
pub fn from_bytes(vec: Vec<u8>) -> Result<Item, MizeError> {
let string = String::from_utf8(vec)?;
let item = serde_json::from_str(&string)?;
return Ok(item);
}
}
impl Itemstore {
pub async fn new(path: String) -> Result<Itemstore, MizeError> {
let ds = Datastore::new(&(String::from("file://") + &path[..] + "/db")[..]).await.expect("Could not open database");
let ds = Datastore::new(&(String::from("file://") + &path[..] + "/db")[..]).await
.map_err(|_| MizeError::new(30).format(vec![&path]))?;
let mut tr = ds.transaction(true, false).await?;
match tr.get(vec!('0' as u8)).await {
match tr.get(0u64.to_le_bytes()).await {
Ok(Some(val)) => println!("item 0 already created"),
Ok(None) => {
let keys = vec![
"num_of_items".as_bytes().to_vec(),
"next_free_id".as_bytes().to_vec(),
"_commit".as_bytes().to_vec(),
"_type".as_bytes().to_vec(),
//"renders".as_bytes().to_vec(),
//"modules".as_bytes().to_vec(),
];
tr.set("0".to_string().into_bytes(), encode(keys)).await?;
let one: u64 = 1;
let zero: u64 = 0;
tr.set("0:num_of_items".to_string().into_bytes(), one.to_be_bytes()).await?;
tr.set("0:next_free_id".to_string().into_bytes(), one.to_be_bytes()).await?;
tr.set("0:_commit".to_string().into_bytes(), zero.to_be_bytes()).await?;
tr.set("0:_type".to_string().into_bytes(), "mize-main".as_bytes().to_vec()).await?;
//tr.set("0:renders".to_string().into_bytes(), Vec::new());
//tr.set("0:modules".to_string().into_bytes(), Vec::new());
let data = serde_json::json!({
"num_of_items": 0,
"next_free_id": 0,
"_commit": 0,
"mize-type": "mize-main",
"mize-id": "0"
});
tr.set(0u64.to_be_bytes(), data.to_string()).await?;
tr.commit().await?;
},
@@ -55,83 +94,50 @@ impl Itemstore {
return Ok(Itemstore {db:ds});
}
pub async fn create(&self, item: Item) -> Result<u64, MizeError> {
let mut new_id:u64 = 0;
pub async fn create(&self, mut item: Item, mutexes: Mutexes) -> Result<u64, MizeError> {
let mut tr = self.db.transaction(true, false).await?;
let id = tr.get("0:next_free_id").await
.expect("no item with id 0 when there definetly should be one")
.expect("error reading item 0 from db");
let id_u64 = u64::from_be_bytes(id.clone().try_into().unwrap());
let mut keys: Vec<Vec<u8>> = Vec::new();
//set id:_commit
let key = format!("{}:_commit", id_u64).into_bytes();
tr.set(key.clone(), vec![0,0,0,0,0,0,0,0]).await?;
keys.push("_commit".to_owned().into_bytes());
//get next_free_id
let json: JsonValue = serde_json::from_str(&String::from_utf8(tr.get(0u64.to_be_bytes()).await?.ok_or(MizeError::new(31))?)
.map_err(|_| MizeError::new(11))?)
.map_err(|_| MizeError::new(11))?;
let new_id: u64 = json.get("next_free_id").ok_or(MizeError::new(11))?.as_u64().ok_or(MizeError::new(11))?;
for field in item {
let mut key = format!("{}:", id_u64).into_bytes();
key.extend(field[0].clone());
keys.push(field[0].clone());
let num_of_items: u64 = json.get("num_of_items").ok_or(MizeError::new(11))?.as_u64().ok_or(MizeError::new(11))?;
let val = field[1].clone();
tr.set(key, val).await?;
}
tr.set(format!("{}", id_u64), encode(keys)).await?;
let new_next_id = new_id +1;
let new_num = num_of_items + 1;
//add mize-id field to item
let delta: Delta = serde_json::from_str(&format!("[[[\"mize-id\"], \"{}\"]]", new_id))?;
item.apply_delta(delta)?;
tr.set(new_id.to_be_bytes(), item.json.to_string()).await?;
tr.commit().await?;
return Ok(new_id)
//handle update to item0
let delta_item0: Delta = serde_json::from_str(&format!("[[[\"num_of_items\"], {}], [[\"next_free_id\"], {}]]", new_num, new_next_id))?;
proto::handle_update(proto::MizeId::Local(0), delta_item0, mutexes.clone(), None).await?;
return Ok(new_id);
}
pub async fn update(&self, update: proto::Update) -> Result<(), MizeError>{
println!("itemstore.update func");
pub async fn update(&self, id: u64, delta: Delta) -> Result<(), MizeError>{
let mut tr = self.db.transaction(true, true).await?;
//read keys
let mut old_keys = match tr.get(format!("{}", update.id).into_bytes()).await? {
Some(keys) => decode(keys),
None => {
return Err(MizeError::new(104)
.extra_msg("Internal Datastorage Error: the Index of the Item was not found"));
},
};
let item_bytes: Vec<u8> = tr.get(id.to_le_bytes()).await?
.ok_or(MizeError::new(11)
.extra_msg("The Item an update should be applied to does not exist."))?;
//write new values
for (mut key, delta) in update.raw {
let mut item = Item::from_bytes(item_bytes)?;
let mut store_key = (update.id.clone() + ":").into_bytes();
store_key.extend(key.clone());
item.apply_delta(delta)?;
let mut new_val = Vec::new();
if let Some(old_val) = tr.get(store_key.clone()).await? {
new_val = proto::apply_delta(old_val, delta)?;
tr.set(store_key.clone(), new_val.clone()).await?;
} else {
old_keys.push(key.clone());
new_val = proto::apply_delta(Vec::new(), delta)?;
tr.set(store_key.clone(), new_val.clone()).await?;
}
//remove field if new_val is empty
if (new_val.len() == 0) {
if let Some(key_index) = old_keys.iter().position(|x| *x == key.clone()){
old_keys.remove(key_index);
}
let mut store_key = update.id.clone().into_bytes();
store_key.push(':' as u8);
store_key.extend(key);
tr.del(store_key).await?;
} else {
tr.set(store_key.clone(), new_val).await?;
}
}
//write keys again
tr.set(update.id.into_bytes(), encode(old_keys)).await?;
tr.set(id.to_be_bytes(), serde_json::to_string(&item)?).await?;
tr.commit().await?;
return Ok(());
@@ -139,107 +145,29 @@ impl Itemstore {
pub async fn delete(&self, id_str: String) -> Result<(), error::MizeError>{
let id_u64: u64 = match id_str.parse() {
Ok(id) => id,
Err(err) => {
return Err(MizeError::new(110)
.extra_msg("std::num::ParseIntError while parsing id \"{}\" into an Integer"));
}
};
pub async fn delete(&self, id: u64) -> Result<(), error::MizeError>{
let mut tr = self.db.transaction(true, true).await?;
let keys_res = tr.get(format!("{}", id_u64).into_bytes()).await?;
if let Some(keys) = keys_res {
for key in decode(keys) {
tr.del(key).await?;
}
} else {
return Err(MizeError::new(104)
.extra_msg("Internal Datastorage Error: the Index of the Item was not found, \
This means most likely that this item does not exist."));
}
tr.del(id_str.into_bytes()).await?;
tr.del(id.to_be_bytes()).await?;
tr.commit().await?;
return Ok(());
}
pub async fn get(&self, id: u64) -> Result<Item, MizeError> {
let mut tr = self.db.transaction(false, false).await?;
let mut item: Item = Vec::new();
let keys_res = tr.get(format!("{}", id).into_bytes()).await?;
if let Some(keys) = keys_res {
for key in decode(keys) {
let mut field: [Vec<u8>; 2] = [Vec::new(), Vec::new()];
field[0] = key.clone();
let mut ke = format!("{}:", id).into_bytes();
ke.extend(key.clone());
field[1] = match tr.get(ke).await {
Ok(Some(val)) => val,
Ok(None) => panic!("a field that should be there wasn't"),
Err(e) => panic!("Error while querying the db: {}", e),
};
item.push(field);
};
return Ok(item);
let item_res = tr.get(id.to_le_bytes()).await?;
if let Some(item_vec) = item_res {
let item_str: String = String::from_utf8(item_vec).map_err(|_|MizeError::new(11))?;
let item: JsonValue = serde_json::from_str(&item_str).map_err(|_|MizeError::new(11))?;
return Ok(Item { json: item })
} else {
return Err(MizeError::new(104)
.extra_msg("Internal Datastorage Error: the Index of the Item was not found"));
return Err(MizeError::new(32).format(vec![&format!("{}", id)]));
}
return Ok(item);
return Err(MizeError::new(11));
}
}
pub fn decode(bytes: Vec<u8>) -> Vec<Vec<u8>> {
let mut count = 0;
let mut index: Vec<Vec<u8>> = Vec::new();
let mut key: Vec<u8> = Vec::new();
loop {
if bytes[count] == '$' as u8 {
if key.len() != 0 {
index.push(key.clone());
key.clear();
}
} else if bytes[count] == '!' as u8 {
count += 1;
key.push(bytes[count]);
} else {
key.push(bytes[count]);
}
if count == bytes.len() -1 {
index.push(key.clone());
}
count += 1;
if count >= bytes.len() {break};
}
return index;
}
pub fn encode(index: Vec<Vec<u8>>) -> Vec<u8> {
let mut bytes: Vec<u8> = Vec::new();
for key in index {
let mut count = 0;
loop {
if key[count] == '!' as u8 || key[count] == '$' as u8 {
bytes.insert(count, '!' as u8);
count += 1;
}
count += 1;
if count >= key.len() {break};
}
bytes.push('$' as u8);
bytes.extend(key);
}
return bytes;
}

File diff suppressed because it is too large Load Diff