//! Defines the structure of an instance snapshot. use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{ types::{Ref, Variant}, WeakDom, }; use serde::{Deserialize, Serialize}; use super::InstanceMetadata; /// A lightweight description of what an instance should look like. /// // Possible future improvements: // - Use refcounted/interned strings // - Replace use of Variant with a sum of Variant + borrowed value #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InstanceSnapshot { // FIXME: Don't use Option anymore! /// A temporary ID applied to the snapshot that's used for Ref properties. pub snapshot_id: Option, /// Rojo-specific metadata associated with the instance. pub metadata: InstanceMetadata, /// Correpsonds to the Name property of the instance. pub name: Cow<'static, str>, /// Corresponds to the ClassName property of the instance. pub class_name: Cow<'static, str>, /// All other properties of the instance, weakly-typed. pub properties: HashMap, /// The children of the instance represented as more snapshots. /// /// Order is relevant for Roblox instances! pub children: Vec, } impl InstanceSnapshot { pub fn new() -> Self { Self { snapshot_id: None, metadata: InstanceMetadata::default(), name: Cow::Borrowed("DEFAULT"), class_name: Cow::Borrowed("DEFAULT"), properties: HashMap::new(), children: Vec::new(), } } pub fn name(self, name: impl Into) -> Self { Self { name: Cow::Owned(name.into()), ..self } } pub fn class_name(self, class_name: impl Into) -> Self { Self { class_name: Cow::Owned(class_name.into()), ..self } } pub fn property(mut self, key: K, value: V) -> Self where K: Into, V: Into, { self.properties.insert(key.into(), value.into()); self } pub fn properties(self, properties: impl Into>) -> Self { Self { properties: properties.into(), ..self } } pub fn children(self, children: impl Into>) -> Self { Self { children: children.into(), ..self } } pub fn snapshot_id(self, snapshot_id: Option) -> Self { Self { snapshot_id, ..self } } pub fn metadata(self, metadata: impl Into) -> Self { Self { metadata: metadata.into(), ..self } } pub fn from_tree(tree: &WeakDom, id: Ref) -> Self { let instance = tree.get_by_ref(id).expect("instance did not exist in tree"); let children = instance .children() .iter() .copied() .map(|id| Self::from_tree(tree, id)) .collect(); Self { snapshot_id: Some(id), metadata: InstanceMetadata::default(), name: Cow::Owned(instance.name.clone()), class_name: Cow::Owned(instance.class.clone()), properties: instance.properties.clone(), children, } } } impl Default for InstanceSnapshot { fn default() -> Self { Self::new() } }