use super::tree::ResolvedProps;
use crate::ir::NodeId;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use slotmap::Key;
mod resolved_props_serde {
use super::ResolvedProps;
use indexmap::IndexMap;
use std::sync::Arc;
pub fn serialize<S>(value: &ResolvedProps, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serde::Serialize::serialize(&**value, serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<ResolvedProps, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::Deserialize;
IndexMap::deserialize(deserializer).map(Arc::new)
}
}
#[doc(hidden)]
#[inline]
pub fn node_id_str(id: NodeId) -> String {
id.data().as_ffi().to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum Patch {
#[serde(rename_all = "camelCase")]
Create {
id: String,
element_type: String,
#[serde(with = "resolved_props_serde")]
props: ResolvedProps,
},
#[serde(rename_all = "camelCase")]
SetProp {
id: String,
name: String,
value: Value,
},
#[serde(rename_all = "camelCase")]
RemoveProp {
id: String,
name: String,
},
#[serde(rename_all = "camelCase")]
SetText {
id: String,
text: String,
},
#[serde(rename_all = "camelCase")]
Insert {
parent_id: String,
id: String,
before_id: Option<String>,
},
#[serde(rename_all = "camelCase")]
Move {
parent_id: String,
id: String,
before_id: Option<String>,
},
#[serde(rename_all = "camelCase")]
Remove { id: String },
#[serde(rename_all = "camelCase")]
Detach { id: String },
#[serde(rename_all = "camelCase")]
Attach {
parent_id: String,
id: String,
before_id: Option<String>,
},
}
impl Patch {
pub fn create(id: NodeId, element_type: String, props: ResolvedProps) -> Self {
Self::Create {
id: node_id_str(id),
element_type,
props,
}
}
pub fn set_prop(id: NodeId, name: String, value: Value) -> Self {
Self::SetProp {
id: node_id_str(id),
name,
value,
}
}
pub fn remove_prop(id: NodeId, name: String) -> Self {
Self::RemoveProp {
id: node_id_str(id),
name,
}
}
pub fn set_text(id: NodeId, text: String) -> Self {
Self::SetText {
id: node_id_str(id),
text,
}
}
pub fn insert(parent_id: NodeId, id: NodeId, before_id: Option<NodeId>) -> Self {
Self::Insert {
parent_id: node_id_str(parent_id),
id: node_id_str(id),
before_id: before_id.map(node_id_str),
}
}
pub fn insert_root(id: NodeId) -> Self {
Self::Insert {
parent_id: "root".to_string(),
id: node_id_str(id),
before_id: None,
}
}
pub fn move_node(parent_id: NodeId, id: NodeId, before_id: Option<NodeId>) -> Self {
Self::Move {
parent_id: node_id_str(parent_id),
id: node_id_str(id),
before_id: before_id.map(node_id_str),
}
}
pub fn remove(id: NodeId) -> Self {
Self::Remove {
id: node_id_str(id),
}
}
pub fn detach(id: NodeId) -> Self {
Self::Detach {
id: node_id_str(id),
}
}
pub fn attach(parent_id: NodeId, id: NodeId, before_id: Option<NodeId>) -> Self {
Self::Attach {
parent_id: node_id_str(parent_id),
id: node_id_str(id),
before_id: before_id.map(node_id_str),
}
}
pub fn attach_root(id: NodeId, before_id: Option<NodeId>) -> Self {
Self::Attach {
parent_id: "root".to_string(),
id: node_id_str(id),
before_id: before_id.map(node_id_str),
}
}
}