Compare commits

...

1 Commits

Author SHA1 Message Date
Lucien Greathouse
273974b74f SmallString implementation 2022-05-27 02:54:33 -04:00
21 changed files with 142 additions and 69 deletions

64
Cargo.lock generated
View File

@@ -1492,6 +1492,26 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "profiling"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f61dcf0b917cd75d4521d7343d1ffff3d1583054133c9b5cbea3375c703c40d"
dependencies = [
"profiling-procmacros",
"superluminal-perf",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98eee3c112f2a6f784b6713fe1d7fb7d6506e066121c0a49371fdb976f72bae5"
dependencies = [
"quote 1.0.18",
"syn",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.6.13" version = "0.6.13"
@@ -1796,7 +1816,15 @@ dependencies = [
] ]
[[package]] [[package]]
name = "rojo" name = "rojo-insta-ext"
version = "0.1.0"
dependencies = [
"serde",
"serde_yaml",
]
[[package]]
name = "rojo-smallstring"
version = "7.1.1" version = "7.1.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
@@ -1822,6 +1850,7 @@ dependencies = [
"opener", "opener",
"paste", "paste",
"pretty_assertions", "pretty_assertions",
"profiling",
"rbx_binary", "rbx_binary",
"rbx_dom_weak", "rbx_dom_weak",
"rbx_reflection", "rbx_reflection",
@@ -1834,6 +1863,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_yaml", "serde_yaml",
"smol_str",
"tempfile", "tempfile",
"termcolor", "termcolor",
"thiserror", "thiserror",
@@ -1843,14 +1873,6 @@ dependencies = [
"winreg 0.10.1", "winreg 0.10.1",
] ]
[[package]]
name = "rojo-insta-ext"
version = "0.1.0"
dependencies = [
"serde",
"serde_yaml",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.21" version = "0.1.21"
@@ -2015,6 +2037,15 @@ version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
[[package]]
name = "smol_str"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7475118a28b7e3a2e157ce0131ba8c5526ea96e90ee601d9f6bb2e286a35ab44"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "snax" name = "snax"
version = "0.2.0" version = "0.2.0"
@@ -2046,6 +2077,21 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
[[package]]
name = "superluminal-perf"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80ed8ddf5d2a4a849fa7dc75b3e0be740adb882fe7fee87e79584402ac9b1e60"
dependencies = [
"superluminal-perf-sys",
]
[[package]]
name = "superluminal-perf-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0342a02bcc62538822a46f54294130677f026666c2e19d078fc213b7bc07ff16"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.95" version = "1.0.95"

View File

@@ -1,5 +1,5 @@
[package] [package]
name = "rojo" name = "rojo-smallstring"
version = "7.1.1" version = "7.1.1"
authors = ["Lucien Greathouse <me@lpghatguy.com>"] authors = ["Lucien Greathouse <me@lpghatguy.com>"]
description = "Enables professional-grade development tools for Roblox developers" description = "Enables professional-grade development tools for Roblox developers"
@@ -80,6 +80,8 @@ thiserror = "1.0.30"
tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] }
uuid = { version = "1.0.0", features = ["v4", "serde"] } uuid = { version = "1.0.0", features = ["v4", "serde"] }
clap = { version = "3.1.18", features = ["derive"] } clap = { version = "3.1.18", features = ["derive"] }
smol_str = "0.1.23"
profiling = { version = "1.0.6", features = ["profile-with-superluminal"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winreg = "0.10.1" winreg = "0.10.1"

View File

@@ -46,6 +46,7 @@ pub struct ChangeProcessor {
impl ChangeProcessor { impl ChangeProcessor {
/// Spin up the ChangeProcessor, connecting it to the given tree, VFS, and /// Spin up the ChangeProcessor, connecting it to the given tree, VFS, and
/// outbound message queue. /// outbound message queue.
#[profiling::function]
pub fn start( pub fn start(
tree: Arc<Mutex<RojoTree>>, tree: Arc<Mutex<RojoTree>>,
vfs: Arc<Vfs>, vfs: Arc<Vfs>,

View File

@@ -97,6 +97,7 @@ fn xml_encode_config() -> rbx_xml::EncodeOptions {
rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown)
} }
#[profiling::function]
fn write_model( fn write_model(
session: &ServeSession, session: &ServeSession,
output: &Path, output: &Path,

View File

@@ -18,6 +18,7 @@ mod project;
mod resolution; mod resolution;
mod serve_session; mod serve_session;
mod session_id; mod session_id;
mod small_string;
mod snapshot; mod snapshot;
mod snapshot_middleware; mod snapshot_middleware;
mod web; mod web;

View File

@@ -6,6 +6,8 @@ use clap::Parser;
use librojo::cli::Options; use librojo::cli::Options;
fn main() { fn main() {
profiling::register_thread!("Main Thread");
panic::set_hook(Box::new(|panic_info| { panic::set_hook(Box::new(|panic_info| {
// PanicInfo's payload is usually a &'static str or String. // PanicInfo's payload is usually a &'static str or String.
// See: https://doc.rust-lang.org/beta/std/panic/struct.PanicInfo.html#method.payload // See: https://doc.rust-lang.org/beta/std/panic/struct.PanicInfo.html#method.payload

View File

@@ -96,6 +96,7 @@ impl ServeSession {
/// The project file is expected to be loaded out-of-band since it's /// The project file is expected to be loaded out-of-band since it's
/// currently loaded from the filesystem directly instead of through the /// currently loaded from the filesystem directly instead of through the
/// in-memory filesystem layer. /// in-memory filesystem layer.
#[profiling::function]
pub fn new<P: AsRef<Path>>(vfs: Vfs, start_path: P) -> Result<Self, ServeSessionError> { pub fn new<P: AsRef<Path>>(vfs: Vfs, start_path: P) -> Result<Self, ServeSessionError> {
let start_path = start_path.as_ref(); let start_path = start_path.as_ref();
let start_time = Instant::now(); let start_time = Instant::now();

1
src/small_string.rs Normal file
View File

@@ -0,0 +1 @@
pub use smol_str::SmolStr as SmallString;

View File

@@ -1,6 +1,6 @@
//! Defines the structure of an instance snapshot. //! Defines the structure of an instance snapshot.
use std::{borrow::Cow, collections::HashMap}; use std::collections::HashMap;
use rbx_dom_weak::{ use rbx_dom_weak::{
types::{Ref, Variant}, types::{Ref, Variant},
@@ -8,6 +8,8 @@ use rbx_dom_weak::{
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::small_string::SmallString;
use super::InstanceMetadata; use super::InstanceMetadata;
/// A lightweight description of what an instance should look like. /// A lightweight description of what an instance should look like.
@@ -25,13 +27,13 @@ pub struct InstanceSnapshot {
pub metadata: InstanceMetadata, pub metadata: InstanceMetadata,
/// Correpsonds to the Name property of the instance. /// Correpsonds to the Name property of the instance.
pub name: Cow<'static, str>, pub name: SmallString,
/// Corresponds to the ClassName property of the instance. /// Corresponds to the ClassName property of the instance.
pub class_name: Cow<'static, str>, pub class_name: SmallString,
/// All other properties of the instance, weakly-typed. /// All other properties of the instance, weakly-typed.
pub properties: HashMap<String, Variant>, pub properties: HashMap<SmallString, Variant>,
/// The children of the instance represented as more snapshots. /// The children of the instance represented as more snapshots.
/// ///
@@ -44,37 +46,37 @@ impl InstanceSnapshot {
Self { Self {
snapshot_id: None, snapshot_id: None,
metadata: InstanceMetadata::default(), metadata: InstanceMetadata::default(),
name: Cow::Borrowed("DEFAULT"), name: "DEFAULT".into(),
class_name: Cow::Borrowed("DEFAULT"), class_name: "DEFAULT".into(),
properties: HashMap::new(), properties: HashMap::new(),
children: Vec::new(), children: Vec::new(),
} }
} }
pub fn name(self, name: impl Into<String>) -> Self { pub fn name(self, name: impl Into<SmallString>) -> Self {
Self { Self {
name: Cow::Owned(name.into()), name: name.into(),
..self ..self
} }
} }
pub fn class_name(self, class_name: impl Into<String>) -> Self { pub fn class_name(self, class_name: impl Into<SmallString>) -> Self {
Self { Self {
class_name: Cow::Owned(class_name.into()), class_name: class_name.into(),
..self ..self
} }
} }
pub fn property<K, V>(mut self, key: K, value: V) -> Self pub fn property<K, V>(mut self, key: K, value: V) -> Self
where where
K: Into<String>, K: Into<SmallString>,
V: Into<Variant>, V: Into<Variant>,
{ {
self.properties.insert(key.into(), value.into()); self.properties.insert(key.into(), value.into());
self self
} }
pub fn properties(self, properties: impl Into<HashMap<String, Variant>>) -> Self { pub fn properties(self, properties: impl Into<HashMap<SmallString, Variant>>) -> Self {
Self { Self {
properties: properties.into(), properties: properties.into(),
..self ..self
@@ -112,12 +114,18 @@ impl InstanceSnapshot {
.map(|id| Self::from_tree(tree, id)) .map(|id| Self::from_tree(tree, id))
.collect(); .collect();
let properties = instance
.properties
.iter()
.map(|(key, value)| (key.into(), value.clone()))
.collect();
Self { Self {
snapshot_id: Some(id), snapshot_id: Some(id),
metadata: InstanceMetadata::default(), metadata: InstanceMetadata::default(),
name: Cow::Owned(instance.name.clone()), name: SmallString::from(&instance.name),
class_name: Cow::Owned(instance.class.clone()), class_name: SmallString::from(&instance.class),
properties: instance.properties.clone(), properties,
children, children,
} }
} }

View File

@@ -5,6 +5,8 @@ use std::collections::HashMap;
use rbx_dom_weak::types::{Ref, Variant}; use rbx_dom_weak::types::{Ref, Variant};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::small_string::SmallString;
use super::{InstanceMetadata, InstanceSnapshot}; use super::{InstanceMetadata, InstanceSnapshot};
/// A set of different kinds of patches that can be applied to an WeakDom. /// A set of different kinds of patches that can be applied to an WeakDom.
@@ -40,12 +42,12 @@ pub struct PatchAdd {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PatchUpdate { pub struct PatchUpdate {
pub id: Ref, pub id: Ref,
pub changed_name: Option<String>, pub changed_name: Option<SmallString>,
pub changed_class_name: Option<String>, pub changed_class_name: Option<SmallString>,
/// Contains all changed properties. If a property is assigned to `None`, /// Contains all changed properties. If a property is assigned to `None`,
/// then that property has been removed. /// then that property has been removed.
pub changed_properties: HashMap<String, Option<Variant>>, pub changed_properties: HashMap<SmallString, Option<Variant>>,
/// Changed Rojo-specific metadata, if any of it changed. /// Changed Rojo-specific metadata, if any of it changed.
pub changed_metadata: Option<InstanceMetadata>, pub changed_metadata: Option<InstanceMetadata>,
@@ -83,9 +85,9 @@ pub struct AppliedPatchUpdate {
pub id: Ref, pub id: Ref,
// TODO: Store previous values in order to detect application conflicts // TODO: Store previous values in order to detect application conflicts
pub changed_name: Option<String>, pub changed_name: Option<SmallString>,
pub changed_class_name: Option<String>, pub changed_class_name: Option<SmallString>,
pub changed_properties: HashMap<String, Option<Variant>>, pub changed_properties: HashMap<SmallString, Option<Variant>>,
pub changed_metadata: Option<InstanceMetadata>, pub changed_metadata: Option<InstanceMetadata>,
} }

View File

@@ -4,6 +4,8 @@ use std::collections::HashMap;
use rbx_dom_weak::types::{Ref, Variant}; use rbx_dom_weak::types::{Ref, Variant};
use crate::small_string::SmallString;
use super::{ use super::{
patch::{AppliedPatchSet, AppliedPatchUpdate, PatchSet, PatchUpdate}, patch::{AppliedPatchSet, AppliedPatchUpdate, PatchSet, PatchUpdate},
InstanceSnapshot, RojoTree, InstanceSnapshot, RojoTree,
@@ -12,6 +14,7 @@ use super::{
/// Consumes the input `PatchSet`, applying all of its prescribed changes to the /// Consumes the input `PatchSet`, applying all of its prescribed changes to the
/// tree and returns an `AppliedPatchSet`, which can be used to keep another /// tree and returns an `AppliedPatchSet`, which can be used to keep another
/// tree in sync with Rojo's. /// tree in sync with Rojo's.
#[profiling::function]
pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatchSet { pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatchSet {
let mut context = PatchApplyContext::default(); let mut context = PatchApplyContext::default();
@@ -68,7 +71,7 @@ struct PatchApplyContext {
/// ///
/// This doesn't affect updated instances, since they're always applied /// This doesn't affect updated instances, since they're always applied
/// after we've added all the instances from the patch. /// after we've added all the instances from the patch.
added_instance_properties: HashMap<Ref, HashMap<String, Variant>>, added_instance_properties: HashMap<Ref, HashMap<SmallString, Variant>>,
/// The current applied patch result, describing changes made to the tree. /// The current applied patch result, describing changes made to the tree.
applied_patch_set: AppliedPatchSet, applied_patch_set: AppliedPatchSet,
@@ -100,7 +103,9 @@ fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) -
} }
} }
instance.properties_mut().insert(key, property_value); instance
.properties_mut()
.insert(key.to_string(), property_value);
} }
} }
@@ -164,13 +169,13 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc
}; };
if let Some(name) = patch.changed_name { if let Some(name) = patch.changed_name {
*instance.name_mut() = name.clone(); *instance.name_mut() = name.to_string();
applied_patch.changed_name = Some(name); applied_patch.changed_name = Some(name.into());
} }
if let Some(class_name) = patch.changed_class_name { if let Some(class_name) = patch.changed_class_name {
*instance.class_name_mut() = class_name.clone(); *instance.class_name_mut() = class_name.to_string();
applied_patch.changed_class_name = Some(class_name); applied_patch.changed_class_name = Some(class_name.into());
} }
for (key, property_entry) in patch.changed_properties { for (key, property_entry) in patch.changed_properties {
@@ -195,13 +200,15 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc
instance instance
.properties_mut() .properties_mut()
.insert(key.clone(), Variant::Ref(new_referent)); .insert(key.to_string(), Variant::Ref(new_referent));
} }
Some(ref value) => { Some(ref value) => {
instance.properties_mut().insert(key.clone(), value.clone()); instance
.properties_mut()
.insert(key.to_string(), value.clone());
} }
None => { None => {
instance.properties_mut().remove(&key); instance.properties_mut().remove(key.as_str());
} }
} }

View File

@@ -10,6 +10,7 @@ use super::{
InstanceSnapshot, InstanceWithMeta, RojoTree, InstanceSnapshot, InstanceWithMeta, RojoTree,
}; };
#[profiling::function]
pub fn compute_patch_set( pub fn compute_patch_set(
snapshot: Option<&InstanceSnapshot>, snapshot: Option<&InstanceSnapshot>,
tree: &RojoTree, tree: &RojoTree,
@@ -102,13 +103,13 @@ fn compute_property_patches(
let changed_name = if snapshot.name == instance.name() { let changed_name = if snapshot.name == instance.name() {
None None
} else { } else {
Some(snapshot.name.clone().into_owned()) Some(snapshot.name.clone())
}; };
let changed_class_name = if snapshot.class_name == instance.class_name() { let changed_class_name = if snapshot.class_name == instance.class_name() {
None None
} else { } else {
Some(snapshot.class_name.clone().into_owned()) Some(snapshot.class_name.clone())
}; };
let changed_metadata = if &snapshot.metadata == instance.metadata() { let changed_metadata = if &snapshot.metadata == instance.metadata() {
@@ -120,7 +121,7 @@ fn compute_property_patches(
for (name, snapshot_value) in &snapshot.properties { for (name, snapshot_value) in &snapshot.properties {
visited_properties.insert(name.as_str()); visited_properties.insert(name.as_str());
match instance.properties().get(name) { match instance.properties().get(name.as_str()) {
Some(instance_value) => { Some(instance_value) => {
if snapshot_value != instance_value { if snapshot_value != instance_value {
changed_properties.insert(name.clone(), Some(snapshot_value.clone())); changed_properties.insert(name.clone(), Some(snapshot_value.clone()));
@@ -137,7 +138,7 @@ fn compute_property_patches(
continue; continue;
} }
changed_properties.insert(name.clone(), None); changed_properties.insert(name.into(), None);
} }
if changed_properties.is_empty() if changed_properties.is_empty()

View File

@@ -30,7 +30,7 @@ pub fn snapshot_csv(
.name(name) .name(name)
.class_name("LocalizationTable") .class_name("LocalizationTable")
.properties(hashmap! { .properties(hashmap! {
"Contents".to_owned() => table_contents.into(), "Contents".into() => table_contents.into(),
}) })
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()

View File

@@ -25,7 +25,7 @@ pub fn snapshot_json(
let as_lua = json_to_lua(value).to_string(); let as_lua = json_to_lua(value).to_string();
let properties = hashmap! { let properties = hashmap! {
"Source".to_owned() => as_lua.into(), "Source".into() => as_lua.into(),
}; };
let meta_path = path.with_file_name(format!("{}.meta.json", name)); let meta_path = path.with_file_name(format!("{}.meta.json", name));

View File

@@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::HashMap, path::Path, str}; use std::{collections::HashMap, path::Path, str};
use anyhow::Context; use anyhow::Context;
use memofs::Vfs; use memofs::Vfs;
@@ -85,14 +85,14 @@ impl JsonModelCore {
let mut properties = HashMap::with_capacity(self.properties.len()); let mut properties = HashMap::with_capacity(self.properties.len());
for (key, unresolved) in self.properties { for (key, unresolved) in self.properties {
let value = unresolved.resolve(&class_name, &key)?; let value = unresolved.resolve(&class_name, &key)?;
properties.insert(key, value); properties.insert(key.into(), value);
} }
Ok(InstanceSnapshot { Ok(InstanceSnapshot {
snapshot_id: None, snapshot_id: None,
metadata: Default::default(), metadata: Default::default(),
name: Cow::Owned(name), name: name.into(),
class_name: Cow::Owned(class_name), class_name: class_name.into(),
properties, properties,
children, children,
}) })

View File

@@ -38,7 +38,7 @@ pub fn snapshot_lua(
.name(instance_name) .name(instance_name)
.class_name(class_name) .class_name(class_name)
.properties(hashmap! { .properties(hashmap! {
"Source".to_owned() => contents_str.into(), "Source".into() => contents_str.into(),
}) })
.metadata( .metadata(
InstanceMetadata::new() InstanceMetadata::new()

View File

@@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::HashMap, path::PathBuf}; use std::{collections::HashMap, path::PathBuf};
use anyhow::{format_err, Context}; use anyhow::{format_err, Context};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -49,7 +49,7 @@ impl AdjacentMetadata {
.resolve(&snapshot.class_name, &key) .resolve(&snapshot.class_name, &key)
.with_context(|| format!("error applying meta file {}", path.display()))?; .with_context(|| format!("error applying meta file {}", path.display()))?;
snapshot.properties.insert(key, value); snapshot.properties.insert(key.into(), value);
} }
Ok(()) Ok(())
@@ -116,7 +116,7 @@ impl DirectoryMetadata {
)); ));
} }
snapshot.class_name = Cow::Owned(class_name); snapshot.class_name = class_name.into();
} }
Ok(()) Ok(())
@@ -136,7 +136,7 @@ impl DirectoryMetadata {
.resolve(&snapshot.class_name, &key) .resolve(&snapshot.class_name, &key)
.with_context(|| format!("error applying meta file {}", path.display()))?; .with_context(|| format!("error applying meta file {}", path.display()))?;
snapshot.properties.insert(key, value); snapshot.properties.insert(key.into(), value);
} }
Ok(()) Ok(())

View File

@@ -40,6 +40,7 @@ pub use self::project::snapshot_project_node;
/// The main entrypoint to the snapshot function. This function can be pointed /// The main entrypoint to the snapshot function. This function can be pointed
/// at any path and will return something if Rojo knows how to deal with it. /// at any path and will return something if Rojo knows how to deal with it.
#[profiling::function]
pub fn snapshot_from_vfs( pub fn snapshot_from_vfs(
context: &InstanceContext, context: &InstanceContext,
vfs: &Vfs, vfs: &Vfs,

View File

@@ -6,6 +6,7 @@ use rbx_reflection::ClassTag;
use crate::{ use crate::{
project::{PathNode, Project, ProjectNode}, project::{PathNode, Project, ProjectNode},
small_string::SmallString,
snapshot::{ snapshot::{
InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, PathIgnoreRule, InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, PathIgnoreRule,
}, },
@@ -67,13 +68,10 @@ pub fn snapshot_project_node(
) -> anyhow::Result<Option<InstanceSnapshot>> { ) -> anyhow::Result<Option<InstanceSnapshot>> {
let project_folder = project_path.parent().unwrap(); let project_folder = project_path.parent().unwrap();
let class_name_from_project = node let class_name_from_project = node.class_name.as_ref().map(|name| SmallString::from(name));
.class_name
.as_ref()
.map(|name| Cow::Owned(name.clone()));
let mut class_name_from_path = None; let mut class_name_from_path = None;
let name = Cow::Owned(instance_name.to_owned()); let name = SmallString::from(instance_name);
let mut properties = HashMap::new(); let mut properties = HashMap::new();
let mut children = Vec::new(); let mut children = Vec::new();
let mut metadata = InstanceMetadata::default(); let mut metadata = InstanceMetadata::default();
@@ -228,7 +226,7 @@ pub fn snapshot_project_node(
_ => {} _ => {}
} }
properties.insert(key.clone(), value); properties.insert(key.into(), value);
} }
// If the user specified $ignoreUnknownInstances, overwrite the existing // If the user specified $ignoreUnknownInstances, overwrite the existing
@@ -262,7 +260,7 @@ pub fn snapshot_project_node(
})) }))
} }
fn infer_class_name(name: &str, parent_class: Option<&str>) -> Option<Cow<'static, str>> { fn infer_class_name(name: &str, parent_class: Option<&str>) -> Option<SmallString> {
// If className wasn't defined from another source, we may be able // If className wasn't defined from another source, we may be able
// to infer one. // to infer one.
@@ -275,13 +273,13 @@ fn infer_class_name(name: &str, parent_class: Option<&str>) -> Option<Cow<'stati
let descriptor = rbx_reflection_database::get().classes.get(name)?; let descriptor = rbx_reflection_database::get().classes.get(name)?;
if descriptor.tags.contains(&ClassTag::Service) { if descriptor.tags.contains(&ClassTag::Service) {
return Some(Cow::Owned(name.to_owned())); return Some(name.into());
} }
} else if parent_class == "StarterPlayer" { } else if parent_class == "StarterPlayer" {
// StarterPlayer has two special members with their own classes. // StarterPlayer has two special members with their own classes.
if name == "StarterPlayerScripts" || name == "StarterCharacterScripts" { if name == "StarterPlayerScripts" || name == "StarterCharacterScripts" {
return Some(Cow::Owned(name.to_owned())); return Some(name.into());
} }
} }

View File

@@ -21,7 +21,7 @@ pub fn snapshot_txt(
.to_owned(); .to_owned();
let properties = hashmap! { let properties = hashmap! {
"Value".to_owned() => contents_str.into(), "Value".into() => contents_str.into(),
}; };
let meta_path = path.with_file_name(format!("{}.meta.json", name)); let meta_path = path.with_file_name(format!("{}.meta.json", name));

View File

@@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
session_id::SessionId, session_id::SessionId,
small_string::SmallString,
snapshot::{ snapshot::{
AppliedPatchSet, InstanceMetadata as RojoInstanceMetadata, InstanceWithMeta, RojoTree, AppliedPatchSet, InstanceMetadata as RojoInstanceMetadata, InstanceWithMeta, RojoTree,
}, },
@@ -83,13 +84,13 @@ impl<'a> SubscribeMessage<'a> {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct InstanceUpdate { pub struct InstanceUpdate {
pub id: Ref, pub id: Ref,
pub changed_name: Option<String>, pub changed_name: Option<SmallString>,
pub changed_class_name: Option<String>, pub changed_class_name: Option<SmallString>,
// TODO: Transform from HashMap<String, Option<_>> to something else, since // TODO: Transform from HashMap<_, Option<_>> to something else, since
// null will get lost when decoding from JSON in some languages. // null will get lost when decoding from JSON in some languages.
#[serde(default)] #[serde(default)]
pub changed_properties: HashMap<String, Option<Variant>>, pub changed_properties: HashMap<SmallString, Option<Variant>>,
pub changed_metadata: Option<InstanceMetadata>, pub changed_metadata: Option<InstanceMetadata>,
} }