use serde_json::{ Map, Value };
use serde::{ Serialize, Serializer };
use crate::{ base::Base, errors::DetaError };
#[derive(Debug, PartialEq)]
pub (crate) enum Operation {
Set,
Delete,
Append,
Prepend,
Increment,
}
impl Operation {
pub fn as_string(&self) -> String {
format!("{:?}", self).to_lowercase()
}
}
pub struct Updater {
key: String,
base: Base,
data: Vec<(String, Value, Operation)>
}
impl Updater {
pub (crate) fn new(base: Base, key: &str) -> Updater {
Updater {
base,
key: key.to_string(),
data: Vec::new()
}
}
pub fn set(mut self, field: &str, value: Value) -> Self {
self.data.push((field.to_string(), value, Operation::Set));
self
}
pub fn delete(mut self, field: &str) -> Self {
self.data.push((field.to_string(), Value::Null, Operation::Delete));
self
}
pub fn append(mut self, field: &str, value: Value) -> Self {
self.data.push((field.to_string(), value, Operation::Append));
self
}
pub fn prepend(mut self, field: &str, value: Value) -> Self {
self.data.push((field.to_string(), value, Operation::Prepend));
self
}
pub fn increment(mut self, field: &str, value: Value) -> Self {
self.data.push((field.to_string(), value, Operation::Increment));
self
}
pub fn commit(&self) -> Result<Value, DetaError> {
self.base.request(
"PATCH", &format!("/items/{}", self.key),
Some(serde_json::to_value(self).unwrap())
)
}
}
impl Serialize for Updater {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
let mut main_map = Map::new();
let mut del_vec = vec![];
for (field, value, operation) in self.data.iter() {
if operation == &Operation::Delete {
del_vec.push(value.clone())
} else {
let tmp = main_map.entry(operation.as_string())
.or_insert(Value::Object(Map::new()));
tmp.as_object_mut().unwrap().insert(field.clone().to_string(), value.clone());
}
}
if !del_vec.is_empty() {
main_map.insert(String::from("delete"), Value::Array(del_vec));
}
Value::Object(main_map).serialize(serializer)
}
}