Simplify usage of attributes. (#574)

* Support implicit values for primitive attributes

This commit adds support for strings, numbers, and booleans to be implicitly typed in attribute maps, reducing the redundancy of needing to specify their types.

I also quietly adjusted one of the tests to use a more stable class/property pair. Since SourceAssetId is locked to Roblox, it could potentially disappear at any time.

* Apply formatting.

* Address feedback

* Backwards compatible format usage.

* Axe UnresolvedValueMap in favor of $attributes

Attributes can be defined directly on instances, with support for unambiguous types.

* Adjust test.

* to_string() -> into()

* Made attribute test more concise.

* small cleanup

* Update src/resolution.rs

* Update src/resolution.rs

* Update src/resolution.rs

* Update src/resolution.rs

Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
This commit is contained in:
Max
2022-08-03 19:07:06 -05:00
committed by GitHub
parent 3e83f92532
commit d196c5091c
7 changed files with 184 additions and 6 deletions

View File

@@ -2,6 +2,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path, str};
use anyhow::Context;
use memofs::Vfs;
use rbx_dom_weak::types::Attributes;
use serde::Deserialize;
use crate::{
@@ -78,6 +79,9 @@ struct JsonModel {
skip_serializing_if = "HashMap::is_empty"
)]
properties: HashMap<String, UnresolvedValue>,
#[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")]
attributes: HashMap<String, UnresolvedValue>,
}
impl JsonModel {
@@ -96,6 +100,17 @@ impl JsonModel {
properties.insert(key, value);
}
if !self.attributes.is_empty() {
let mut attributes = Attributes::new();
for (key, unresolved) in self.attributes {
let value = unresolved.resolve_unambiguous()?;
attributes.insert(key, value);
}
properties.insert("Attributes".into(), attributes.into());
}
Ok(InstanceSnapshot {
snapshot_id: None,
metadata: Default::default(),

View File

@@ -1,6 +1,7 @@
use std::{borrow::Cow, collections::HashMap, path::PathBuf};
use anyhow::{format_err, Context};
use rbx_dom_weak::types::Attributes;
use serde::{Deserialize, Serialize};
use crate::{resolution::UnresolvedValue, snapshot::InstanceSnapshot};
@@ -78,6 +79,9 @@ pub struct DirectoryMetadata {
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub properties: HashMap<String, UnresolvedValue>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub attributes: HashMap<String, UnresolvedValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub class_name: Option<String>,
@@ -139,6 +143,19 @@ impl DirectoryMetadata {
snapshot.properties.insert(key, value);
}
if !self.attributes.is_empty() {
let mut attributes = Attributes::new();
for (key, unresolved) in self.attributes.drain() {
let value = unresolved.resolve_unambiguous()?;
attributes.insert(key, value);
}
snapshot
.properties
.insert("Attributes".into(), attributes.into());
}
Ok(())
}
}

View File

@@ -2,6 +2,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path};
use anyhow::{bail, Context};
use memofs::Vfs;
use rbx_dom_weak::types::Attributes;
use rbx_reflection::ClassTag;
use crate::{
@@ -231,6 +232,23 @@ pub fn snapshot_project_node(
properties.insert(key.clone(), value);
}
if !node.attributes.is_empty() {
let mut attributes = Attributes::new();
for (key, unresolved) in &node.attributes {
let value = unresolved.clone().resolve_unambiguous().with_context(|| {
format!(
"Unresolvable attribute in project at path {}",
project_path.display()
)
})?;
attributes.insert(key.clone(), value);
}
properties.insert("Attributes".into(), attributes.into());
}
// If the user specified $ignoreUnknownInstances, overwrite the existing
// value.
//