Add in restrictions for roblox attribute names

This commit is contained in:
Filip Tibell 2023-03-25 11:00:22 +01:00
parent 22ab18026b
commit 25f46c10a8
No known key found for this signature in database
4 changed files with 74 additions and 36 deletions

View file

@ -0,0 +1,56 @@
use mlua::prelude::*;
use rbx_dom_weak::types::{Variant as DomValue, VariantType as DomType};
use super::extension::DomValueExt;
pub fn ensure_valid_attribute_name(name: impl AsRef<str>) -> LuaResult<()> {
let name = name.as_ref();
if name.to_ascii_uppercase().starts_with("RBX") {
Err(LuaError::RuntimeError(
"Attribute names must not start with the prefix \"RBX\"".to_string(),
))
} else if !name.chars().all(|c| c == '_' || c.is_alphanumeric()) {
Err(LuaError::RuntimeError(
"Attribute names must only use alphanumeric characters and underscore".to_string(),
))
} else if name.len() > 100 {
Err(LuaError::RuntimeError(
"Attribute names must be 100 characters or less in length".to_string(),
))
} else {
Ok(())
}
}
pub fn ensure_valid_attribute_value(value: &DomValue) -> LuaResult<()> {
let is_valid = matches!(
value.ty(),
DomType::Bool
| DomType::BrickColor
| DomType::CFrame
| DomType::Color3
| DomType::ColorSequence
| DomType::Float32
| DomType::Float64
| DomType::Int32
| DomType::Int64
| DomType::NumberRange
| DomType::NumberSequence
| DomType::Rect
| DomType::String
| DomType::UDim
| DomType::UDim2
| DomType::Vector2
| DomType::Vector3
| DomType::Font
);
if is_valid {
Ok(())
} else {
Err(LuaError::RuntimeError(format!(
"'{}' is not a valid attribute type",
value.ty().variant_name()
)))
}
}

View file

@ -1,6 +1,6 @@
use super::*; use super::*;
pub(crate) trait DomValueExt { pub(super) trait DomValueExt {
fn variant_name(&self) -> &'static str; fn variant_name(&self) -> &'static str;
} }

View file

@ -1,5 +1,6 @@
pub(crate) use rbx_dom_weak::types::{Variant as DomValue, VariantType as DomType}; pub(crate) use rbx_dom_weak::types::{Variant as DomValue, VariantType as DomType};
pub mod attributes;
pub mod conversion; pub mod conversion;
pub mod extension; pub mod extension;
pub mod result; pub mod result;

View file

@ -6,14 +6,14 @@ use std::{
use mlua::prelude::*; use mlua::prelude::*;
use rbx_dom_weak::{ use rbx_dom_weak::{
types::{Ref as DomRef, Variant as DomValue, VariantType as DomType}, types::{Ref as DomRef, Variant as DomValue},
Instance as DomInstance, InstanceBuilder as DomInstanceBuilder, WeakDom, Instance as DomInstance, InstanceBuilder as DomInstanceBuilder, WeakDom,
}; };
use crate::{ use crate::{
datatypes::{ datatypes::{
attributes::{ensure_valid_attribute_name, ensure_valid_attribute_value},
conversion::{DomValueToLua, LuaToDomValue}, conversion::{DomValueToLua, LuaToDomValue},
extension::DomValueExt,
types::EnumItem, types::EnumItem,
userdata_impl_eq, userdata_impl_to_string, userdata_impl_eq, userdata_impl_to_string,
}, },
@ -400,40 +400,12 @@ impl Instance {
.insert(name.as_ref().to_string(), value); .insert(name.as_ref().to_string(), value);
} }
fn ensure_valid_attribute_value(&self, value: &DomValue) -> LuaResult<()> {
let is_valid = matches!(
value.ty(),
DomType::Bool
| DomType::BrickColor
| DomType::CFrame
| DomType::Color3
| DomType::ColorSequence
| DomType::Float32
| DomType::Float64
| DomType::Int32
| DomType::Int64
| DomType::NumberRange
| DomType::NumberSequence
| DomType::Rect
| DomType::String
| DomType::UDim
| DomType::UDim2
| DomType::Vector2
| DomType::Vector3
| DomType::Font
);
if is_valid {
Ok(())
} else {
Err(LuaError::RuntimeError(format!(
"'{}' is not a valid attribute type",
value.ty().variant_name()
)))
}
}
/** /**
Gets an attribute for the instance, if it exists. Gets an attribute for the instance, if it exists.
### See Also
* [`GetAttribute`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetAttribute)
on the Roblox Developer Hub
*/ */
pub fn get_attribute(&self, name: impl AsRef<str>) -> Option<DomValue> { pub fn get_attribute(&self, name: impl AsRef<str>) -> Option<DomValue> {
let dom = INTERNAL_DOM let dom = INTERNAL_DOM
@ -451,6 +423,10 @@ impl Instance {
/** /**
Gets all known attributes for the instance. Gets all known attributes for the instance.
### See Also
* [`GetAttributes`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetAttributes)
on the Roblox Developer Hub
*/ */
pub fn get_attributes(&self) -> BTreeMap<String, DomValue> { pub fn get_attributes(&self) -> BTreeMap<String, DomValue> {
let dom = INTERNAL_DOM let dom = INTERNAL_DOM
@ -468,6 +444,10 @@ impl Instance {
/** /**
Sets an attribute for the instance. Sets an attribute for the instance.
### See Also
* [`SetAttribute`](https://create.roblox.com/docs/reference/engine/classes/Instance#SetAttribute)
on the Roblox Developer Hub
*/ */
pub fn set_attribute(&self, name: impl AsRef<str>, value: DomValue) { pub fn set_attribute(&self, name: impl AsRef<str>, value: DomValue) {
let mut dom = INTERNAL_DOM let mut dom = INTERNAL_DOM
@ -968,9 +948,10 @@ impl LuaUserData for Instance {
"SetAttribute", "SetAttribute",
|lua, this, (attribute_name, lua_value): (String, LuaValue)| { |lua, this, (attribute_name, lua_value): (String, LuaValue)| {
this.ensure_not_destroyed()?; this.ensure_not_destroyed()?;
ensure_valid_attribute_name(&attribute_name)?;
match lua_value.lua_to_dom_value(lua, None) { match lua_value.lua_to_dom_value(lua, None) {
Ok(dom_value) => { Ok(dom_value) => {
this.ensure_valid_attribute_value(&dom_value)?; ensure_valid_attribute_value(&dom_value)?;
this.set_attribute(attribute_name, dom_value); this.set_attribute(attribute_name, dom_value);
Ok(()) Ok(())
} }