use serde::{Deserialize, Serialize};
use crate::core::Graph;
use crate::ops::apply::ApplyError;
use crate::ops::transaction::GraphOp;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GraphTransaction {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub ops: Vec<GraphOp>,
}
impl GraphTransaction {
pub fn new() -> Self {
Self::default()
}
pub fn from_ops(ops: impl IntoIterator<Item = GraphOp>) -> Self {
Self::new().with_ops(ops)
}
pub fn from_parts(label: Option<String>, ops: impl IntoIterator<Item = GraphOp>) -> Self {
Self {
label,
ops: ops.into_iter().collect(),
}
}
pub fn diff(from: &Graph, to: &Graph) -> Self {
crate::ops::diff::graph_diff(from, to)
}
pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn with_optional_label(mut self, label: Option<String>) -> Self {
self.label = label;
self
}
pub fn with_ops(mut self, ops: impl IntoIterator<Item = GraphOp>) -> Self {
self.extend(ops);
self
}
pub fn map_ops(mut self, f: impl FnOnce(Vec<GraphOp>) -> Vec<GraphOp>) -> Self {
self.ops = f(self.ops);
self
}
pub fn push(&mut self, op: GraphOp) {
self.ops.push(op);
}
pub fn extend(&mut self, ops: impl IntoIterator<Item = GraphOp>) {
self.ops.extend(ops);
}
pub fn retain_ops(&mut self, f: impl FnMut(&GraphOp) -> bool) {
self.ops.retain(f);
}
pub fn clear_ops(&mut self) {
self.ops.clear();
}
pub fn is_empty(&self) -> bool {
self.ops.is_empty()
}
pub fn label(&self) -> Option<&str> {
self.label.as_deref()
}
pub fn ops(&self) -> &[GraphOp] {
&self.ops
}
pub fn into_ops(self) -> Vec<GraphOp> {
self.ops
}
pub fn into_parts(self) -> (Option<String>, Vec<GraphOp>) {
let Self { label, ops } = self;
(label, ops)
}
pub fn len(&self) -> usize {
self.ops.len()
}
pub fn apply_to(&self, graph: &mut Graph) -> Result<(), ApplyError> {
crate::ops::apply::apply_transaction(graph, self)
}
pub fn inverse(&self) -> Self {
crate::ops::history::invert_transaction(self)
}
}