From 8a9a72fd50e87f5fbb63e66bbccee782a4abcc31 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 15:42:44 -0700 Subject: [PATCH] Refactor .meta.json into AdjacentMetadata type more strongly --- src/snapshot_middleware/lua.rs | 25 ++++++------- src/snapshot_middleware/meta_file.rs | 55 +++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index b59898ea..c13648e9 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -94,31 +94,28 @@ fn snapshot_lua_file( .path() .with_file_name(format!("{}.meta.json", instance_name)); - let mut metadata = InstanceMetadata { + let metadata = InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }; - if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(imfs)?; - let parsed: AdjacentMetadata = serde_json::from_slice(meta_contents) - // TODO: Turn into error type - .expect(".meta.json file was malformed"); - - if let Some(ignore) = parsed.ignore_unknown_instances { - metadata.ignore_unknown_instances = ignore; - } - } - - Ok(Some(InstanceSnapshot { + let mut snapshot = InstanceSnapshot { snapshot_id: None, metadata, name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed(class_name), properties, children: Vec::new(), - })) + }; + + if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(imfs)?; + let mut metadata = AdjacentMetadata::from_slice(meta_contents); + metadata.apply_all(&mut snapshot); + } + + Ok(Some(snapshot)) } /// Attempts to snapshot an 'init' Lua script contained inside of a folder with diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index f20a5e41..f8d8e960 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,15 +1,60 @@ +use std::{borrow::Cow, collections::HashMap}; + +use rbx_dom_weak::UnresolvedRbxValue; +use rbx_reflection::try_resolve_value; use serde::{Deserialize, Serialize}; +use crate::snapshot::InstanceSnapshot; + #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AdjacentMetadata { #[serde(skip_serializing_if = "Option::is_none")] - pub ignore_unknown_instances: Option, -} + pub class_name: Option, -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct InitMetadata { #[serde(skip_serializing_if = "Option::is_none")] pub ignore_unknown_instances: Option, + + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub properties: HashMap, +} + +impl AdjacentMetadata { + pub fn from_slice(slice: &[u8]) -> Self { + serde_json::from_slice(slice) + // TODO: Turn into error type + .expect(".meta.json file was malformed") + } + + pub fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) { + if let Some(ignore) = self.ignore_unknown_instances.take() { + snapshot.metadata.ignore_unknown_instances = ignore; + } + } + + pub fn apply_class_name(&mut self, snapshot: &mut InstanceSnapshot) { + if let Some(class_name) = self.class_name.take() { + snapshot.class_name = Cow::Owned(class_name); + } + } + + pub fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) { + let class_name = &snapshot.class_name; + + let source_properties = self.properties.drain().map(|(key, value)| { + try_resolve_value(class_name, &key, &value) + .map(|resolved| (key, resolved)) + .expect("TODO: Handle rbx_reflection errors") + }); + + for (key, value) in source_properties { + snapshot.properties.insert(key, value); + } + } + + pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { + self.apply_ignore_unknown_instances(snapshot); + self.apply_class_name(snapshot); + self.apply_properties(snapshot); + } }