mirror of
https://github.com/lune-org/lune.git
synced 2025-05-04 10:43:57 +01:00
Merge branch 'main' into datetime-rfc2822-support
This commit is contained in:
commit
f5d0967c24
20 changed files with 318 additions and 66 deletions
55
Cargo.lock
generated
55
Cargo.lock
generated
|
@ -28,6 +28,19 @@ dependencies = [
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"getrandom 0.2.15",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -2258,10 +2271,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_binary"
|
name = "rbx_binary"
|
||||||
version = "0.7.7"
|
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 = "7b85057e8ff75a1ce99248200c4b3c7b481a3d52f921f1053ecd67921dcc7930"
|
checksum = "9573fee5e073d7b303f475c285197fdc8179468de66ca60ee115a58fbac99296"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"log",
|
"log",
|
||||||
"lz4",
|
"lz4",
|
||||||
"profiling",
|
"profiling",
|
||||||
|
@ -2269,6 +2283,7 @@ dependencies = [
|
||||||
"rbx_reflection",
|
"rbx_reflection",
|
||||||
"rbx_reflection_database",
|
"rbx_reflection_database",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2288,19 +2303,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_dom_weak"
|
name = "rbx_dom_weak"
|
||||||
version = "2.9.0"
|
version = "3.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fcd2a17d09e46af0805f8b311a926402172b97e8d9388745c9adf8f448901841"
|
checksum = "04425cf6e9376e5486f4fb35906c120d1b1b45618a490318cf563fab1fa230a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"rbx_types",
|
"rbx_types",
|
||||||
"serde",
|
"serde",
|
||||||
|
"ustr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_reflection"
|
name = "rbx_reflection"
|
||||||
version = "4.7.0"
|
version = "5.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8118ac6021d700e8debe324af6b40ecfd2cef270a00247849dbdfeebb0802677"
|
checksum = "1b6d0d62baa613556b058a5f94a53b01cf0ccde0ea327ce03056e335b982e77e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rbx_types",
|
"rbx_types",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2309,9 +2326,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_reflection_database"
|
name = "rbx_reflection_database"
|
||||||
version = "0.2.12+roblox-638"
|
version = "1.0.1+roblox-666"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e29381d675420e841f8c02db5755cbb2545ed3e13f56c539546dc58702b512a"
|
checksum = "1ea11f26cfddc57a136781baed2e68eda5a3aa0735152d1562d65b1909c8d65d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"rbx_reflection",
|
"rbx_reflection",
|
||||||
|
@ -2321,9 +2338,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_types"
|
name = "rbx_types"
|
||||||
version = "1.10.0"
|
version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e30f49b2a3bb667e4074ba73c2dfb8ca0873f610b448ccf318a240acfdec6c73"
|
checksum = "78e4fdde46493def107e5f923d82e813dec9b3eef52c2f75fbad3a716023eda2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
|
@ -2336,10 +2353,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_xml"
|
name = "rbx_xml"
|
||||||
version = "0.13.5"
|
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 = "2b14b3027bc9ccd82e2fc854c8bcd25ed58318e570c355bf2cf63df9cdbd5ba8"
|
checksum = "bb623833c31cc43bbdaeb32f5e91db8ecd63fc46e438d0d268baf9e61539cf1c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"log",
|
"log",
|
||||||
"rbx_dom_weak",
|
"rbx_dom_weak",
|
||||||
|
@ -3483,6 +3501,19 @@ version = "2.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ustr"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18b19e258aa08450f93369cf56dd78063586adf19e92a75b338a800f799a0208"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"byteorder 1.5.0",
|
||||||
|
"lazy_static",
|
||||||
|
"parking_lot",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf-8"
|
name = "utf-8"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
|
|
|
@ -20,10 +20,10 @@ rand = "0.8"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
once_cell = "1.17"
|
once_cell = "1.17"
|
||||||
|
|
||||||
rbx_binary = "0.7.7"
|
rbx_binary = "1.0.0"
|
||||||
rbx_dom_weak = "2.9.0"
|
rbx_dom_weak = "3.0.0"
|
||||||
rbx_reflection = "4.7.0"
|
rbx_reflection = "5.0.0"
|
||||||
rbx_reflection_database = "0.2.12"
|
rbx_reflection_database = "1.0.0"
|
||||||
rbx_xml = "0.13.5"
|
rbx_xml = "1.0.0"
|
||||||
|
|
||||||
lune-utils = { version = "0.1.3", path = "../lune-utils" }
|
lune-utils = { version = "0.1.3", path = "../lune-utils" }
|
||||||
|
|
|
@ -47,6 +47,7 @@ pub fn ensure_valid_attribute_value(value: &DomValue) -> LuaResult<()> {
|
||||||
| DomType::CFrame
|
| DomType::CFrame
|
||||||
| DomType::Color3
|
| DomType::Color3
|
||||||
| DomType::ColorSequence
|
| DomType::ColorSequence
|
||||||
|
| DomType::EnumItem
|
||||||
| DomType::Float32
|
| DomType::Float32
|
||||||
| DomType::Float64
|
| DomType::Float64
|
||||||
| DomType::Font
|
| DomType::Font
|
||||||
|
|
|
@ -51,7 +51,7 @@ impl<'lua> DomValueToLua<'lua> for LuaValue<'lua> {
|
||||||
DomValue::Float32(n) => Ok(LuaValue::Number(*n as f64)),
|
DomValue::Float32(n) => Ok(LuaValue::Number(*n as f64)),
|
||||||
DomValue::String(s) => Ok(LuaValue::String(lua.create_string(s)?)),
|
DomValue::String(s) => Ok(LuaValue::String(lua.create_string(s)?)),
|
||||||
DomValue::BinaryString(s) => Ok(LuaValue::String(lua.create_string(s)?)),
|
DomValue::BinaryString(s) => Ok(LuaValue::String(lua.create_string(s)?)),
|
||||||
DomValue::Content(s) => Ok(LuaValue::String(
|
DomValue::ContentId(s) => Ok(LuaValue::String(
|
||||||
lua.create_string(AsRef::<str>::as_ref(s))?,
|
lua.create_string(AsRef::<str>::as_ref(s))?,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
|
@ -104,8 +104,8 @@ impl<'lua> LuaToDomValue<'lua> for LuaValue<'lua> {
|
||||||
(LuaValue::String(s), DomType::BinaryString) => {
|
(LuaValue::String(s), DomType::BinaryString) => {
|
||||||
Ok(DomValue::BinaryString(s.as_ref().into()))
|
Ok(DomValue::BinaryString(s.as_ref().into()))
|
||||||
}
|
}
|
||||||
(LuaValue::String(s), DomType::Content) => {
|
(LuaValue::String(s), DomType::ContentId) => {
|
||||||
Ok(DomValue::Content(s.to_str()?.to_string().into()))
|
Ok(DomValue::ContentId(s.to_str()?.to_string().into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Some values are either optional or default and we
|
// NOTE: Some values are either optional or default and we
|
||||||
|
@ -200,6 +200,8 @@ impl<'lua> DomValueToLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
DomValue::Color3(value) => dom_to_userdata!(lua, value => Color3),
|
DomValue::Color3(value) => dom_to_userdata!(lua, value => Color3),
|
||||||
DomValue::Color3uint8(value) => dom_to_userdata!(lua, value => Color3),
|
DomValue::Color3uint8(value) => dom_to_userdata!(lua, value => Color3),
|
||||||
DomValue::ColorSequence(value) => dom_to_userdata!(lua, value => ColorSequence),
|
DomValue::ColorSequence(value) => dom_to_userdata!(lua, value => ColorSequence),
|
||||||
|
DomValue::Content(value) => dom_to_userdata!(lua, value => Content),
|
||||||
|
DomValue::EnumItem(value) => dom_to_userdata!(lua, value => EnumItem),
|
||||||
DomValue::Faces(value) => dom_to_userdata!(lua, value => Faces),
|
DomValue::Faces(value) => dom_to_userdata!(lua, value => Faces),
|
||||||
DomValue::Font(value) => dom_to_userdata!(lua, value => Font),
|
DomValue::Font(value) => dom_to_userdata!(lua, value => Font),
|
||||||
DomValue::NumberRange(value) => dom_to_userdata!(lua, value => NumberRange),
|
DomValue::NumberRange(value) => dom_to_userdata!(lua, value => NumberRange),
|
||||||
|
@ -256,7 +258,8 @@ impl<'lua> LuaToDomValue<'lua> for LuaAnyUserData<'lua> {
|
||||||
DomType::Color3 => userdata_to_dom!(self as Color3 => dom::Color3),
|
DomType::Color3 => userdata_to_dom!(self as Color3 => dom::Color3),
|
||||||
DomType::Color3uint8 => userdata_to_dom!(self as Color3 => dom::Color3uint8),
|
DomType::Color3uint8 => userdata_to_dom!(self as Color3 => dom::Color3uint8),
|
||||||
DomType::ColorSequence => userdata_to_dom!(self as ColorSequence => dom::ColorSequence),
|
DomType::ColorSequence => userdata_to_dom!(self as ColorSequence => dom::ColorSequence),
|
||||||
DomType::Enum => userdata_to_dom!(self as EnumItem => dom::Enum),
|
DomType::Content => userdata_to_dom!(self as Content => dom::Content),
|
||||||
|
DomType::EnumItem => userdata_to_dom!(self as EnumItem => dom::EnumItem),
|
||||||
DomType::Faces => userdata_to_dom!(self as Faces => dom::Faces),
|
DomType::Faces => userdata_to_dom!(self as Faces => dom::Faces),
|
||||||
DomType::Font => userdata_to_dom!(self as Font => dom::Font),
|
DomType::Font => userdata_to_dom!(self as Font => dom::Font),
|
||||||
DomType::NumberRange => userdata_to_dom!(self as NumberRange => dom::NumberRange),
|
DomType::NumberRange => userdata_to_dom!(self as NumberRange => dom::NumberRange),
|
||||||
|
@ -314,7 +317,7 @@ impl<'lua> LuaToDomValue<'lua> for LuaAnyUserData<'lua> {
|
||||||
value if value.is::<CFrame>() => userdata_to_dom!(value as CFrame => dom::CFrame),
|
value if value.is::<CFrame>() => userdata_to_dom!(value as CFrame => dom::CFrame),
|
||||||
value if value.is::<Color3>() => userdata_to_dom!(value as Color3 => dom::Color3),
|
value if value.is::<Color3>() => userdata_to_dom!(value as Color3 => dom::Color3),
|
||||||
value if value.is::<ColorSequence>() => userdata_to_dom!(value as ColorSequence => dom::ColorSequence),
|
value if value.is::<ColorSequence>() => userdata_to_dom!(value as ColorSequence => dom::ColorSequence),
|
||||||
value if value.is::<Enum>() => userdata_to_dom!(value as EnumItem => dom::Enum),
|
value if value.is::<EnumItem>() => userdata_to_dom!(value as EnumItem => dom::EnumItem),
|
||||||
value if value.is::<Faces>() => userdata_to_dom!(value as Faces => dom::Faces),
|
value if value.is::<Faces>() => userdata_to_dom!(value as Faces => dom::Faces),
|
||||||
value if value.is::<Font>() => userdata_to_dom!(value as Font => dom::Font),
|
value if value.is::<Font>() => userdata_to_dom!(value as Font => dom::Font),
|
||||||
value if value.is::<Instance>() => userdata_to_dom!(value as Instance => dom::Ref),
|
value if value.is::<Instance>() => userdata_to_dom!(value as Instance => dom::Ref),
|
||||||
|
|
|
@ -19,7 +19,9 @@ impl DomValueExt for DomType {
|
||||||
Color3uint8 => "Color3uint8",
|
Color3uint8 => "Color3uint8",
|
||||||
ColorSequence => "ColorSequence",
|
ColorSequence => "ColorSequence",
|
||||||
Content => "Content",
|
Content => "Content",
|
||||||
|
ContentId => "ContentId",
|
||||||
Enum => "Enum",
|
Enum => "Enum",
|
||||||
|
EnumItem => "EnumItem",
|
||||||
Faces => "Faces",
|
Faces => "Faces",
|
||||||
Float32 => "Float32",
|
Float32 => "Float32",
|
||||||
Float64 => "Float64",
|
Float64 => "Float64",
|
||||||
|
|
120
crates/lune-roblox/src/datatypes/types/content.rs
Normal file
120
crates/lune-roblox/src/datatypes/types/content.rs
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use rbx_dom_weak::types::{Content as DomContent, ContentType};
|
||||||
|
|
||||||
|
use lune_utils::TableBuilder;
|
||||||
|
|
||||||
|
use crate::{exports::LuaExportsTable, instance::Instance};
|
||||||
|
|
||||||
|
use super::{super::*, EnumItem};
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the [Content](https://create.roblox.com/docs/reference/engine/datatypes/Content) Roblox datatype.
|
||||||
|
|
||||||
|
This implements all documented properties, methods & constructors of the Content type as of April 2025.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Content(ContentType);
|
||||||
|
|
||||||
|
impl LuaExportsTable<'_> for Content {
|
||||||
|
const EXPORT_NAME: &'static str = "Content";
|
||||||
|
|
||||||
|
fn create_exports_table(lua: &'_ Lua) -> LuaResult<LuaTable<'_>> {
|
||||||
|
let from_uri = |_, uri: String| Ok(Self(ContentType::Uri(uri)));
|
||||||
|
|
||||||
|
let from_object = |_, obj: LuaUserDataRef<Instance>| {
|
||||||
|
let database = rbx_reflection_database::get();
|
||||||
|
let instance_descriptor = database
|
||||||
|
.classes
|
||||||
|
.get("Instance")
|
||||||
|
.expect("the reflection database should always have Instance in it");
|
||||||
|
let param_descriptor = database.classes.get(obj.get_class_name()).expect(
|
||||||
|
"you should not be able to construct an Instance that is not known to Lune",
|
||||||
|
);
|
||||||
|
if database.has_superclass(param_descriptor, instance_descriptor) {
|
||||||
|
Err(LuaError::runtime("the provided object is a descendant class of 'Instance', expected one that was only an 'Object'"))
|
||||||
|
} else {
|
||||||
|
Ok(Content(ContentType::Object(obj.dom_ref)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TableBuilder::new(lua)?
|
||||||
|
.with_value("none", Content(ContentType::None))?
|
||||||
|
.with_function("fromUri", from_uri)?
|
||||||
|
.with_function("fromObject", from_object)?
|
||||||
|
.build_readonly()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for Content {
|
||||||
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("SourceType", |_, this| {
|
||||||
|
let variant_name = match &this.0 {
|
||||||
|
ContentType::None => "None",
|
||||||
|
ContentType::Uri(_) => "Uri",
|
||||||
|
ContentType::Object(_) => "Object",
|
||||||
|
other => {
|
||||||
|
return Err(LuaError::runtime(format!(
|
||||||
|
"cannot get SourceType: unknown ContentType variant '{other:?}'"
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(EnumItem::from_enum_name_and_name(
|
||||||
|
"ContentSourceType",
|
||||||
|
variant_name,
|
||||||
|
))
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("Uri", |_, this| {
|
||||||
|
if let ContentType::Uri(uri) = &this.0 {
|
||||||
|
Ok(Some(uri.to_owned()))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fields.add_field_method_get("Object", |_, this| {
|
||||||
|
if let ContentType::Object(referent) = &this.0 {
|
||||||
|
Ok(Instance::new_opt(*referent))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||||
|
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Content {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
// Regardless of the actual content of the Content, Roblox just emits
|
||||||
|
// `Content` when casting it to a string. We do not do that.
|
||||||
|
write!(f, "Content(")?;
|
||||||
|
match &self.0 {
|
||||||
|
ContentType::None => write!(f, "None")?,
|
||||||
|
ContentType::Uri(uri) => write!(f, "Uri={uri}")?,
|
||||||
|
ContentType::Object(_) => write!(f, "Object")?,
|
||||||
|
other => write!(f, "UnknownType({other:?})")?,
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DomContent> for Content {
|
||||||
|
fn from(value: DomContent) -> Self {
|
||||||
|
Self(value.value().clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Content> for DomContent {
|
||||||
|
fn from(value: Content) -> Self {
|
||||||
|
match value.0 {
|
||||||
|
ContentType::None => Self::none(),
|
||||||
|
ContentType::Uri(uri) => Self::from_uri(uri),
|
||||||
|
ContentType::Object(referent) => Self::from_referent(referent),
|
||||||
|
other => unimplemented!("unknown variant of ContentType: {other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
use rbx_dom_weak::types::Enum as DomEnum;
|
use rbx_dom_weak::types::EnumItem as DomEnumItem;
|
||||||
|
|
||||||
use super::{super::*, Enum};
|
use super::{super::*, Enum};
|
||||||
|
|
||||||
|
@ -100,8 +100,18 @@ impl PartialEq for EnumItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EnumItem> for DomEnum {
|
impl From<EnumItem> for DomEnumItem {
|
||||||
fn from(v: EnumItem) -> Self {
|
fn from(v: EnumItem) -> Self {
|
||||||
DomEnum::from_u32(v.value)
|
DomEnumItem {
|
||||||
|
ty: v.parent.desc.name.to_string(),
|
||||||
|
value: v.value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DomEnumItem> for EnumItem {
|
||||||
|
fn from(value: DomEnumItem) -> Self {
|
||||||
|
EnumItem::from_enum_name_and_value(value.ty, value.value)
|
||||||
|
.expect("cannot convert rbx_type::EnumItem with unknown type into EnumItem")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ mod cframe;
|
||||||
mod color3;
|
mod color3;
|
||||||
mod color_sequence;
|
mod color_sequence;
|
||||||
mod color_sequence_keypoint;
|
mod color_sequence_keypoint;
|
||||||
|
mod content;
|
||||||
mod r#enum;
|
mod r#enum;
|
||||||
mod r#enum_item;
|
mod r#enum_item;
|
||||||
mod r#enums;
|
mod r#enums;
|
||||||
|
@ -30,6 +31,7 @@ pub use cframe::CFrame;
|
||||||
pub use color3::Color3;
|
pub use color3::Color3;
|
||||||
pub use color_sequence::ColorSequence;
|
pub use color_sequence::ColorSequence;
|
||||||
pub use color_sequence_keypoint::ColorSequenceKeypoint;
|
pub use color_sequence_keypoint::ColorSequenceKeypoint;
|
||||||
|
pub use content::Content;
|
||||||
pub use faces::Faces;
|
pub use faces::Faces;
|
||||||
pub use font::Font;
|
pub use font::Font;
|
||||||
pub use number_range::NumberRange;
|
pub use number_range::NumberRange;
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl DocumentKind {
|
||||||
for child_ref in dom.root().children() {
|
for child_ref in dom.root().children() {
|
||||||
if let Some(child_inst) = dom.get_by_ref(*child_ref) {
|
if let Some(child_inst) = dom.get_by_ref(*child_ref) {
|
||||||
has_top_level_child = true;
|
has_top_level_child = true;
|
||||||
if class_is_a_service(&child_inst.class).unwrap_or(false) {
|
if class_is_a_service(child_inst.class).unwrap_or(false) {
|
||||||
has_top_level_service = true;
|
has_top_level_service = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rbx_dom_weak::{
|
use rbx_dom_weak::{
|
||||||
types::{Ref as DomRef, VariantType as DomType},
|
types::{Ref as DomRef, VariantType as DomType},
|
||||||
Instance as DomInstance, WeakDom,
|
ustr, Instance as DomInstance, WeakDom,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::shared::instance::class_is_a;
|
use crate::shared::instance::class_is_a;
|
||||||
|
@ -18,8 +18,8 @@ pub fn postprocess_dom_for_model(dom: &mut WeakDom) {
|
||||||
remove_matching_prop(inst, DomType::UniqueId, "HistoryId");
|
remove_matching_prop(inst, DomType::UniqueId, "HistoryId");
|
||||||
// Similar story with ScriptGuid - this is used
|
// Similar story with ScriptGuid - this is used
|
||||||
// in the studio-only cloud script drafts feature
|
// in the studio-only cloud script drafts feature
|
||||||
if class_is_a(&inst.class, "LuaSourceContainer").unwrap_or(false) {
|
if class_is_a(inst.class, "LuaSourceContainer").unwrap_or(false) {
|
||||||
inst.properties.remove("ScriptGuid");
|
inst.properties.remove(&ustr("ScriptGuid"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_matching_prop(inst: &mut DomInstance, ty: DomType, name: &'static str) {
|
fn remove_matching_prop(inst: &mut DomInstance, ty: DomType, name: &'static str) {
|
||||||
|
let name = &ustr(name);
|
||||||
if inst.properties.get(name).is_some_and(|u| u.ty() == ty) {
|
if inst.properties.get(name).is_some_and(|u| u.ty() == ty) {
|
||||||
inst.properties.remove(name);
|
inst.properties.remove(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(m: &mut M) {
|
||||||
"FindFirstAncestorWhichIsA",
|
"FindFirstAncestorWhichIsA",
|
||||||
|lua, this, class_name: String| {
|
|lua, this, class_name: String| {
|
||||||
ensure_not_destroyed(this)?;
|
ensure_not_destroyed(this)?;
|
||||||
this.find_ancestor(|child| class_is_a(&child.class, &class_name).unwrap_or(false))
|
this.find_ancestor(|child| class_is_a(child.class, &class_name).unwrap_or(false))
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -104,7 +104,7 @@ pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(m: &mut M) {
|
||||||
|lua, this, (class_name, recursive): (String, Option<bool>)| {
|
|lua, this, (class_name, recursive): (String, Option<bool>)| {
|
||||||
ensure_not_destroyed(this)?;
|
ensure_not_destroyed(this)?;
|
||||||
let predicate =
|
let predicate =
|
||||||
|child: &DomInstance| class_is_a(&child.class, &class_name).unwrap_or(false);
|
|child: &DomInstance| class_is_a(child.class, &class_name).unwrap_or(false);
|
||||||
if matches!(recursive, Some(true)) {
|
if matches!(recursive, Some(true)) {
|
||||||
this.find_descendant(predicate).into_lua(lua)
|
this.find_descendant(predicate).into_lua(lua)
|
||||||
} else {
|
} else {
|
||||||
|
@ -113,7 +113,7 @@ pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(m: &mut M) {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
m.add_method("IsA", |_, this, class_name: String| {
|
m.add_method("IsA", |_, this, class_name: String| {
|
||||||
Ok(class_is_a(&this.class_name, class_name).unwrap_or(false))
|
Ok(class_is_a(this.class_name, class_name).unwrap_or(false))
|
||||||
});
|
});
|
||||||
m.add_method(
|
m.add_method(
|
||||||
"IsAncestorOf",
|
"IsAncestorOf",
|
||||||
|
@ -230,7 +230,7 @@ fn instance_property_get<'lua>(
|
||||||
return this.get_name().into_lua(lua);
|
return this.get_name().into_lua(lua);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(info) = find_property_info(&this.class_name, &prop_name) {
|
if let Some(info) = find_property_info(this.class_name, &prop_name) {
|
||||||
if let Some(prop) = this.get_property(&prop_name) {
|
if let Some(prop) = this.get_property(&prop_name) {
|
||||||
if let DomValue::Enum(enum_value) = prop {
|
if let DomValue::Enum(enum_value) = prop {
|
||||||
let enum_name = info.enum_name.ok_or_else(|| {
|
let enum_name = info.enum_name.ok_or_else(|| {
|
||||||
|
@ -275,7 +275,7 @@ fn instance_property_get<'lua>(
|
||||||
} else if let Some(inst) = this.find_child(|inst| inst.name == prop_name) {
|
} else if let Some(inst) = this.find_child(|inst| inst.name == prop_name) {
|
||||||
Ok(LuaValue::UserData(lua.create_userdata(inst)?))
|
Ok(LuaValue::UserData(lua.create_userdata(inst)?))
|
||||||
} else if let Some(getter) = InstanceRegistry::find_property_getter(lua, this, &prop_name) {
|
} else if let Some(getter) = InstanceRegistry::find_property_getter(lua, this, &prop_name) {
|
||||||
getter.call(this.clone())
|
getter.call(*this)
|
||||||
} else if let Some(method) = InstanceRegistry::find_method(lua, this, &prop_name) {
|
} else if let Some(method) = InstanceRegistry::find_method(lua, this, &prop_name) {
|
||||||
Ok(LuaValue::Function(method))
|
Ok(LuaValue::Function(method))
|
||||||
} else {
|
} else {
|
||||||
|
@ -321,17 +321,17 @@ fn instance_property_set<'lua>(
|
||||||
}
|
}
|
||||||
type Parent<'lua> = Option<LuaUserDataRef<'lua, Instance>>;
|
type Parent<'lua> = Option<LuaUserDataRef<'lua, Instance>>;
|
||||||
let parent = Parent::from_lua(prop_value, lua)?;
|
let parent = Parent::from_lua(prop_value, lua)?;
|
||||||
this.set_parent(parent.map(|p| p.clone()));
|
this.set_parent(parent.map(|p| *p));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(info) = find_property_info(&this.class_name, &prop_name) {
|
if let Some(info) = find_property_info(this.class_name, &prop_name) {
|
||||||
if let Some(enum_name) = info.enum_name {
|
if let Some(enum_name) = info.enum_name {
|
||||||
match LuaUserDataRef::<EnumItem>::from_lua(prop_value, lua) {
|
match LuaUserDataRef::<EnumItem>::from_lua(prop_value, lua) {
|
||||||
Ok(given_enum) if given_enum.parent.desc.name == enum_name => {
|
Ok(given_enum) if given_enum.parent.desc.name == enum_name => {
|
||||||
this.set_property(prop_name, DomValue::Enum((*given_enum).clone().into()));
|
this.set_property(prop_name, DomValue::EnumItem((*given_enum).clone().into()));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Ok(given_enum) => Err(LuaError::RuntimeError(format!(
|
Ok(given_enum) => Err(LuaError::RuntimeError(format!(
|
||||||
|
@ -354,7 +354,7 @@ fn instance_property_set<'lua>(
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
} else if let Some(setter) = InstanceRegistry::find_property_setter(lua, this, &prop_name) {
|
} else if let Some(setter) = InstanceRegistry::find_property_setter(lua, this, &prop_name) {
|
||||||
setter.call((this.clone(), prop_value))
|
setter.call((*this, prop_value))
|
||||||
} else {
|
} else {
|
||||||
Err(LuaError::RuntimeError(format!(
|
Err(LuaError::RuntimeError(format!(
|
||||||
"{prop_name} is not a valid member of {this}",
|
"{prop_name} is not a valid member of {this}",
|
||||||
|
|
|
@ -48,7 +48,7 @@ fn data_model_get_service(_: &Lua, this: &Instance, service_name: String) -> Lua
|
||||||
Ok(service)
|
Ok(service)
|
||||||
} else {
|
} else {
|
||||||
let service = Instance::new_orphaned(service_name);
|
let service = Instance::new_orphaned(service_name);
|
||||||
service.set_parent(Some(this.clone()));
|
service.set_parent(Some(*this));
|
||||||
Ok(service)
|
Ok(service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use mlua::prelude::*;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rbx_dom_weak::{
|
use rbx_dom_weak::{
|
||||||
types::{Attributes as DomAttributes, Ref as DomRef, Variant as DomValue},
|
types::{Attributes as DomAttributes, Ref as DomRef, Variant as DomValue},
|
||||||
Instance as DomInstance, InstanceBuilder as DomInstanceBuilder, WeakDom,
|
ustr, Instance as DomInstance, InstanceBuilder as DomInstanceBuilder, Ustr, WeakDom,
|
||||||
};
|
};
|
||||||
|
|
||||||
use lune_utils::TableBuilder;
|
use lune_utils::TableBuilder;
|
||||||
|
@ -34,10 +34,10 @@ const PROPERTY_NAME_TAGS: &str = "Tags";
|
||||||
static INTERNAL_DOM: Lazy<Mutex<WeakDom>> =
|
static INTERNAL_DOM: Lazy<Mutex<WeakDom>> =
|
||||||
Lazy::new(|| Mutex::new(WeakDom::new(DomInstanceBuilder::new("ROOT"))));
|
Lazy::new(|| Mutex::new(WeakDom::new(DomInstanceBuilder::new("ROOT"))));
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
pub(crate) dom_ref: DomRef,
|
pub(crate) dom_ref: DomRef,
|
||||||
pub(crate) class_name: String,
|
pub(crate) class_name: Ustr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
|
@ -75,7 +75,7 @@ impl Instance {
|
||||||
|
|
||||||
Some(Self {
|
Some(Self {
|
||||||
dom_ref,
|
dom_ref,
|
||||||
class_name: instance.class.clone(),
|
class_name: instance.class,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -96,14 +96,14 @@ impl Instance {
|
||||||
|
|
||||||
let class_name = class_name.as_ref();
|
let class_name = class_name.as_ref();
|
||||||
|
|
||||||
let instance = DomInstanceBuilder::new(class_name.to_string());
|
let instance = DomInstanceBuilder::new(class_name);
|
||||||
|
|
||||||
let dom_root = dom.root_ref();
|
let dom_root = dom.root_ref();
|
||||||
let dom_ref = dom.insert(dom_root, instance);
|
let dom_ref = dom.insert(dom_root, instance);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
dom_ref,
|
dom_ref,
|
||||||
class_name: class_name.to_string(),
|
class_name: ustr(class_name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ impl Instance {
|
||||||
on the Roblox Developer Hub
|
on the Roblox Developer Hub
|
||||||
*/
|
*/
|
||||||
pub fn is_a(&self, class_name: impl AsRef<str>) -> bool {
|
pub fn is_a(&self, class_name: impl AsRef<str>) -> bool {
|
||||||
class_is_a(&self.class_name, class_name).unwrap_or(false)
|
class_is_a(self.class_name, class_name).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -341,7 +341,7 @@ impl Instance {
|
||||||
.get_by_ref(self.dom_ref)
|
.get_by_ref(self.dom_ref)
|
||||||
.expect("Failed to find instance in document")
|
.expect("Failed to find instance in document")
|
||||||
.properties
|
.properties
|
||||||
.get(name.as_ref())
|
.get(&ustr(name.as_ref()))
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ impl Instance {
|
||||||
.get_by_ref_mut(self.dom_ref)
|
.get_by_ref_mut(self.dom_ref)
|
||||||
.expect("Failed to find instance in document")
|
.expect("Failed to find instance in document")
|
||||||
.properties
|
.properties
|
||||||
.insert(name.as_ref().to_string(), value);
|
.insert(ustr(name.as_ref()), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -374,7 +374,7 @@ impl Instance {
|
||||||
.get_by_ref(self.dom_ref)
|
.get_by_ref(self.dom_ref)
|
||||||
.expect("Failed to find instance in document");
|
.expect("Failed to find instance in document");
|
||||||
if let Some(DomValue::Attributes(attributes)) =
|
if let Some(DomValue::Attributes(attributes)) =
|
||||||
inst.properties.get(PROPERTY_NAME_ATTRIBUTES)
|
inst.properties.get(&ustr(PROPERTY_NAME_ATTRIBUTES))
|
||||||
{
|
{
|
||||||
attributes.get(name.as_ref()).cloned()
|
attributes.get(name.as_ref()).cloned()
|
||||||
} else {
|
} else {
|
||||||
|
@ -395,7 +395,7 @@ impl Instance {
|
||||||
.get_by_ref(self.dom_ref)
|
.get_by_ref(self.dom_ref)
|
||||||
.expect("Failed to find instance in document");
|
.expect("Failed to find instance in document");
|
||||||
if let Some(DomValue::Attributes(attributes)) =
|
if let Some(DomValue::Attributes(attributes)) =
|
||||||
inst.properties.get(PROPERTY_NAME_ATTRIBUTES)
|
inst.properties.get(&ustr(PROPERTY_NAME_ATTRIBUTES))
|
||||||
{
|
{
|
||||||
attributes.clone().into_iter().collect()
|
attributes.clone().into_iter().collect()
|
||||||
} else {
|
} else {
|
||||||
|
@ -422,14 +422,14 @@ impl Instance {
|
||||||
value => value,
|
value => value,
|
||||||
};
|
};
|
||||||
if let Some(DomValue::Attributes(attributes)) =
|
if let Some(DomValue::Attributes(attributes)) =
|
||||||
inst.properties.get_mut(PROPERTY_NAME_ATTRIBUTES)
|
inst.properties.get_mut(&ustr(PROPERTY_NAME_ATTRIBUTES))
|
||||||
{
|
{
|
||||||
attributes.insert(name.as_ref().to_string(), value);
|
attributes.insert(name.as_ref().to_string(), value);
|
||||||
} else {
|
} else {
|
||||||
let mut attributes = DomAttributes::new();
|
let mut attributes = DomAttributes::new();
|
||||||
attributes.insert(name.as_ref().to_string(), value);
|
attributes.insert(name.as_ref().to_string(), value);
|
||||||
inst.properties.insert(
|
inst.properties.insert(
|
||||||
PROPERTY_NAME_ATTRIBUTES.to_string(),
|
ustr(PROPERTY_NAME_ATTRIBUTES),
|
||||||
DomValue::Attributes(attributes),
|
DomValue::Attributes(attributes),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -449,11 +449,11 @@ impl Instance {
|
||||||
.get_by_ref_mut(self.dom_ref)
|
.get_by_ref_mut(self.dom_ref)
|
||||||
.expect("Failed to find instance in document");
|
.expect("Failed to find instance in document");
|
||||||
if let Some(DomValue::Attributes(attributes)) =
|
if let Some(DomValue::Attributes(attributes)) =
|
||||||
inst.properties.get_mut(PROPERTY_NAME_ATTRIBUTES)
|
inst.properties.get_mut(&ustr(PROPERTY_NAME_ATTRIBUTES))
|
||||||
{
|
{
|
||||||
attributes.remove(name.as_ref());
|
attributes.remove(name.as_ref());
|
||||||
if attributes.is_empty() {
|
if attributes.is_empty() {
|
||||||
inst.properties.remove(PROPERTY_NAME_ATTRIBUTES);
|
inst.properties.remove(&ustr(PROPERTY_NAME_ATTRIBUTES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,11 +470,11 @@ impl Instance {
|
||||||
let inst = dom
|
let inst = dom
|
||||||
.get_by_ref_mut(self.dom_ref)
|
.get_by_ref_mut(self.dom_ref)
|
||||||
.expect("Failed to find instance in document");
|
.expect("Failed to find instance in document");
|
||||||
if let Some(DomValue::Tags(tags)) = inst.properties.get_mut(PROPERTY_NAME_TAGS) {
|
if let Some(DomValue::Tags(tags)) = inst.properties.get_mut(&ustr(PROPERTY_NAME_TAGS)) {
|
||||||
tags.push(name.as_ref());
|
tags.push(name.as_ref());
|
||||||
} else {
|
} else {
|
||||||
inst.properties.insert(
|
inst.properties.insert(
|
||||||
PROPERTY_NAME_TAGS.to_string(),
|
ustr(PROPERTY_NAME_TAGS),
|
||||||
DomValue::Tags(vec![name.as_ref().to_string()].into()),
|
DomValue::Tags(vec![name.as_ref().to_string()].into()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -492,7 +492,7 @@ impl Instance {
|
||||||
let inst = dom
|
let inst = dom
|
||||||
.get_by_ref(self.dom_ref)
|
.get_by_ref(self.dom_ref)
|
||||||
.expect("Failed to find instance in document");
|
.expect("Failed to find instance in document");
|
||||||
if let Some(DomValue::Tags(tags)) = inst.properties.get(PROPERTY_NAME_TAGS) {
|
if let Some(DomValue::Tags(tags)) = inst.properties.get(&ustr(PROPERTY_NAME_TAGS)) {
|
||||||
tags.iter().map(ToString::to_string).collect()
|
tags.iter().map(ToString::to_string).collect()
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
@ -511,7 +511,7 @@ impl Instance {
|
||||||
let inst = dom
|
let inst = dom
|
||||||
.get_by_ref(self.dom_ref)
|
.get_by_ref(self.dom_ref)
|
||||||
.expect("Failed to find instance in document");
|
.expect("Failed to find instance in document");
|
||||||
if let Some(DomValue::Tags(tags)) = inst.properties.get(PROPERTY_NAME_TAGS) {
|
if let Some(DomValue::Tags(tags)) = inst.properties.get(&ustr(PROPERTY_NAME_TAGS)) {
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
tags.iter().any(|tag| tag == name)
|
tags.iter().any(|tag| tag == name)
|
||||||
} else {
|
} else {
|
||||||
|
@ -531,14 +531,12 @@ impl Instance {
|
||||||
let inst = dom
|
let inst = dom
|
||||||
.get_by_ref_mut(self.dom_ref)
|
.get_by_ref_mut(self.dom_ref)
|
||||||
.expect("Failed to find instance in document");
|
.expect("Failed to find instance in document");
|
||||||
if let Some(DomValue::Tags(tags)) = inst.properties.get_mut(PROPERTY_NAME_TAGS) {
|
if let Some(DomValue::Tags(tags)) = inst.properties.get_mut(&ustr(PROPERTY_NAME_TAGS)) {
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
let mut new_tags = tags.iter().map(ToString::to_string).collect::<Vec<_>>();
|
let mut new_tags = tags.iter().map(ToString::to_string).collect::<Vec<_>>();
|
||||||
new_tags.retain(|tag| tag != name);
|
new_tags.retain(|tag| tag != name);
|
||||||
inst.properties.insert(
|
inst.properties
|
||||||
PROPERTY_NAME_TAGS.to_string(),
|
.insert(ustr(PROPERTY_NAME_TAGS), DomValue::Tags(new_tags.into()));
|
||||||
DomValue::Tags(new_tags.into()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ fn create_all_exports(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
||||||
export::<Color3>(lua)?,
|
export::<Color3>(lua)?,
|
||||||
export::<ColorSequence>(lua)?,
|
export::<ColorSequence>(lua)?,
|
||||||
export::<ColorSequenceKeypoint>(lua)?,
|
export::<ColorSequenceKeypoint>(lua)?,
|
||||||
|
export::<Content>(lua)?,
|
||||||
export::<Faces>(lua)?,
|
export::<Faces>(lua)?,
|
||||||
export::<Font>(lua)?,
|
export::<Font>(lua)?,
|
||||||
export::<NumberRange>(lua)?,
|
export::<NumberRange>(lua)?,
|
||||||
|
|
|
@ -122,7 +122,7 @@ pub(crate) fn get_or_create_property_ref_instance(
|
||||||
Ok(inst)
|
Ok(inst)
|
||||||
} else {
|
} else {
|
||||||
let inst = Instance::new_orphaned(class_name);
|
let inst = Instance::new_orphaned(class_name);
|
||||||
inst.set_parent(Some(this.clone()));
|
inst.set_parent(Some(*this));
|
||||||
this.set_property(prop_name, DomValue::Ref(inst.dom_ref));
|
this.set_property(prop_name, DomValue::Ref(inst.dom_ref));
|
||||||
Ok(inst)
|
Ok(inst)
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ async fn serialize_place<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
(data_model, as_xml): (LuaUserDataRef<'lua, Instance>, Option<bool>),
|
(data_model, as_xml): (LuaUserDataRef<'lua, Instance>, Option<bool>),
|
||||||
) -> LuaResult<LuaString<'lua>> {
|
) -> LuaResult<LuaString<'lua>> {
|
||||||
let data_model = (*data_model).clone();
|
let data_model = *data_model;
|
||||||
let fut = lua.spawn_blocking(move || {
|
let fut = lua.spawn_blocking(move || {
|
||||||
let doc = Document::from_data_model_instance(data_model)?;
|
let doc = Document::from_data_model_instance(data_model)?;
|
||||||
let bytes = doc.to_bytes_with_format(match as_xml {
|
let bytes = doc.to_bytes_with_format(match as_xml {
|
||||||
|
@ -94,7 +94,7 @@ async fn serialize_model<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
(instances, as_xml): (Vec<LuaUserDataRef<'lua, Instance>>, Option<bool>),
|
(instances, as_xml): (Vec<LuaUserDataRef<'lua, Instance>>, Option<bool>),
|
||||||
) -> LuaResult<LuaString<'lua>> {
|
) -> LuaResult<LuaString<'lua>> {
|
||||||
let instances = instances.iter().map(|i| (*i).clone()).collect();
|
let instances = instances.iter().map(|i| **i).collect();
|
||||||
let fut = lua.spawn_blocking(move || {
|
let fut = lua.spawn_blocking(move || {
|
||||||
let doc = Document::from_instance_array(instances)?;
|
let doc = Document::from_instance_array(instances)?;
|
||||||
let bytes = doc.to_bytes_with_format(match as_xml {
|
let bytes = doc.to_bytes_with_format(match as_xml {
|
||||||
|
|
|
@ -169,6 +169,7 @@ create_tests! {
|
||||||
roblox_datatype_color3: "roblox/datatypes/Color3",
|
roblox_datatype_color3: "roblox/datatypes/Color3",
|
||||||
roblox_datatype_color_sequence: "roblox/datatypes/ColorSequence",
|
roblox_datatype_color_sequence: "roblox/datatypes/ColorSequence",
|
||||||
roblox_datatype_color_sequence_keypoint: "roblox/datatypes/ColorSequenceKeypoint",
|
roblox_datatype_color_sequence_keypoint: "roblox/datatypes/ColorSequenceKeypoint",
|
||||||
|
roblox_datatype_content: "roblox/datatypes/Content",
|
||||||
roblox_datatype_enum: "roblox/datatypes/Enum",
|
roblox_datatype_enum: "roblox/datatypes/Enum",
|
||||||
roblox_datatype_faces: "roblox/datatypes/Faces",
|
roblox_datatype_faces: "roblox/datatypes/Faces",
|
||||||
roblox_datatype_font: "roblox/datatypes/Font",
|
roblox_datatype_font: "roblox/datatypes/Font",
|
||||||
|
|
62
tests/roblox/datatypes/Content.luau
Normal file
62
tests/roblox/datatypes/Content.luau
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
local roblox = require("@lune/roblox") :: any
|
||||||
|
local Content = roblox.Content
|
||||||
|
local Instance = roblox.Instance
|
||||||
|
local Enum = roblox.Enum
|
||||||
|
|
||||||
|
assert(Content.none, "Content.none did not exist")
|
||||||
|
assert(
|
||||||
|
Content.none.SourceType == Enum.ContentSourceType.None,
|
||||||
|
"Content.none's SourceType was wrong"
|
||||||
|
)
|
||||||
|
assert(Content.none.Uri == nil, "Content.none's Uri field was wrong")
|
||||||
|
assert(Content.none.Object == nil, "Content.none's Object field was wrong")
|
||||||
|
|
||||||
|
local uri = Content.fromUri("test uri")
|
||||||
|
assert(uri.SourceType == Enum.ContentSourceType.Uri, "URI Content's SourceType was wrong")
|
||||||
|
assert(uri.Uri == "test uri", "URI Content's Uri field was wrong")
|
||||||
|
assert(uri.Object == nil, "URI Content's Object field was wrong")
|
||||||
|
|
||||||
|
assert(not pcall(Content.fromUri), "Content.fromUri accepted no argument")
|
||||||
|
assert(not pcall(Content.fromUri, false), "Content.fromUri accepted a boolean argument")
|
||||||
|
assert(not pcall(Content.fromUri, Enum), "Content.fromUri accepted a UserData as an argument")
|
||||||
|
assert(
|
||||||
|
not pcall(Content.fromUri, buffer.create(0)),
|
||||||
|
"Content.fromUri accepted a buffer as an argument"
|
||||||
|
)
|
||||||
|
|
||||||
|
-- It feels weird that this is allowed because `EditableImage` is very much
|
||||||
|
-- not an Instance. But what can you do?
|
||||||
|
local target = Instance.new("EditableImage")
|
||||||
|
local object = Content.fromObject(target)
|
||||||
|
assert(object.SourceType == Enum.ContentSourceType.Object, "Object Content's SourceType was wrong")
|
||||||
|
assert(object.Uri == nil, "Object Content's Uri field was wrong")
|
||||||
|
assert(object.Object == target, "Object Content's Object field was wrong")
|
||||||
|
|
||||||
|
assert(not pcall(Content.fromObject), "Content.fromObject accepted no argument")
|
||||||
|
assert(not pcall(Content.fromObject, false), "Content.fromObject accepted a boolean argument")
|
||||||
|
assert(
|
||||||
|
not pcall(Content.fromObject, Enum),
|
||||||
|
"Content.fromObject accepted a non-Instance/Object UserData as an argument"
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
not pcall(Content.fromObject, buffer.create(0)),
|
||||||
|
"Content.fromObject accepted a buffer as an argument"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert(
|
||||||
|
not pcall(Content.fromObject, Instance.new("Folder")),
|
||||||
|
"Content.fromObject accepted an Instance as an argument"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert(
|
||||||
|
tostring(Content.none) == "Content(None)",
|
||||||
|
`expected tostring(Content.none) to be Content(None), it was actually {Content.none}`
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
tostring(uri) == "Content(Uri=test uri)",
|
||||||
|
`expected tostring(URI Content) to be Content(Uri=...), it was actually {uri}`
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
tostring(object) == "Content(Object)",
|
||||||
|
`expected tostring(Object Content) to be Content(Object), it was actually {object}`
|
||||||
|
)
|
|
@ -16,6 +16,7 @@ local UDim2 = roblox.UDim2
|
||||||
local Vector2 = roblox.Vector2
|
local Vector2 = roblox.Vector2
|
||||||
local Vector3 = roblox.Vector3
|
local Vector3 = roblox.Vector3
|
||||||
local Instance = roblox.Instance
|
local Instance = roblox.Instance
|
||||||
|
local Enum = roblox.Enum
|
||||||
|
|
||||||
local modelFile = fs.readFile("tests/roblox/rbx-test-files/models/attributes/binary.rbxm")
|
local modelFile = fs.readFile("tests/roblox/rbx-test-files/models/attributes/binary.rbxm")
|
||||||
local model = roblox.deserializeModel(modelFile)[1]
|
local model = roblox.deserializeModel(modelFile)[1]
|
||||||
|
@ -114,3 +115,12 @@ model.Parent = game
|
||||||
local placeFile = roblox.serializePlace(game)
|
local placeFile = roblox.serializePlace(game)
|
||||||
fs.writeDir("bin/roblox")
|
fs.writeDir("bin/roblox")
|
||||||
fs.writeFile("bin/roblox/attributes.rbxl", placeFile)
|
fs.writeFile("bin/roblox/attributes.rbxl", placeFile)
|
||||||
|
|
||||||
|
local enum_attr = Instance.new("Folder")
|
||||||
|
enum_attr:SetAttribute("Foo", Enum.NormalId.Front)
|
||||||
|
assert(enum_attr:GetAttribute("Foo") == Enum.NormalId.Front)
|
||||||
|
|
||||||
|
local enum_attr_ser = roblox.serializeModel({ enum_attr })
|
||||||
|
local enum_attr_de = roblox.deserializeModel(enum_attr_ser)
|
||||||
|
|
||||||
|
assert(enum_attr_de[1]:GetAttribute("Foo") == Enum.NormalId.Front)
|
||||||
|
|
|
@ -33,6 +33,16 @@ part.Shape = Enum.PartType.Ball
|
||||||
|
|
||||||
assert(part.Shape == Enum.PartType.Ball)
|
assert(part.Shape == Enum.PartType.Ball)
|
||||||
|
|
||||||
|
-- Enums should roundtrip through serde without problem
|
||||||
|
|
||||||
|
local decal = Instance.new("Decal")
|
||||||
|
decal.Face = Enum.NormalId.Top
|
||||||
|
|
||||||
|
local decal_ser = roblox.serializeModel({ decal })
|
||||||
|
local decal_de = roblox.deserializeModel(decal_ser)
|
||||||
|
|
||||||
|
assert(decal_de[1].Face == Enum.NormalId.Top)
|
||||||
|
|
||||||
-- Properties that don't exist for a class should error
|
-- Properties that don't exist for a class should error
|
||||||
|
|
||||||
local meshPart = Instance.new("MeshPart")
|
local meshPart = Instance.new("MeshPart")
|
||||||
|
|
Loading…
Add table
Reference in a new issue