mirror of
https://github.com/lune-org/lune.git
synced 2025-01-22 10:48:04 +00:00
209 lines
5.7 KiB
Rust
209 lines
5.7 KiB
Rust
use std::path::Path;
|
|
|
|
use rbx_dom_weak::WeakDom;
|
|
|
|
use crate::instance::util::instance_is_a_service;
|
|
|
|
/**
|
|
A document kind specifier.
|
|
|
|
Valid variants are the following:
|
|
|
|
- `Model`
|
|
- `Place`
|
|
|
|
Other variants are only to be used for logic internal to this crate.
|
|
*/
|
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
|
pub enum DocumentKind {
|
|
InternalRoot,
|
|
Place,
|
|
Model,
|
|
}
|
|
|
|
impl DocumentKind {
|
|
/**
|
|
Try to convert a file extension into a valid document kind specifier.
|
|
|
|
Returns `None` if the file extension is not a canonical roblox file format extension.
|
|
*/
|
|
pub fn from_extension(extension: impl AsRef<str>) -> Option<Self> {
|
|
match extension.as_ref() {
|
|
"rbxl" | "rbxlx" => Some(Self::Place),
|
|
"rbxm" | "rbxmx" => Some(Self::Model),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/**
|
|
Try to convert a file path into a valid document kind specifier.
|
|
|
|
Returns `None` if the file extension of the path
|
|
is not a canonical roblox file format extension.
|
|
*/
|
|
pub fn from_path(path: impl AsRef<Path>) -> Option<Self> {
|
|
match path
|
|
.as_ref()
|
|
.extension()
|
|
.map(|ext| ext.to_string_lossy())
|
|
.as_deref()
|
|
{
|
|
Some("rbxl") | Some("rbxlx") => Some(Self::Place),
|
|
Some("rbxm") | Some("rbxmx") => Some(Self::Model),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/**
|
|
Try to detect a document kind specifier from a weak dom.
|
|
|
|
Returns `None` if the given dom is empty and as such can not have its kind inferred.
|
|
*/
|
|
pub fn from_weak_dom(dom: &WeakDom) -> Option<Self> {
|
|
let mut has_top_level_child = false;
|
|
let mut has_top_level_service = false;
|
|
for child_ref in dom.root().children() {
|
|
if let Some(child_inst) = dom.get_by_ref(*child_ref) {
|
|
has_top_level_child = true;
|
|
if instance_is_a_service(&child_inst.class).unwrap_or(false) {
|
|
has_top_level_service = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if has_top_level_service {
|
|
Some(Self::Place)
|
|
} else if has_top_level_child {
|
|
Some(Self::Model)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use std::path::PathBuf;
|
|
|
|
use rbx_dom_weak::InstanceBuilder;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn from_extension_place() {
|
|
assert_eq!(
|
|
DocumentKind::from_extension("rbxl"),
|
|
Some(DocumentKind::Place)
|
|
);
|
|
|
|
assert_eq!(
|
|
DocumentKind::from_extension("rbxlx"),
|
|
Some(DocumentKind::Place)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn from_extension_model() {
|
|
assert_eq!(
|
|
DocumentKind::from_extension("rbxm"),
|
|
Some(DocumentKind::Model)
|
|
);
|
|
|
|
assert_eq!(
|
|
DocumentKind::from_extension("rbxmx"),
|
|
Some(DocumentKind::Model)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn from_extension_invalid() {
|
|
assert_eq!(DocumentKind::from_extension("csv"), None);
|
|
assert_eq!(DocumentKind::from_extension("json"), None);
|
|
assert_eq!(DocumentKind::from_extension("rbx"), None);
|
|
assert_eq!(DocumentKind::from_extension("rbxn"), None);
|
|
assert_eq!(DocumentKind::from_extension("xlx"), None);
|
|
assert_eq!(DocumentKind::from_extension("xmx"), None);
|
|
}
|
|
|
|
#[test]
|
|
fn from_path_place() {
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from("place.rbxl")),
|
|
Some(DocumentKind::Place)
|
|
);
|
|
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from("place.rbxlx")),
|
|
Some(DocumentKind::Place)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn from_path_model() {
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from("model.rbxm")),
|
|
Some(DocumentKind::Model)
|
|
);
|
|
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from("model.rbxmx")),
|
|
Some(DocumentKind::Model)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn from_path_invalid() {
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from("data-file.csv")),
|
|
None
|
|
);
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from("nested/path/file.json")),
|
|
None
|
|
);
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from(".no-name-strange-rbx")),
|
|
None
|
|
);
|
|
assert_eq!(
|
|
DocumentKind::from_path(PathBuf::from("file_without_extension")),
|
|
None
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn from_weak_dom() {
|
|
let empty = WeakDom::new(InstanceBuilder::new("Instance"));
|
|
assert_eq!(DocumentKind::from_weak_dom(&empty), None);
|
|
|
|
let with_services = WeakDom::new(
|
|
InstanceBuilder::new("Instance")
|
|
.with_child(InstanceBuilder::new("Workspace"))
|
|
.with_child(InstanceBuilder::new("ReplicatedStorage")),
|
|
);
|
|
assert_eq!(
|
|
DocumentKind::from_weak_dom(&with_services),
|
|
Some(DocumentKind::Place)
|
|
);
|
|
|
|
let with_children = WeakDom::new(
|
|
InstanceBuilder::new("Instance")
|
|
.with_child(InstanceBuilder::new("Model"))
|
|
.with_child(InstanceBuilder::new("Part")),
|
|
);
|
|
assert_eq!(
|
|
DocumentKind::from_weak_dom(&with_children),
|
|
Some(DocumentKind::Model)
|
|
);
|
|
|
|
let with_mixed = WeakDom::new(
|
|
InstanceBuilder::new("Instance")
|
|
.with_child(InstanceBuilder::new("Workspace"))
|
|
.with_child(InstanceBuilder::new("Part")),
|
|
);
|
|
assert_eq!(
|
|
DocumentKind::from_weak_dom(&with_mixed),
|
|
Some(DocumentKind::Place)
|
|
);
|
|
}
|
|
}
|