basic JSON message handling. not tested yet at all
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
1154
src/server/proto.rs
1154
src/server/proto.rs
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user