use super::diff::{diff, EscalationReason, TemplateDiff};
use super::registry;
use super::Template;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SwapOutcome {
Applied,
Unchanged,
Escalate(EscalationReason),
UnknownSite,
}
pub fn apply_swap(new: Template) -> SwapOutcome {
match registry::get(&new.key) {
None => SwapOutcome::UnknownSite,
Some(running) => match diff(&running, &new) {
TemplateDiff::Unchanged => SwapOutcome::Unchanged,
TemplateDiff::Swappable => {
registry::register(new);
SwapOutcome::Applied
}
TemplateDiff::Escalate(reason) => SwapOutcome::Escalate(reason),
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::template::{registry, PropValue, StaticValue, Template, TemplateKey, TemplateNode};
fn col(key: &TemplateKey, spacing: PropValue) -> Template {
Template::new(key.clone(), TemplateNode::new("Column").with_prop("spacing", spacing))
}
trait WithProp {
fn with_prop(self, k: &str, v: PropValue) -> Self;
}
impl WithProp for TemplateNode {
fn with_prop(mut self, k: &str, v: PropValue) -> Self {
self.props.push((k.to_string(), v));
self
}
}
#[test]
fn safe_static_edit_is_applied_and_replaces_the_registry_entry() {
let key = TemplateKey::new("src/swap_a.rs", 1, 1);
registry::register(col(&key, PropValue::Static(StaticValue::Float(4.0))));
let edited = col(&key, PropValue::Static(StaticValue::Float(40.0)));
assert_eq!(apply_swap(edited), SwapOutcome::Applied);
let now = registry::get(&key).unwrap();
assert_eq!(now.root.props[0].1, PropValue::Static(StaticValue::Float(40.0)));
}
#[test]
fn adding_a_hole_escalates_and_leaves_the_registry_untouched() {
let key = TemplateKey::new("src/swap_b.rs", 2, 1);
registry::register(col(&key, PropValue::Static(StaticValue::Float(4.0))));
let edited = col(&key, PropValue::Hole(0));
assert_eq!(
apply_swap(edited),
SwapOutcome::Escalate(EscalationReason::HoleCountChanged { old: 0, new: 1 })
);
assert_eq!(
registry::get(&key).unwrap().root.props[0].1,
PropValue::Static(StaticValue::Float(4.0))
);
}
#[test]
fn unknown_site_is_reported() {
let key = TemplateKey::new("src/never_registered_swap.rs", 99, 1);
assert_eq!(apply_swap(col(&key, PropValue::Static(StaticValue::Float(1.0)))), SwapOutcome::UnknownSite);
}
#[test]
fn identical_edit_is_unchanged() {
let key = TemplateKey::new("src/swap_c.rs", 3, 1);
registry::register(col(&key, PropValue::Static(StaticValue::Float(4.0))));
assert_eq!(apply_swap(col(&key, PropValue::Static(StaticValue::Float(4.0)))), SwapOutcome::Unchanged);
}
}