|
1 | 1 | use super::DocumentNode; |
2 | 2 | use crate::application_io::PlatformEditorApi; |
3 | 3 | use crate::proto::{Any as DAny, FutureAny}; |
4 | | -use brush_nodes::brush_cache::BrushCache; |
5 | 4 | use brush_nodes::brush_stroke::BrushStroke; |
6 | 5 | use core_types::table::Table; |
7 | 6 | use core_types::transform::Footprint; |
@@ -39,7 +38,7 @@ macro_rules! tagged_value { |
39 | 38 | $( $(#[$meta] ) *$identifier( $ty ), )* |
40 | 39 | RenderOutput(RenderOutput), |
41 | 40 | #[serde(skip)] |
42 | | - EditorApi(Arc<PlatformEditorApi>) |
| 41 | + EditorApi(Arc<PlatformEditorApi>), |
43 | 42 | } |
44 | 43 |
|
45 | 44 | impl CacheHash for TaggedValue { |
@@ -79,7 +78,7 @@ macro_rules! tagged_value { |
79 | 78 | Self::None => concrete!(()), |
80 | 79 | $( Self::$identifier(_) => concrete!($ty), )* |
81 | 80 | Self::RenderOutput(_) => concrete!(RenderOutput), |
82 | | - Self::EditorApi(_) => concrete!(&PlatformEditorApi) |
| 81 | + Self::EditorApi(_) => concrete!(&PlatformEditorApi), |
83 | 82 | } |
84 | 83 | } |
85 | 84 | /// Attempts to downcast the dynamic type to a tagged value |
@@ -211,7 +210,6 @@ tagged_value! { |
211 | 210 | Stroke(Stroke), |
212 | 211 | Gradient(Gradient), |
213 | 212 | Font(Font), |
214 | | - BrushCache(BrushCache), |
215 | 213 | DocumentNode(DocumentNode), |
216 | 214 | ContextFeatures(ContextFeatures), |
217 | 215 | Curve(Curve), |
@@ -412,6 +410,35 @@ impl TaggedValue { |
412 | 410 | _ => panic!("Passed value is not of type u32"), |
413 | 411 | } |
414 | 412 | } |
| 413 | + |
| 414 | + /// Walks a JSON document tree and replaces any externally-tagged `TaggedValue` whose discriminant is in `REMOVED_VARIANTS` with the unit variant `"None"`. |
| 415 | + /// Lets documents written before a variant was removed continue to deserialize. The document migration step then removes any orphan node inputs that result. |
| 416 | + #[cfg(feature = "loading")] |
| 417 | + pub fn scrub_removed_variants_from_json(value: &mut serde_json::Value) { |
| 418 | + // Names of `TaggedValue` variants that have been removed since being released. Any object of the form `{"<name>": <payload>}` is rewritten to `"None"` on load. |
| 419 | + const REMOVED_VARIANTS: &[&str] = &["BrushCache"]; |
| 420 | + |
| 421 | + match value { |
| 422 | + serde_json::Value::Object(map) => { |
| 423 | + if map.len() == 1 |
| 424 | + && let Some(key) = map.keys().next() |
| 425 | + && REMOVED_VARIANTS.contains(&key.as_str()) |
| 426 | + { |
| 427 | + *value = serde_json::Value::String("None".to_string()); |
| 428 | + return; |
| 429 | + } |
| 430 | + for child in map.values_mut() { |
| 431 | + Self::scrub_removed_variants_from_json(child); |
| 432 | + } |
| 433 | + } |
| 434 | + serde_json::Value::Array(array) => { |
| 435 | + for child in array { |
| 436 | + Self::scrub_removed_variants_from_json(child); |
| 437 | + } |
| 438 | + } |
| 439 | + _ => {} |
| 440 | + } |
| 441 | + } |
415 | 442 | } |
416 | 443 |
|
417 | 444 | impl Display for TaggedValue { |
@@ -518,3 +545,35 @@ impl CacheHash for RenderOutput { |
518 | 545 | self.data.cache_hash(state); |
519 | 546 | } |
520 | 547 | } |
| 548 | + |
| 549 | +#[cfg(all(test, feature = "loading"))] |
| 550 | +mod tests { |
| 551 | + use super::*; |
| 552 | + |
| 553 | + #[test] |
| 554 | + fn scrub_replaces_removed_variant_with_none_unit() { |
| 555 | + let mut value = serde_json::json!({ |
| 556 | + "Value": { |
| 557 | + "tagged_value": { "BrushCache": { "unique_id": 1, "prev_input": [] } }, |
| 558 | + "exposed": false |
| 559 | + } |
| 560 | + }); |
| 561 | + TaggedValue::scrub_removed_variants_from_json(&mut value); |
| 562 | + assert_eq!(value, serde_json::json!({ "Value": { "tagged_value": "None", "exposed": false } })); |
| 563 | + } |
| 564 | + |
| 565 | + #[test] |
| 566 | + fn scrub_leaves_live_variants_unchanged() { |
| 567 | + let mut value = serde_json::json!({ "Value": { "tagged_value": { "F64": 1.5 }, "exposed": false } }); |
| 568 | + let original = value.clone(); |
| 569 | + TaggedValue::scrub_removed_variants_from_json(&mut value); |
| 570 | + assert_eq!(value, original); |
| 571 | + } |
| 572 | + |
| 573 | + #[test] |
| 574 | + fn scrub_recurses_through_arrays_and_nested_objects() { |
| 575 | + let mut value = serde_json::json!([{ "BrushCache": { "any": "payload" } }, { "F32": 0.5 }]); |
| 576 | + TaggedValue::scrub_removed_variants_from_json(&mut value); |
| 577 | + assert_eq!(value, serde_json::json!(["None", { "F32": 0.5 }])); |
| 578 | + } |
| 579 | +} |
0 commit comments