diff options
author | Vika <vika@fireburn.ru> | 2021-05-04 21:06:24 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2021-05-04 21:07:39 +0300 |
commit | 12a4906117349fa518e4be5550bd8901941abcf0 (patch) | |
tree | deefc3766df9aaee563cbfdf52108f4bc323c233 | |
parent | 7024cbefb27e1c9649bff57df32b316484de4104 (diff) | |
download | kittybox-12a4906117349fa518e4be5550bd8901941abcf0.tar.zst |
Implemented MemoryStorage::update_post()
-rw-r--r-- | src/database/memory.rs | 83 | ||||
-rw-r--r-- | src/database/mod.rs | 2 |
2 files changed, 84 insertions, 1 deletions
diff --git a/src/database/memory.rs b/src/database/memory.rs index a4cf5a9..d1a69a2 100644 --- a/src/database/memory.rs +++ b/src/database/memory.rs @@ -21,7 +21,88 @@ impl Storage for MemoryStorage { } async fn update_post<'a>(&self, url: &'a str, update: serde_json::Value) -> Result<()> { - todo!() + let mut add_keys: HashMap<String, serde_json::Value> = HashMap::new(); + let mut remove_keys: Vec<String> = vec![]; + let mut remove_values: HashMap<String, Vec<serde_json::Value>> = HashMap::new(); + + if let Some(delete) = update["delete"].as_array() { + remove_keys.extend(delete.iter().filter_map(|v| v.as_str()).map(|v| v.to_string())); + } else if let Some(delete) = update["delete"].as_object() { + for (k, v) in delete { + if let Some(v) = v.as_array() { + remove_values.entry(k.to_string()).or_default().extend(v.clone()); + } else { + return Err(StorageError::new(ErrorKind::BadRequest, "Malformed update object")); + } + } + } + if let Some(add) = update["add"].as_object() { + for (k, v) in add { + if v.is_array() { + add_keys.insert(k.to_string(), v.clone()); + } else { + return Err(StorageError::new(ErrorKind::BadRequest, "Malformed update object")); + } + } + } + if let Some(replace) = update["replace"].as_object() { + for (k, v) in replace { + remove_keys.push(k.to_string()); + add_keys.insert(k.to_string(), v.clone()); + } + } + let mut mapping = self.mapping.write().await; + if let Some(mut post) = mapping.get(url) { + if let Some(url) = post["see_other"].as_str() { + if let Some(new_post) = mapping.get(url) { + post = new_post + } else { + return Err(StorageError::new(ErrorKind::NotFound, "The post you have requested is not found in the database.")); + } + } + let mut post = post.clone(); + for k in remove_keys { + post["properties"].as_object_mut().unwrap().remove(&k); + } + for (k, v) in remove_values { + let k = &k; + let props; + if k == "children" { + props = &mut post; + } else { + props = &mut post["properties"]; + } + v.iter().for_each(|v| { + if let Some(vec) = props[k].as_array_mut() { + if let Some(index) = vec.iter().position(|w| w == v) { + vec.remove(index); + } + } + }); + } + for (k, v) in add_keys { + let props; + if k == "children" { + props = &mut post; + } else { + props = &mut post["properties"]; + } + let k = &k; + if let Some(prop) = props[k].as_array_mut() { + if k == "children" { + v.as_array().unwrap().iter().cloned().rev().for_each(|v| prop.insert(0, v)); + } else { + prop.extend(v.as_array().unwrap().iter().cloned()); + } + } else { + post["properties"][k] = v + } + } + mapping.insert(post["properties"]["uid"][0].as_str().unwrap().to_string(), post); + } else { + return Err(StorageError::new(ErrorKind::NotFound, "The designated post wasn't found in the database.")); + } + Ok(()) } async fn delete_post<'a>(&self, url: &'a str) -> Result<()> { diff --git a/src/database/mod.rs b/src/database/mod.rs index 6abe72c..82bbea5 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -24,6 +24,7 @@ pub enum ErrorKind { PermissionDenied, JSONParsing, NotFound, + BadRequest, Other } @@ -56,6 +57,7 @@ impl std::fmt::Display for StorageError { ErrorKind::JSONParsing => write!(f, "error while parsing JSON: "), ErrorKind::PermissionDenied => write!(f, "permission denied: "), ErrorKind::NotFound => write!(f, "not found: "), + ErrorKind::BadRequest => write!(f, "bad request: "), ErrorKind::Other => write!(f, "generic storage layer error: ") } { Ok(_) => write!(f, "{}", self.msg), |