Skip to content

Commit

Permalink
Add YAML middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
Dekkonot committed May 13, 2024
1 parent 3d4e387 commit b341bb0
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 4 deletions.
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ rbx_reflection = "4.5.0"
rbx_reflection_database = "0.2.10"
rbx_xml = "0.13.3"

serde = { version = "1.0.197", features = ["derive", "rc"] }
serde_json = "1.0.114"
serde_yaml = "0.8.26"
toml = "0.5.11"

anyhow = "1.0.80"
backtrace = "0.3.69"
bincode = "1.3.3"
Expand All @@ -81,9 +86,6 @@ reqwest = { version = "0.11.24", default-features = false, features = [
] }
ritz = "0.1.0"
roblox_install = "1.0.0"
serde = { version = "1.0.197", features = ["derive", "rc"] }
serde_json = "1.0.114"
toml = "0.5.11"
termcolor = "1.4.1"
thiserror = "1.0.57"
tokio = { version = "1.36.0", features = ["rt", "rt-multi-thread"] }
Expand Down Expand Up @@ -111,6 +113,5 @@ criterion = "0.3.6"
insta = { version = "1.36.1", features = ["redactions", "yaml"] }
paste = "1.0.14"
pretty_assertions = "1.4.0"
serde_yaml = "0.8.26"
tempfile = "3.10.1"
walkdir = "2.5.0"
4 changes: 4 additions & 0 deletions src/snapshot_middleware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod rbxmx;
mod toml;
mod txt;
mod util;
mod yaml;

use std::{
path::{Path, PathBuf},
Expand All @@ -41,6 +42,7 @@ use self::{
rbxmx::snapshot_rbxmx,
toml::snapshot_toml,
txt::snapshot_txt,
yaml::snapshot_yaml,
};

pub use self::{project::snapshot_project_node, util::emit_legacy_scripts_default};
Expand Down Expand Up @@ -204,6 +206,7 @@ pub enum Middleware {
Rbxmx,
Toml,
Text,
Yaml,
Ignore,
}

Expand All @@ -229,6 +232,7 @@ impl Middleware {
Self::Rbxmx => snapshot_rbxmx(context, vfs, path, name),
Self::Toml => snapshot_toml(context, vfs, path, name),
Self::Text => snapshot_txt(context, vfs, path, name),
Self::Yaml => snapshot_yaml(context, vfs, path, name),
Self::Ignore => Ok(None),
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
source: src/snapshot_middleware/yaml.rs
expression: instance_snapshot
---
snapshot_id: "00000000000000000000000000000000"
metadata:
ignore_unknown_instances: false
instigating_source:
Path: /foo.yml
relevant_paths:
- /foo.yml
- /foo.meta.json
context:
emit_legacy_scripts: true
name: foo
class_name: ModuleScript
properties:
Source:
String: "return {\n\tstring = \"this is a string\",\n\tboolean = true,\n\tnumber = 1337,\n\t[\"value-with-hypen\"] = \"it sure is\",\n\tsequence = {\"wow\", 8675309},\n\tmap = {{\n\t\tkey = \"value\",\n\t}, {\n\t\tkey2 = \"value 2\",\n\t}, {\n\t\tkey3 = \"value 3\",\n\t}},\n\twhatever_this_is = {\"i imagine\", \"it's\", \"a\", \"sequence?\"},\n}"
children: []
116 changes: 116 additions & 0 deletions src/snapshot_middleware/yaml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::path::Path;

use anyhow::Context;
use maplit::hashmap;
use memofs::{IoResultExt, Vfs};

use crate::{
lua_ast::{Expression, Statement},
snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot},
};

use super::meta_file::AdjacentMetadata;

pub fn snapshot_yaml(
context: &InstanceContext,
vfs: &Vfs,
path: &Path,
name: &str,
) -> anyhow::Result<Option<InstanceSnapshot>> {
let contents = vfs.read(path)?;

let value: serde_yaml::Value = serde_yaml::from_slice(&contents)
.with_context(|| format!("File contains malformed YAML: {}", path.display()))?;

let as_lua = yaml_to_lua(value).to_string();

let properties = hashmap! {
"Source".to_owned() => as_lua.into(),
};

let meta_path = path.with_file_name(format!("{}.meta.json", name));

let mut snapshot = InstanceSnapshot::new()
.name(name)
.class_name("ModuleScript")
.properties(properties)
.metadata(
InstanceMetadata::new()
.instigating_source(path)
.relevant_paths(vec![path.to_path_buf(), meta_path.clone()])
.context(context),
);

if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? {
let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?;
metadata.apply_all(&mut snapshot)?;
}

Ok(Some(snapshot))
}

fn yaml_to_lua(value: serde_yaml::Value) -> Statement {
Statement::Return(yaml_to_lua_value(value))
}

fn yaml_to_lua_value(value: serde_yaml::Value) -> Expression {
use serde_yaml::Value;

match value {
Value::Bool(value) => Expression::Bool(value),
Value::Null => Expression::Nil,
Value::Number(value) => Expression::Number(value.as_f64().unwrap()),
Value::String(value) => Expression::String(value),
Value::Mapping(map) => Expression::table(
map.into_iter()
.map(|(key, value)| (yaml_to_lua_value(key), yaml_to_lua_value(value)))
.collect(),
),
Value::Sequence(seq) => Expression::Array(seq.into_iter().map(yaml_to_lua_value).collect()),
}
}

#[cfg(test)]
mod test {
use super::*;

use memofs::{InMemoryFs, VfsSnapshot};

#[test]
fn instance_from_vfs() {
let mut imfs = InMemoryFs::new();
imfs.load_snapshot(
"/foo.yml",
VfsSnapshot::file(
r#"
---
string: this is a string
boolean: true
number: 1337
value-with-hypen: it sure is
sequence:
- wow
- 8675309
map:
- key: value
- key2: "value 2"
- key3: 'value 3'
whatever_this_is: [i imagine, it's, a, sequence?]"#,
),
)
.unwrap();

let vfs = Vfs::new(imfs.clone());

let instance_snapshot = snapshot_yaml(
&InstanceContext::default(),
&vfs,
Path::new("/foo.yml"),
"foo",
)
.unwrap()
.unwrap();

insta::assert_yaml_snapshot!(instance_snapshot);
}
}

0 comments on commit b341bb0

Please sign in to comment.