From cc8f6ec84369e53a6667c6a4d37ae3640ef1324a Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Sat, 18 Mar 2023 08:39:46 +0100 Subject: [PATCH] Improve codegen of Font roblox datatype enums some more --- .../lib-roblox/scripts/font_enum_map.luau | 82 +++++-- .../lib-roblox/src/datatypes/types/font.rs | 205 +++++++++++++----- 2 files changed, 215 insertions(+), 72 deletions(-) diff --git a/packages/lib-roblox/scripts/font_enum_map.luau b/packages/lib-roblox/scripts/font_enum_map.luau index eff5d16..da9a0cd 100644 --- a/packages/lib-roblox/scripts/font_enum_map.luau +++ b/packages/lib-roblox/scripts/font_enum_map.luau @@ -12,13 +12,13 @@ pub(crate) enum <> { } impl <> { - pub fn as_<>(&self) -> <> { + pub(crate) fn as_<>(&self) -> <> { match self { <> } } - pub fn from_<>(n: <>) -> Option { + pub(crate) fn from_<>(n: <>) -> Option { match n { <> _ => None, @@ -26,25 +26,73 @@ impl <> { } } +impl Default for <> { + fn default() -> Self { + Self::<> + } +} + impl std::str::FromStr for <> { - type Err = &'static str; - fn from_str(s: &str) -> Result { - match s { + type Err = &'static str; + fn from_str(s: &str) -> Result { + match s { <> - _ => Err("Unknown <>"), - } - } + _ => Err("Unknown <>"), + } + } } impl std::fmt::Display for <> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( f, "{}", match self { <> } ) + } +} + +impl<'lua> FromLua<'lua> for <> { + fn from_lua(lua_value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult { + let mut message = None; + if let LuaValue::UserData(ud) = &lua_value { + let value = ud.borrow::()?; + if value.parent.desc.name == "<>" { + if let Ok(value) = <>::from_str(&value.name) { + return Ok(value); + } else { + message = Some(format!( + "Found unknown Enum.<> value '{}'", + value.name + )); + } + } else { + message = Some(format!( + "Expected Enum.<>, got Enum.{}", + value.parent.desc.name + )); + } + } + Err(LuaError::FromLuaConversionError { + from: lua_value.type_name(), + to: "Enum.<>", + message, + }) + } +} + +impl<'lua> ToLua<'lua> for <> { + fn to_lua(self, lua: &'lua Lua) -> LuaResult> { + match EnumItem::from_enum_name_and_name("<>", self.to_string()) { + Some(enum_item) => Ok(LuaValue::UserData(lua.create_userdata(enum_item)?)), + None => Err(LuaError::ToLuaConversionError { + from: "<>", + to: "EnumItem", + message: Some(format!("Found unknown Enum.<> value '{}'", self)), + }), + } } } @@ -52,8 +100,13 @@ impl std::fmt::Display for <> { -- FontWeight enum and implementation -local function makeRustEnum(enum, numType: string) - local name = string.gsub(tostring(enum), "^Enum.", "") +local function makeRustEnum(enum, default, numType: string) + local name = tostring(enum) + name = string.gsub(name, "^Enum.", "") + + local defaultName = tostring(default) + defaultName = string.gsub(defaultName, "^Enum.", "") + defaultName = string.gsub(defaultName, "^" .. name .. ".", "") local enumNames = "" local enumToNumbers = "" @@ -71,6 +124,7 @@ local function makeRustEnum(enum, numType: string) local mappings: { [string]: string } = { ["<>"] = name, + ["<>"] = defaultName, ["<>"] = numType, ["<>"] = enumNames, ["<>"] = enumToNumbers, @@ -91,10 +145,10 @@ local function makeRustEnum(enum, numType: string) return result end -contents ..= makeRustEnum(Enum.FontWeight, "u16") +contents ..= makeRustEnum(Enum.FontWeight, Enum.FontWeight.Regular, "u16") contents ..= "\n" -contents ..= makeRustEnum(Enum.FontStyle, "u8") +contents ..= makeRustEnum(Enum.FontStyle, Enum.FontStyle.Normal, "u8") contents ..= "\n" -- Font constant map from enum to font data diff --git a/packages/lib-roblox/src/datatypes/types/font.rs b/packages/lib-roblox/src/datatypes/types/font.rs index c6052a7..07d8e99 100644 --- a/packages/lib-roblox/src/datatypes/types/font.rs +++ b/packages/lib-roblox/src/datatypes/types/font.rs @@ -21,7 +21,7 @@ pub struct Font { } impl Font { - pub(crate) fn from_enum(material_enum_item: &EnumItem) -> Option { + pub(crate) fn from_enum_item(material_enum_item: &EnumItem) -> Option { FONT_ENUM_MAP .iter() .find(|props| props.0 == material_enum_item.name && props.1.is_some()) @@ -34,11 +34,23 @@ impl Font { } pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> { + datatype_table.set( + "new", + lua.create_function( + |_, (family, weight, style): (String, Option, Option)| { + Ok(Font { + family, + weight: weight.unwrap_or_default(), + style: style.unwrap_or_default(), + }) + }, + )?, + )?; datatype_table.set( "fromEnum", lua.create_function(|_, value: EnumItem| { if value.parent.desc.name == "Font" { - match Font::from_enum(&value) { + match Font::from_enum_item(&value) { Some(props) => Ok(props), None => Err(LuaError::RuntimeError(format!( "Found unknown Font '{}'", @@ -53,9 +65,30 @@ impl Font { } })?, )?; - // TODO: Add fromName and fromId constructors - // TODO: Add "new" constructor - Ok(()) + datatype_table.set( + "fromName", + lua.create_function( + |_, (file, weight, style): (String, Option, Option)| { + Ok(Font { + family: format!("rbxasset://fonts/families/{}.json", file), + weight: weight.unwrap_or_default(), + style: style.unwrap_or_default(), + }) + }, + )?, + )?; + datatype_table.set( + "fromId", + lua.create_function( + |_, (id, weight, style): (i32, Option, Option)| { + Ok(Font { + family: format!("rbxassetid://{}", id), + weight: weight.unwrap_or_default(), + style: style.unwrap_or_default(), + }) + }, + )?, + ) } } @@ -63,57 +96,17 @@ impl LuaUserData for Font { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { // Getters fields.add_field_method_get("Family", |_, this| Ok(this.family.clone())); - fields.add_field_method_get("Weight", |_, this| { - Ok(EnumItem::from_enum_name_and_name( - "FontWeight", - this.weight.to_string(), - )) - }); - fields.add_field_method_get("Style", |_, this| { - Ok(EnumItem::from_enum_name_and_name( - "FontStyle", - this.style.to_string(), - )) - }); - fields.add_field_method_get("Bold", |_, this| Ok(this.weight.clone().as_u16() >= 600)); + fields.add_field_method_get("Weight", |_, this| Ok(this.weight)); + fields.add_field_method_get("Style", |_, this| Ok(this.style)); + fields.add_field_method_get("Bold", |_, this| Ok(this.weight.as_u16() >= 600)); // Setters - fields.add_field_method_set("Weight", |_, this, value: EnumItem| { - if value.parent.desc.name == "FontWeight" { - match FontWeight::from_str(&value.name) { - Ok(weight) => { - this.weight = weight; - Ok(()) - } - Err(e) => Err(LuaError::RuntimeError(format!( - "Failed to set value to FontWeight '{}' - {}", - value.name, e - ))), - } - } else { - Err(LuaError::RuntimeError(format!( - "Expected value to be a FontWeight, got {}", - value.parent.desc.name - ))) - } + fields.add_field_method_set("Weight", |_, this, value: FontWeight| { + this.weight = value; + Ok(()) }); - fields.add_field_method_set("Style", |_, this, value: EnumItem| { - if value.parent.desc.name == "FontStyle" { - match FontStyle::from_str(&value.name) { - Ok(style) => { - this.style = style; - Ok(()) - } - Err(e) => Err(LuaError::RuntimeError(format!( - "Failed to set value to FontStyle '{}' - {}", - value.name, e - ))), - } - } else { - Err(LuaError::RuntimeError(format!( - "Expected value to be a FontStyle, got {}", - value.parent.desc.name - ))) - } + fields.add_field_method_set("Style", |_, this, value: FontStyle| { + this.style = value; + Ok(()) }); fields.add_field_method_set("Bold", |_, this, value: bool| { if value { @@ -206,7 +199,7 @@ pub(crate) enum FontWeight { } impl FontWeight { - pub fn as_u16(&self) -> u16 { + pub(crate) fn as_u16(&self) -> u16 { match self { Self::Thin => 100, Self::ExtraLight => 200, @@ -220,7 +213,7 @@ impl FontWeight { } } - pub fn from_u16(n: u16) -> Option { + pub(crate) fn from_u16(n: u16) -> Option { match n { 100 => Some(Self::Thin), 200 => Some(Self::ExtraLight), @@ -236,6 +229,12 @@ impl FontWeight { } } +impl Default for FontWeight { + fn default() -> Self { + Self::Regular + } +} + impl std::str::FromStr for FontWeight { type Err = &'static str; fn from_str(s: &str) -> Result { @@ -274,6 +273,48 @@ impl std::fmt::Display for FontWeight { } } +impl<'lua> FromLua<'lua> for FontWeight { + fn from_lua(lua_value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult { + let mut message = None; + if let LuaValue::UserData(ud) = &lua_value { + let value = ud.borrow::()?; + if value.parent.desc.name == "FontWeight" { + if let Ok(value) = FontWeight::from_str(&value.name) { + return Ok(value); + } else { + message = Some(format!( + "Found unknown Enum.FontWeight value '{}'", + value.name + )); + } + } else { + message = Some(format!( + "Expected Enum.FontWeight, got Enum.{}", + value.parent.desc.name + )); + } + } + Err(LuaError::FromLuaConversionError { + from: lua_value.type_name(), + to: "Enum.FontWeight", + message, + }) + } +} + +impl<'lua> ToLua<'lua> for FontWeight { + fn to_lua(self, lua: &'lua Lua) -> LuaResult> { + match EnumItem::from_enum_name_and_name("FontWeight", self.to_string()) { + Some(enum_item) => Ok(LuaValue::UserData(lua.create_userdata(enum_item)?)), + None => Err(LuaError::ToLuaConversionError { + from: "FontWeight", + to: "EnumItem", + message: Some(format!("Found unknown Enum.FontWeight value '{}'", self)), + }), + } + } +} + #[derive(Debug, Clone, Copy, PartialEq)] pub(crate) enum FontStyle { Normal, @@ -281,14 +322,14 @@ pub(crate) enum FontStyle { } impl FontStyle { - pub fn as_u8(&self) -> u8 { + pub(crate) fn as_u8(&self) -> u8 { match self { Self::Normal => 0, Self::Italic => 1, } } - pub fn from_u8(n: u8) -> Option { + pub(crate) fn from_u8(n: u8) -> Option { match n { 0 => Some(Self::Normal), 1 => Some(Self::Italic), @@ -297,6 +338,12 @@ impl FontStyle { } } +impl Default for FontStyle { + fn default() -> Self { + Self::Normal + } +} + impl std::str::FromStr for FontStyle { type Err = &'static str; fn from_str(s: &str) -> Result { @@ -321,6 +368,48 @@ impl std::fmt::Display for FontStyle { } } +impl<'lua> FromLua<'lua> for FontStyle { + fn from_lua(lua_value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult { + let mut message = None; + if let LuaValue::UserData(ud) = &lua_value { + let value = ud.borrow::()?; + if value.parent.desc.name == "FontStyle" { + if let Ok(value) = FontStyle::from_str(&value.name) { + return Ok(value); + } else { + message = Some(format!( + "Found unknown Enum.FontStyle value '{}'", + value.name + )); + } + } else { + message = Some(format!( + "Expected Enum.FontStyle, got Enum.{}", + value.parent.desc.name + )); + } + } + Err(LuaError::FromLuaConversionError { + from: lua_value.type_name(), + to: "Enum.FontStyle", + message, + }) + } +} + +impl<'lua> ToLua<'lua> for FontStyle { + fn to_lua(self, lua: &'lua Lua) -> LuaResult> { + match EnumItem::from_enum_name_and_name("FontStyle", self.to_string()) { + Some(enum_item) => Ok(LuaValue::UserData(lua.create_userdata(enum_item)?)), + None => Err(LuaError::ToLuaConversionError { + from: "FontStyle", + to: "EnumItem", + message: Some(format!("Found unknown Enum.FontStyle value '{}'", self)), + }), + } + } +} + #[rustfmt::skip] const FONT_ENUM_MAP: &[(&str, Option)] = &[ ("Legacy", Some(("rbxasset://fonts/families/LegacyArial.json", FontWeight::Regular, FontStyle::Normal))),